网站可以检测到您何时将硒与chromedriver一起使用吗?

我一直在用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周围浏览,你会在一两个请求中被重定向和“阻止”。我一直在调查这个问题,我不知道他们怎么能分辨出用户正在使用硒。

他们是怎么做到的?

我在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"}}

它在硒和铬中是相同的。

VPN适用于单次使用,但在我加载第一页后会检测到它们。显然,一些JavaScript正在运行以检测Selenium。


答案 1

基本上,Selenium检测的工作方式是,它们测试预定义的JavaScript变量,这些变量在与Selenium一起运行时出现。机器人检测脚本通常会在任何变量(窗口对象上)中查找包含单词“selenium”/“webdriver”的任何内容,并且还会记录名为 和 的变量。当然,所有这些都取决于您使用的浏览器。所有不同的浏览器都公开了不同的东西。$cdc_$wdc_

对我来说,我使用Chrome,所以,我所要做的就是确保它不再作为文档变量存在,瞧(下载chromedriver源代码,修改chromedriver并以不同的名称重新编译。$cdc_$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十六进制编辑器中,然后手动进行替换,而无需实际进行任何编译。


答案 2

替换cdc_字符串

可以使用 或 替换 中的字符串。请参阅@Erti-Chris Eelmaa的答案,以了解有关该字符串的更多信息以及它如何成为检测点vimperlcdc_chromedriver

使用 或 防止您不得不重新编译源代码或使用十六进制编辑器。vimperl

请务必先复制原始 chromedriver,然后再尝试对其进行编辑。

我们的目标是改变字符串,它看起来像 。cdc_$cdc_lasutopfhvcZLmcfl

以下方法已在 上进行了测试。chromedriver version 2.41.578706


使用 Vim

vim /path/to/chromedriver

运行上面的行后,您可能会看到一堆胡言乱语。请执行下列操作:

  1. 通过键入 将 的所有实例替换为 。cdc_dog_:%s/cdc_/dog_/g
    • dog_只是一个例子。您可以选择任何内容,只要它具有与搜索字符串相同的字符数(例如,),否则将失败。cdc_chromedriver
  2. 要保存更改并退出,请键入并按 。:wq!return
    • 如果需要在不保存更改的情况下退出,请键入并按 。:q!return

使用 Perl

下面的行将所有匹配项替换为 。感谢Vic Seedoubleyewcdc_dog_

perl -pi -e 's/cdc_/dog_/g' /path/to/chromedriver

确保替换字符串(例如,)具有与搜索字符串(例如,)相同的字符数,否则将失败。dog_cdc_chromedriver


结束语

要验证是否替换了所有匹配项,请执行以下操作:cdc_

grep "cdc_" /path/to/chromedriver

如果未返回任何输出,则替换成功。

转到更改并双击它。应打开一个终端窗口。如果在输出中看不到,则表示已成功更改驱动程序。chromedriverkilled

确保已更改的二进制文件的名称为 ,并且原始二进制文件已从其原始位置移动或重命名。chromedriverchromedriver


我对这种方法的经验

以前在尝试登录时在网站上检测到我,但是在替换为大小相等的字符串后,我能够登录。就像其他人说的那样,如果您已经被检测到,那么即使在使用此方法后,您也可能由于许多其他原因而被阻止。因此,您可能需要尝试使用VPN,其他网络等访问检测到您的站点。cdc_