目前網上的反檢測方法幾乎都是掩耳盜鈴,因為模擬瀏覽器有幾十個特征可以被檢測,僅僅隱藏 webdriver 這一個值是沒有任何意義的。
今天我們就來說說應該如何正確解決這個問題。我們首先給出解決方案。然后再說明這個解決方案,我是通過什么方式找到的。
解決這個問題的關鍵,就是一個 js 文件,叫做stealth.min.js
。
我們需要設定,讓 Selenium 或者 Pyppeteer 在打開任何頁面之前,先運行這個 Js 文件。
Selenium 代碼如下:
import time from selenium.webdriver import Chrome from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument("--headless") chrome_options.add_argument('user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36') driver = Chrome('./chromedriver', options=chrome_options) with open('./stealth.min.js') as f: js = f.read() driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", { "source": js }) driver.get('https://bot.sannysoft.com/') time.sleep(5) driver.save_screenshot('screenshoot.png') # 你可以保存源代碼為 html 再雙擊打開,查看完整結果 source = driver.page_source with open('result.html', 'w') as f: f.write(source)
Pyppeteer 代碼如下:
import asyncio from pyppeteer import launch async def main(): browser = await launch(headless=False, ignoreDefaultArgs=['--enable-automation'], executablePath=r'C:\\Users\\admin\\AppData\\Local\\pyppeteer\\pyppeteer\\local-chromium\\588429\\chrome-win32\\chrome.exe') # 關閉無頭瀏覽器 # page = await browser.newPage() page = await browser.newPage() await page.addScriptTag(path='./stealth.min.js') await page.goto('https://bot.sannysoft.com/') # 跳轉 # content = await page.evaluate('document.body.textContent', force_expr=True) # print(content) await page.screenshot({'path': 'screenshot.png'}) # 截圖 await browser.close() # 關閉 asyncio.get_event_loop().run_until_complete(main())
最后檢測的結果如下
那么,這個stealth.min.js
文件是怎么來的呢?這就要說到puppeteer
了。我們知道,Python 版本的pyppeteer
已經很久沒有人維護了,但是Node.js 版本的 puppeteer
持續有人維護,並且在持續更新,生態也越來越好。
有開發者給 puppeteer 寫了一套插件,叫做puppeteer-extra
。其中,就有一個插件叫做puppeteer-extra-plugin-stealth[1]。這個東西,就來專門用來讓 puppeteer 隱藏模擬瀏覽器的指紋特征。
這個東西是專門給 puppeteer 用的。所以,如果你使用的是 puppeteer,那么你可以根據它的 Readme說明,直接使用。
那么,我們用 Python 的人怎么辦呢?實際上也有辦法。就是把其中的隱藏特征的腳本提取出來,做成一個單獨的 js 文件。然后讓 Selenium 或者 Pyppeteer 在打開任意網頁之前,先運行一下這個 js 文件里面的內容。
puppeteer-extra-plugin-stealth的作者還寫了另外一個工具,叫做extract-stealth-evasions[2]。這個東西就是用來生成stealth.min.js
文件的。
如果你在國外(或者有梯子),並且網速足夠快的話。那么你根據它的 Readme,首先安裝 Node.js,然后安裝 Npm,接着運行如下命令:
npx extract-stealth-evasions
就會在你執行命令的文件夾下面生成一個stealth.min.js
文件。然后你就可以正常使用了。
如果你在國內,那么執行這個命令的過程中,會有一個下載 Chromium 的過程,速度非常慢,雖然只有130MB,但是可能會下載好幾個小時。
此時,你需要把它的package.json
和index.js
兩個文件保存到本地。然后打開package.json
文件,修改其中的dependencies
這一項,把里面的puppeteer
改成puppeteer-core
,如下圖所示:
然后修改index.js
,給.launch()
函數增加一個參數executablePath
,指向你電腦上的 Chrome 瀏覽器,如下圖所示:
修改完成以后。首先執行yarn install
安裝依賴包。然后執行node index.js
運行程序。1秒鍾以后就會生成stealth.min.js
了
參考:[1] puppeteer-extra-plugin-stealth: https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth
[2] extract-stealth-evasions: https://github.com/berstend/puppeteer-extra/tree/master/packages/extract-stealth-evasions