使用chromedriver.exe時如何避免網(wǎng)站檢測到模擬器
你已經(jīng)可以編寫selenium程序爬一個沒有驗證碼的網(wǎng)頁,但現(xiàn)在碰到了一個拖動驗證碼:https://cf.aliyun.com/nocaptcha
總結(jié)
經(jīng)過搜索、嘗試、再搜索、再嘗試…,終于發(fā)現(xiàn)需要使用兩項技術(shù)對selenium進(jìn)行反爬:
webdriver屬性
特征$cdc_asdjflasutopfhvcZLmcfl_
通過js腳本提取webdriver屬性和特征$cdc_asdjflasutopfhvcZLmcfl_,將提取結(jié)果進(jìn)行編碼后發(fā)送給服務(wù)器。服務(wù)器發(fā)現(xiàn)是selenium爬蟲后,拒絕驗證。
知道了反爬,則反反爬也就好辦了。逐項針對規(guī)避即可。
有大神已經(jīng)將步驟整理:https://blog.csdn.net/sdzhr/article/details/86714328
下面解惑一下:
webdriver屬性
Chrome從v63版本開始添加了webdriver屬性。只要通過selenium調(diào)用了瀏覽器便會將這個屬性設(shè)置為true。
當(dāng)服務(wù)器通過js腳本識別到webdriver屬性時,會有如下現(xiàn)象:
手工啟動chrome,人工拖動驗證碼可以通過驗證。
使用selenium啟動chrome,人工拖動驗證碼無法通過驗證。
使用selenium啟動chrome,程序模擬拖動驗證碼無法通過驗證。
所以,避開webdriver屬性需要使用低于v63版本的Chrome(v62.0.3202.94版本測試通過)。
注:
參考文章中提到的chrome 62.0.3202.62版本,未找到下載鏈接。
chrome和chromedriver之間是有對應(yīng)關(guān)系的,版本不匹配則無法使用。chrome和chromedriver之間的對應(yīng)關(guān)系。
換用Firefox,也會有webdriver屬性。
在瀏覽器的console控制臺中輸入navigator回車后,在輸出中會發(fā)現(xiàn)webdriver屬性,且值為true。
特征$cdc_asdjflasutopfhvcZLmcfl_
$cdc_asdjflasutopfhvcZLmcfl_是chromeDriver的特征之一。
chromeDriver會創(chuàng)建cdc_asdjflasutopfhvcZLmcfl_元素,并將該元素用于各種操作。比如,在使用findElement方法時,會使用該元素。
當(dāng)服務(wù)器通過js腳本識別到特征“$cdc_asdjflasutopfhvcZLmcfl_”時,會有如下現(xiàn)象:
手工啟動chrome,人工拖動驗證碼可以通過驗證。
使用selenium啟動chrome,人工拖動驗證碼可以通過驗證。
使用selenium啟動chrome,程序模擬拖動驗證碼無法通過驗證。(原因即為上面所述)
避開webdriver屬性需要修改chromeDriver中的特征$cdc_asdjflasutopfhvcZLmcfl_。修改方法:
通過文本編輯器打開chromedriver。linux下,通過vim chromedriver打開。windows下,通過notepad++打開chromedriver.exe。
查找特征"cdc_",改為"chr_"。(刪掉幾個字符,則加幾個字符。不能改變var key = '$cdc_asdjflasutopfhvcZLmcfl_';key字符串的長度。否則,會導(dǎo)致chromedriver程序無法執(zhí)行)
修改完成后保存。
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.
除此之外,還有一些其它的標(biāo)志性字符串(不同的瀏覽器可能會有所不同):
-
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_
附網(wǎng)站常見檢測方法 :
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; };