转自:https://blog.csdn.net/Revivedsun/article/details/81785000
原文链接:https://intoli.com/blog/not-possible-to-block-chrome-headless/
本文测试使用的chrome版本为 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3514.2 Safari/537.36
无头模式下的UA会带有HeadlessChrome关键字
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/70.0.3521.2 Safari/537.36因此可以检查UA中的关键字
if (/HeadlessChrome/.test(navigator.userAgent)) { // headless... }无头模式下navigator.webdriver为true,因此可以进行如下检测。
// Webdriver Test if (navigator.webdriver) { // headless... }为了绕过这个检测,重新设置该属性即可。
Object.defineProperty(navigator, 'webdriver', { get: () => false, });补充说明:大麦网或淘宝网的滑块验证码首先就会检测环境, 通常会利用sufei_data文件检测当前浏览器信息,其中检测webdriver代码如下
function r() { return "$cdc_asdjflasutopfhvcZLmcfl_"in u || f.webdriver } // 完整的检测代码,这个文件会经常升级 // https://g.alicdn.com/secdev/sufei_data/3.6.8/index.js因此在尝试拖动滑块的时候,先要修改该属性。不然如何修改路径都会提示错误,并要求重试。
在无头模式下window.chrome属性是undefined,而在正常有界面模式下,定义如下。
csi: ƒ () embeddedSearch: {searchBox: {…}, newTabPage: {…}} loadTimes: ƒ () app: (...) runtime: (...) webstore: (...) get app: ƒ nativeGetter() set app: ƒ nativeSetter() get runtime: ƒ nativeGetter() set runtime: ƒ nativeSetter() get webstore: ƒ nativeGetter() set webstore: ƒ nativeSetter(因此可以进行如下形式检测
if (!window.chrome || !window.chrome.runtime) { // headless... }绕过检测修改属性即可
window.navigator.chrome = { runtime: {}, // etc. };无头模式下Notification.permission与navigator.permissions.query会返回相反的值。 因此绕过的方式如下。
// Pass the Permissions Test. await page.evaluateOnNewDocument(() => { const originalQuery = window.navigator.permissions.query; return window.navigator.permissions.query = (parameters) => ( parameters.name === 'notifications' ? Promise.resolve({ state: Notification.permission }) : originalQuery(parameters) ); });无头模式下navigator.plugins.length返回0
if (navigator.plugins.length === 0) { // headless }绕过方式如下
Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5], });注意:反爬除了检查长度,还会检查内容。如果你设置了长度,别忘了再设置内容。防止被反爬。
navigator.languages检测方法
if (!navigator.languages || navigator.languages.length === 0) { // headless }绕过方法
Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'], });