Article / 文章中心

使用chromedriver.exe时如何避免网站检测到模拟器

发布时间:2022-06-27 点击数:3702

你已经可以编写selenium程序爬一个没有验证码的网页,但现在碰到了一个拖动验证码:https://cf.aliyun.com/nocaptcha

 

总结

经过搜索、尝试、再搜索、再尝试…,终于发现需要使用两项技术对selenium进行反爬:

webdriver属性
特征$cdc_asdjflasutopfhvcZLmcfl_
通过js脚本提取webdriver属性和特征$cdc_asdjflasutopfhvcZLmcfl_,将提取结果进行编码后发送给服务器。服务器发现是selenium爬虫后,拒绝验证。

知道了反爬,则反反爬也就好办了。逐项针对规避即可。
有大神已经将步骤整理:https://blog.csdn.net/sdzhr/article/details/86714328
下面解惑一下:

webdriver属性

Chrome从v63版本开始添加了webdriver属性。只要通过selenium调用了浏览器便会将这个属性设置为true。
当服务器通过js脚本识别到webdriver属性时,会有如下现象:

手工启动chrome,人工拖动验证码可以通过验证。
使用selenium启动chrome,人工拖动验证码无法通过验证。
使用selenium启动chrome,程序模拟拖动验证码无法通过验证。
所以,避开webdriver属性需要使用低于v63版本的Chrome(v62.0.3202.94版本测试通过)。

注:

参考文章中提到的chrome 62.0.3202.62版本,未找到下载链接。
chrome和chromedriver之间是有对应关系的,版本不匹配则无法使用。chrome和chromedriver之间的对应关系。
换用Firefox,也会有webdriver属性。
在浏览器的console控制台中输入navigator回车后,在输出中会发现webdriver属性,且值为true。
特征$cdc_asdjflasutopfhvcZLmcfl_

$cdc_asdjflasutopfhvcZLmcfl_是chromeDriver的特征之一。

chromeDriver会创建cdc_asdjflasutopfhvcZLmcfl_元素,并将该元素用于各种操作。比如,在使用findElement方法时,会使用该元素。
当服务器通过js脚本识别到特征“$cdc_asdjflasutopfhvcZLmcfl_”时,会有如下现象:

手工启动chrome,人工拖动验证码可以通过验证。
使用selenium启动chrome,人工拖动验证码可以通过验证。
使用selenium启动chrome,程序模拟拖动验证码无法通过验证。(原因即为上面所述)
避开webdriver属性需要修改chromeDriver中的特征$cdc_asdjflasutopfhvcZLmcfl_。修改方法:

通过文本编辑器打开chromedriver。linux下,通过vim chromedriver打开。windows下,通过notepad++打开chromedriver.exe。
查找特征"cdc_",改为"chr_"。(删掉几个字符,则加几个字符。不能改变var key = '$cdc_asdjflasutopfhvcZLmcfl_';key字符串的长度。否则,会导致chromedriver程序无法执行)
修改完成后保存。
Using Vim
vim /path/to/chromedriver


After running the line above, you’ll probably see a bunch of gibberish. Do the following:
Search for cdc_by typing /cdc_and pressing return.
Enable editing by pressing a.
Delete any amount of $cdc_lasutopfhvcZLmcfland replace what was deleted with an equal amount characters. If you don’t, chromedriverwill fail.
After you’re done editing, press esc.
5.To save the changes and quit, type :wq!and press return.
If you don’t want to save the changes, but you want to quit, type :q!and press return.
You’re done.
Go to the altered chromedriver and double click on it. A terminal window should open up. If you don’t see killed in the output, you successfully altered the driver.

 

除此之外,还有一些其它的标志性字符串(不同的浏览器可能会有所不同):

 

  • webdriver  

  • __driver_evaluate 

  • __webdriver_evaluate 

  •  __selenium_evaluate  

  • __fxdriver_evaluate  

  • __driver_unwrapped  

  • __webdriver_unwrapped  

  • __selenium_unwrapped  

  • __fxdriver_unwrapped  

  • _Selenium_IDE_Recorder  

  • _selenium  

  • calledSelenium  

  • _WEBDRIVER_ELEM_CACHE  

  • ChromeDriverw  

  • driver-evaluate  

  • webdriver-evaluate  

  • selenium-evaluate  

  • webdriverCommand  

  • webdriver-evaluate-response  

  • __webdriverFunc  

  • __webdriver_script_fn  __$webdriverAsyncExecutor  

  • __lastWatirAlert  

  • __lastWatirConfirm  

  • __lastWatirPrompt  

  • $chrome_asyncScriptInfo  

  • $cdc_asdjflasutopfhvcZLmcfl_

附网站常见检测方法 :

File call_function.js:

function getPageCache(opt_doc) {
  var doc = opt_doc || document;
  //var key = '$cdc_asdjflasutopfhvcZLmcfl_';
  var key = 'randomblabla_';
  if (!(key in doc))
    doc[key] = new Cache();
  return doc[key];
}

runBotDetection = function () { var documentDetectionKeys = [ "__webdriver_evaluate", "__selenium_evaluate", "__webdriver_script_function", "__webdriver_script_func", "__webdriver_script_fn", "__fxdriver_evaluate", "__driver_unwrapped", "__webdriver_unwrapped", "__driver_evaluate", "__selenium_unwrapped", "__fxdriver_unwrapped", ]; var windowDetectionKeys = [ "_phantom", "__nightmare", "_selenium", "callPhantom", "callSelenium", "_Selenium_IDE_Recorder", ]; for (const windowDetectionKey in windowDetectionKeys) { const windowDetectionKeyValue = windowDetectionKeys[windowDetectionKey]; if (window[windowDetectionKeyValue]) { return true; } }; for (const documentDetectionKey in documentDetectionKeys) { const documentDetectionKeyValue = documentDetectionKeys[documentDetectionKey]; if (window['document'][documentDetectionKeyValue]) { return true; } }; for (const documentKey in window['document']) { if (documentKey.match(/\$[a-z]dc_/) && window['document'][documentKey]['cache_']) { return true; } } if (window['external'] && window['external'].toString() && (window['external'].toString()['indexOf']('Sequentum') != -1)) return true; if (window['document']['documentElement']['getAttribute']('selenium')) return true; if (window['document']['documentElement']['getAttribute']('webdriver')) return true; if (window['document']['documentElement']['getAttribute']('driver')) return true; return false; };