我一直在用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。


当前回答

随着硒隐身的可用性,逃避硒驱动的ChromeDriver启动谷歌chrome浏览上下文的检测已经变得更加容易。


selenium-stealth

selenium-stealth是一个Python包,用于防止被探测。这个程序试图使python selenium更加隐秘。然而,目前硒隐身只支持硒铬。

目前硒隐身可以提供的特性:

具有隐身功能的硒隐身通过了所有公共机器人测试。 用硒隐身硒可以做到谷歌账号登录。 硒隐身有助于保持正常的reCAPTCHA v3评分


安装

硒隐身在PyPI上可用,因此您可以按照以下方式安装pip:

pip install selenium-stealth

Selenium4兼容代码

Code Block: from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium_stealth import stealth options = Options() options.add_argument("start-maximized") # Chrome is controlled by automated test software options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) s = Service('C:\\BrowserDrivers\\chromedriver.exe') driver = webdriver.Chrome(service=s, options=options) # Selenium Stealth settings stealth(driver, languages=["en-US", "en"], vendor="Google Inc.", platform="Win32", webgl_vendor="Intel Inc.", renderer="Intel Iris OpenGL Engine", fix_hairline=True, ) driver.get("https://bot.sannysoft.com/") Browser Screenshot:


Tl;博士

你可以在下面找到一些相关的详细讨论:

当你用chromedriver使用Selenium时,网站能检测到吗? 如何自动登录到一个网站,这是检测我的尝试登录使用硒隐身 未检测到的Chromedriver没有正确加载

其他回答

即使你发送了所有正确的数据(例如,Selenium没有显示为扩展,你有一个合理的分辨率/位深,等等),也有许多服务和工具可以分析访问者的行为,以确定参与者是用户还是自动化系统。

例如,访问一个网站,然后立即通过将鼠标直接移动到相关按钮上来执行一些操作,在不到一秒钟的时间内,这是用户实际上不会做的事情。

它也可能是一个有用的调试工具,使用网站,如https://panopticlick.eff.org/,以检查您的浏览器有多独特;它还将帮助您验证是否有任何特定的参数表明您正在运行Selenium。

随着硒隐身的可用性,逃避硒驱动的ChromeDriver启动谷歌chrome浏览上下文的检测已经变得更加容易。


selenium-stealth

selenium-stealth是一个Python包,用于防止被探测。这个程序试图使python selenium更加隐秘。然而,目前硒隐身只支持硒铬。

目前硒隐身可以提供的特性:

具有隐身功能的硒隐身通过了所有公共机器人测试。 用硒隐身硒可以做到谷歌账号登录。 硒隐身有助于保持正常的reCAPTCHA v3评分


安装

硒隐身在PyPI上可用,因此您可以按照以下方式安装pip:

pip install selenium-stealth

Selenium4兼容代码

Code Block: from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium_stealth import stealth options = Options() options.add_argument("start-maximized") # Chrome is controlled by automated test software options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) s = Service('C:\\BrowserDrivers\\chromedriver.exe') driver = webdriver.Chrome(service=s, options=options) # Selenium Stealth settings stealth(driver, languages=["en-US", "en"], vendor="Google Inc.", platform="Win32", webgl_vendor="Intel Inc.", renderer="Intel Iris OpenGL Engine", fix_hairline=True, ) driver.get("https://bot.sannysoft.com/") Browser Screenshot:


Tl;博士

你可以在下面找到一些相关的详细讨论:

当你用chromedriver使用Selenium时,网站能检测到吗? 如何自动登录到一个网站,这是检测我的尝试登录使用硒隐身 未检测到的Chromedriver没有正确加载

基本上,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,只需手动进行替换,而无需实际进行任何编译。

据说Firefox在使用webdriver时设置window.navigator.webdriver === true。这是根据一个旧的规格(例如:archive.org),但我无法在新的附录中找到它,除了一些非常模糊的措辞。

它的测试是在文件fingerprint_test.js中的selenium代码中,其中末尾的注释说“目前仅在firefox中实现”,但我无法通过一些简单的greping识别该方向的任何代码,无论是在当前(41.0.2)firefox发布树中还是在chromium树中。

我还发现了一个关于2015年1月firefox驱动程序b82512999938中指纹识别的旧提交的评论。该代码仍然在昨天从javascript/firefox-driver/extension/content/server.js下载的Selenium GIT-master中,并附有一个链接到当前w3c webdriver规范中措辞略有不同的附录的注释。

它适用于一些网站,从导航器中删除属性webdriver

from selenium import webdriver
driver = webdriver.Chrome()
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    "source":
        "const newProto = navigator.__proto__;"
        "delete newProto.webdriver;"
        "navigator.__proto__ = newProto;"
    })