首先,一切使用自动化框架的项目,或者说代码,或者说爬虫都会碰到某些网站刚刚打开页面就被判定为:非人类行为。为啥??


----------因为很多网站有对selenium的js监测机制。比如:navigator.webdriver,navigator.languages,navigator.plugins.length......很多很多。

   比如美团,大众,淘宝这些'无良'商家。。就有对window.navigator.webdriver的检测机制。正常情况下---->

window.navigator.webdriver的值为undefined。

而当我们使用selenium 的时候---->



window.navigator.webdriver的值为True。

 


-------------------------------------------------------------------------------------------------------------------------------------------------------------------------


主要说下破解的两种办法。第一张使用mitmproxy用中间人的方式截取服务器发送来的js,修改js里面函数的参值方式发送给服务器。相当于在browser和server之间做一层中介的拦截。不过此方法要对js非常熟悉的人才好实施。

第二种方法依旧通过selenium,不过是在服务器在第一次发送js并在本地验证的时候,做好‘第一次’的伪装,从而实现‘第一次登陆’有效。。方法简单,适合小白。

我们用第二种方式来实现淘宝的登陆吧------------------>
pyppeteer 加 asyncio
绕过selenium检测,实现鼠标滑动后自动登陆(代码很简单。主要熟悉异步模块及pyppeteer模块。pyppeteer模块看不懂就去看puppeteer文档,pyppeteer只是在puppeteer之上稍微包装了下而已
)。
1.main_py 文件作为主要运行的py:
import asyncio import time from pyppeteer.launcher import launch from alifunc
import mouse_slide, input_time_random from exe_js import js1, js3, js4, js5
async def main(username, pwd, url): browser = await launch({'headless': False,
'args': ['--no-sandbox'], }) page = await browser.newPage() await
page.setUserAgent( 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Edge/16.16299') await page.goto(url) await page.evaluate(js1) await
page.evaluate(js3) await page.evaluate(js4) await page.evaluate(js5) await
page.type('.J_UserName', username, {'delay': input_time_random() - 50}) await
page.type('#J_StandardPwd input', pwd, {'delay': input_time_random()}) await
page.screenshot({'path': './headless-test-result.png'}) time.sleep(2) slider =
await page.Jeval('#nocaptcha', 'node => node.style') # 是否有滑块 if slider:
print('出现滑块情况判定') await page.screenshot({'path': './headless-login-slide.png'})
flag = await mouse_slide(page=page) if flag: await get_cookie(page) else: await
page.keyboard.press('Enter') await page.waitFor(20) await
page.waitForNavigation() try: global error error = await page.Jeval('.error',
'node => node.textContent') except Exception as e: error = None finally: if
error: print('确保账户安全重新入输入') # 程序退出。 loop.close() else: print(page.url) await
get_cookie(page) # 获取登录后cookie async def get_cookie(page): res = await
page.content() cookies_list = await page.cookies() cookies = '' for cookie in
cookies_list: str_cookie = '{0}={1};' str_cookie =
str_cookie.format(cookie.get('name'), cookie.get('value')) cookies +=
str_cookie print(cookies) return cookies if __name__ == '__main__': username =
'xxxxxxxxxxxxx' pwd = 'xxxxxxx' url =
'https://login.taobao.com/member/login.jhtml?style=mini&css_style=b2b&from=b2b&full_redirect=true&redirect_url=https://login.1688.com/member/jump.htm?target=https://login.1688.com/member/marketSigninJump.htm?Done=http://login.1688.com/member/taobaoSellerLoginDispatch.htm®=
http://member.1688.com/member/join/enterprise_join.htm?lead=http://login.1688.com/member/taobaoSellerLoginDispatch.htm&leadUrl=http://login.1688.com/member/'
loop = asyncio.get_event_loop() loop.run_until_complete(main(username, pwd,
url))
2 exe_js 需要伪装js数据的py文件,alifunc出现滑块情况下进行鼠标移动的py文件。
# alifunc.py from retrying import retry import time, asyncio, random def
retry_if_result_none(result): return result is None
@retry(retry_on_result=retry_if_result_none,) async def mouse_slide(page=None):
await asyncio.sleep(3) try: await page.hover('#nc_1_n1z') await
page.mouse.down() await page.mouse.move(2000, 0, {'delay': random.randint(1000,
2000)}) await page.mouse.up() except Exception as e: print(e, ' :slide login
False') return None else: await asyncio.sleep(3) slider_again = await
page.Jeval('.nc-lang-cnt', 'node => node.textContent') if slider_again !=
'验证通过': return None else: await page.screenshot({'path':
'./headless-slide-result.png'}) print('验证通过') return 1 def input_time_random():
return random.randint(100, 151)
 
# exe_js.py js1 = '''() =>{ Object.defineProperties(navigator,{ webdriver:{
get: () => false } }) }''' js2 = '''() => { alert ( window.navigator.webdriver
) }''' js3 = '''() => { window.navigator.chrome = { runtime: {}, // etc. };
}''' js4 = '''() =>{ Object.defineProperty(navigator, 'languages', { get: () =>
['en-US', 'en'] }); }''' js5 = '''() =>{ Object.defineProperty(navigator,
'plugins', { get: () => [1, 2, 3, 4, 5,6], }); }'''
---------------------------------------------------------------------

运行结果





 

代码下载地址:

https://github.com/chenchong6/taobao-login
<https://github.com/chenchong6/taobao-login>

puppeteer文档地址:

https://zhaoqize.github.io/puppeteer-api-zh_CN/#/?id=%E6%A6%82%E8%BF%B0
<https://zhaoqize.github.io/puppeteer-api-zh_CN/#/?id=%E6%A6%82%E8%BF%B0>

async/await 速看:

https://python.freelycode.com/contribution/detail/57
<https://python.freelycode.com/contribution/detail/57>

pyppeteer地址:

https://github.com/miyakogi/pyppeteer <https://github.com/miyakogi/pyppeteer>