? ? 首先,一切使用自動化框架的項目,或者說代碼,或者說爬蟲都會碰到某些網(wǎng)站剛剛打開頁面就被判定為:非人類行為。為啥??
----------因為很多網(wǎng)站有對selenium的js監(jiān)測機制。比如:navigator.webdriver,navigator.languages,navigator.plugins.length......很多很多。
比如美團,大眾,淘寶這些'無良'商家。。就有對window.navigator.webdriver的檢測機制。正常情況下---->?
window.navigator.webdriver的值為undefined。
而當我們使用selenium 的時候---->
?
window.navigator.webdriver的值為True。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
主要說下破解的兩種辦法。第一張使用mitmproxy用中間人的方式截取服務器發(fā)送來的js,修改js里面函數(shù)的參值方式發(fā)送給服務器。相當于在browser和server之間做一層中介的攔截。不過此方法要對js非常熟悉的人才好實施。
第二種方法依舊通過selenium,不過是在服務器在第一次發(fā)送js并在本地驗證的時候,做好‘第一次’的偽裝,從而實現(xiàn)‘第一次登陸’有效。。方法簡單,適合小白。
我們用第二種方式來實現(xiàn)淘寶的登陸吧------------------>
pyppeteer 加 asyncio 繞過selenium檢測,實現(xiàn)鼠標滑動后自動登陸(代碼很簡單。主要熟悉異步模塊及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('出現(xiàn)滑塊情況判定')
? ? ? ? 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數(shù)據(jù)的py文件,alifunc出現(xiàn)滑塊情況下進行鼠標移動的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],
? });
? ? ? ? }'''
---------------------------------------------------------------------
運行結(jié)果
?
?
代碼下載地址:
https://github.com/chenchong6/taobao-login
puppeteer文檔地址:
https://zhaoqize.github.io/puppeteer-api-zh_CN/#/?id=%E6%A6%82%E8%BF%B0
async/await 速看:
https://python.freelycode.com/contribution/detail/57
pyppeteer地址: