我一直在用Chromedriver测试Selenium,我注意到一些页面可以检测到你正在使用Selenium,即使根本没有自动化。甚至当我手动使用Chrome通过Selenium和Xephyr浏览时,我经常会看到一个页面说检测到可疑活动。我已经检查了我的用户代理和浏览器指纹,它们都与正常的Chrome浏览器完全相同。
当我在普通的Chrome浏览器中浏览这些网站时,一切都很好,但当我使用Selenium时,我被检测到。
理论上,chromedriver和Chrome在任何web服务器上看起来应该是完全一样的,但不知何故它们可以检测到它。
如果你想要一些测试代码,试试这个:
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页面中?建议当你在使用网络驱动程序时没有办法检测。但这些证据表明情况并非如此。
该网站将指纹上传到他们的服务器上,但我检查了一下,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_ string
您可以使用Vim或Perl来替换chromedriver中的cdc_ string。查看@Erti-Chris Eelmaa的回答,了解更多关于字符串的信息,以及它是如何成为探测点的。
使用Vim或Perl可以避免重新编译源代码或使用十六进制编辑器。
在尝试编辑原始chromedriver之前,请确保复制它。
我们的目标是修改cdc_字符串,它看起来类似于$cdc_lasutopfhvcZLmcfl。
下面的方法在chromedriver版本2.41.578706上进行了测试。
使用Vim
vim /path/to/chromedriver
运行上面的代码行之后,您可能会看到一堆胡言乱语。做以下几点:
通过输入:%s/cdc_/dog_/g将cdc_的所有实例替换为dog_。
Dog_只是一个例子。你可以选择任何东西,只要它有相同数量的字符作为搜索字符串(例如,cdc_),否则chromedriver将失败。
要保存修改并退出,输入:wq!然后按回车键。
如果您需要在不保存更改的情况下退出,请键入:q!然后按回车键。
使用Perl
下面这行代码将所有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,那么您已经成功修改了驱动程序。
确保更改后的chromedriver二进制文件的名称为chromedriver,并且原始二进制文件要么从原始位置移动,要么重命名。
我使用这种方法的经验
我之前在尝试登录时在网站上被检测到,但在用相等大小的字符串替换cdc_后,我能够登录。就像其他人说的那样,如果你已经被检测到,即使使用了这种方法,你也可能会因为其他很多原因被屏蔽。因此,您可能需要尝试访问使用VPN、其他网络等检测您的站点。
基本上,Selenium检测的工作方式是测试与Selenium一起运行时出现的预定义JavaScript变量。机器人检测脚本通常在任何变量(在窗口对象上)中查找包含单词“selenium”/“webdriver”的任何内容,也记录名为$cdc_和$wdc_的变量。当然,所有这些都取决于您使用的是哪种浏览器。所有不同的浏览器都公开不同的内容。
对我来说,我使用Chrome,所以,我所要做的就是确保$cdc_不再存在作为文档变量,和voilà(下载chromedriver源代码,修改chromedriver和重新编译$cdc_在不同的名称。)
这是我在chromedriver中修改的函数:
文件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];
}
(注意注释。我所做的就是把$cdc_变成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;
};
根据用户szx的说法,也可以简单地在十六进制编辑器中打开chromedriver.exe,只需手动进行替换,而无需实际进行任何编译。