防止 Selenium 被检测

在众多文章中的反检测方法都是隐藏 webdriver 这一值,这种可以说是掩耳盗铃,因为模拟浏览器有几十个特征可以被检测,只隐藏 webdriver 这一项是远远不够的。

先不做任何措施访问检测页面,得到的结果如下所示。

no

解决这个问题的关键就是一个 js 文件,叫做 stealth.min.js。稍后会说明如何生成这个文件。

我们需要让 Selenium 打开任何页面之前,先运行这个 js 文件。

示例代码如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36')

driver = Chrome(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('result.png')

经过处理后再次访问检测页面,得到的结果如下所示。

stealth
自己用真机 chrome 浏览器访问检测页面,得到的结果如下所示。

real

那么,这个 stealth.min.js 文件是怎么来的呢?这就要说到 puppeteer 了。
有一个插件叫做 puppeteer-extra-plugin-stealth。这个用来让 puppeteer 隐藏模拟浏览器的指纹特征。

puppeteer-extra-plugin-stealth 的作者还写了另外一个工具,叫做 extract-stealth-evasions。这个就是用来生成stealth.min.js 文件的。

首先安装 node.js,下载extract-stealth-evasion

然后安装依赖,运行就可以了。

1
2
npm install
node inedx.js

运行完后就可以在同目录下找到 stealth.min.js 文件。

报错解决方案:

在使用运行过程中可能会出现以下错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/root/puppeteer-extra/packages/extract-stealth-evasions/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:229
reject(new Error([
^

Error: Failed to launch the browser process!
[0107/143903.053441:ERROR:zygote_host_impl_linux.cc(90)] Running as root without --no-sandbox is not supported. See https://crbug.com/638180.


TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md

at onClose (/root/puppeteer-extra/packages/extract-stealth-evasions/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:229:20)
at Interface.<anonymous> (/root/puppeteer-extra/packages/extract-stealth-evasions/node_modules/puppeteer-core/lib/cjs/puppeteer/node/BrowserRunner.js:219:68)
at Interface.emit (node:events:402:35)
at Interface.close (node:readline:586:8)
at Socket.onend (node:readline:277:10)
at Socket.emit (node:events:402:35)
at endReadableNT (node:internal/streams/readable:1343:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)

这个时候就需要修改 index.js 文件了,在 launch 里增加一些参数就行了。

1
2
3
4
5
6
puppeteer
.use(stealth)
.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
})