我一直在用 Chromedriver 测试 Selenium,我注意到有些页面可以检测到您正在使用 Selenium,即使根本没有自动化。即使我只是通过 Selenium 和 Xephyr 使用 Chrome 手动浏览,我也经常得到一个页面,说检测到可疑活动。我检查了我的用户代理和浏览器指纹,它们都与普通的 Chrome 浏览器完全相同。
当我在普通 Chrome 中浏览这些网站时,一切正常,但是当我使用 Selenium 时,我就被检测到了。
从理论上讲,chromedriver 和 Chrome 在任何网络服务器上看起来都应该完全一样,但它们可以通过某种方式检测到它。
如果你想要一些测试代码试试这个:
from pyvirtualdisplay import Display from selenium import webdriver display = Display(visible=1, size=(1600, 902)) display.start() chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--disable-extensions') chrome_options.add_argument('--profile-directory=Default') chrome_options.add_argument("--incognito") chrome_options.add_argument("--disable-plugins-discovery"); chrome_options.add_argument("--start-maximized") driver = webdriver.Chrome(chrome_options=chrome_options) driver.delete_all_cookies() driver.set_window_size(800,800) driver.set_window_position(0,0) print 'arguments done' driver.get('http://stubhub.com')
如果您浏览 stubhub,您将在一两个请求中被重定向和“阻止”。我一直在对此进行调查,但我无法弄清楚他们如何判断用户正在使用 Selenium。
他们是怎么做到的呢?
我在 Firefox 中安装了 Selenium IDE 插件,当我在普通的 Firefox 浏览器中仅使用附加插件访问 stubhub.com 时被禁止。
当我使用 Fiddler 查看来回发送的 HTTP 请求时,我注意到“假浏览器”请求通常在响应标头中包含“无缓存”。
像这样的结果有没有办法 从 JavaScript 中检测到我在 Selenium Webdriver 页面中, 这表明应该没有办法检测到您何时使用 webdriver。但这一证据表明并非如此。
该站点将指纹上传到他们的服务器,但我检查了 Selenium 的指纹与使用 Chrome 时的指纹相同。
这是他们发送到服务器的指纹有效负载之一:
{"appName":"Netscape","platform":"Linuxx86_64","cookies":1,"syslang":"en-US","userlang":"en- US","cpu":"","productSub":"20030107","setTimeout":1,"setInterval":1,"plugins": {"0":"ChromePDFViewer","1":"ShockwaveFlash","2":"WidevineContentDecryptionMo dule","3":"NativeClient","4":"ChromePDFViewer"},"mimeTypes": {"0":"application/pdf","1":"ShockwaveFlashapplication/x-shockwave- flash","2":"FutureSplashPlayerapplication/futuresplash","3":"WidevineContent DecryptionModuleapplication/x-ppapi-widevine- cdm","4":"NativeClientExecutableapplication/x- nacl","5":"PortableNativeClientExecutableapplication/x- pnacl","6":"PortableDocumentFormatapplication/x-google-chrome- pdf"},"screen":{"width":1600,"height":900,"colorDepth":24},"fonts": {"0":"monospace","1":"DejaVuSerif","2":"Georgia","3":"DejaVuSans","4":"Trebu chetMS","5":"Verdana","6":"AndaleMono","7":"DejaVuSansMono","8":"LiberationM ono","9":"NimbusMonoL","10":"CourierNew","11":"Courier"}}
它在 Selenium 和 Chrome 中是相同的。
VPN 只能使用一次,但在我加载第一页后就会被检测到。显然,正在运行一些 JavaScript 来检测 Selenium。
cdc_
您可以使用vim或perl替换 中的cdc_字符串chromedriver。 请参阅回答,以了解有关该字符串以及它如何成为检测点的更多信息: 基本上,Selenium 检测的工作方式是,它们测试使用 Selenium 运行时出现的预定义 JavaScript 变量。bot 检测脚本通常在任何变量(在窗口对象上)中查找包含单词“selenium”/“webdriver”的任何内容,并且还记录名为$cdc_and的变量$wdc_。当然,所有这些都取决于您使用的浏览器。所有不同的浏览器都暴露了不同的东西。
vim
perl
chromedriver
$cdc_
$wdc_
对我来说,我使用的是 Chrome,所以,我所要做的就是确保它$cdc_不再作为文档变量存在,然后瞧(下载 chromedriver 源代码,修改 chromedriver 并$cdc_以不同的名称重新编译。)
这是我在chromedriver中修改的函数:
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]; }
(注意评论。我所做的一切都转向$cdc_了randomblabla_。)
randomblabla_
以下是演示僵尸网络可能使用的一些技术的伪代码:
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; };
根据用户的说法,也可以在十六进制编辑器中简单地打开 chromedriver.exe,然后手动进行替换,而无需实际进行任何编译。
使用vim或perl防止您必须重新编译源代码或使用十六进制编辑器。
确保chromedriver在尝试编辑之前复制原件。
我们的目标是改变cdc_字符串,它看起来像$cdc_lasutopfhvcZLmcfl.
$cdc_lasutopfhvcZLmcfl
以下方法已在chromedriver version 2.41.578706.
chromedriver version 2.41.578706
vim /path/to/chromedriver
运行上面的代码后,你可能会看到一堆乱码。请执行下列操作:
dog_``:%s/cdc_/dog_/g
dog_
:wq!
return
:q!
下面的行用 替换所有cdc_出现的地方dog_。感谢 Vic Seedoubleyew :
perl -pi -e 's/cdc_/dog_/g' /path/to/chromedriver
确保替换字符串(例如,dog_)与搜索字符串(例如,)具有相同数量的字符cdc_,否则chromedriver将失败。
要验证所有出现的cdc_被替换:
grep "cdc_" /path/to/chromedriver
如果没有返回输出,则替换成功。
转到更改chromedriver并双击它。应打开一个终端窗口。如果您没有killed在输出中看到,则您已成功更改了驱动程序。
killed
确保更改后的chromedriver二进制文件的名称是chromedriver,并且原始二进制文件已从其原始位置移动或重命名。
我之前在尝试登录时在网站上被检测到,但在替换cdc_为相同大小的字符串后,我能够登录。就像其他人所说的那样,如果您已经被检测到,您可能会被阻止一段时间即使使用了这种方法,还有很多其他原因。因此,您可能必须尝试访问使用 VPN、其他网络等检测到您的站点。