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


当前回答

在我看来,用Selenium做这件事最简单的方法是拦截发送回浏览器指纹的XHR。

但由于这是一个只有硒的问题,所以最好使用其他东西。硒应该让事情变得更容易,而不是更难。

其他回答

针对一个由Selenium控制的ChromeDriver驱动的网站被检测的问题进行了大量的分析和讨论。以下是我的观点:

根据这篇文章,使用为不同浏览器提供不同网页或服务的用户代理进行浏览器检测通常不是最好的想法之一。无论用户使用哪种浏览器或设备,网络都应该对所有人开放。这里列出了开发网站的最佳实践,以便根据功能可用性而不是针对特定的浏览器逐步增强自己。

然而,浏览器和标准并不完美,仍然有一些边缘情况,一些网站仍然检测到浏览器,如果浏览器是由Selenium控制的WebDriver驱动。浏览器可以通过不同的方式检测,一些常用的机制如下:

实现captcha / recaptcha来检测自动机器人。

您可以在如何recaptcha 3知道我正在使用selenium/chromedriver中找到相关的详细讨论?

检测术语HeadlessChrome在headless Chrome UserAgent

你可以在无头Chrome在Linux上的访问拒绝页面中找到相关的详细讨论,而有头Chrome在通过Python使用Selenium在windows上工作

使用蒸馏网络的机器人管理服务

您可以在无法使用Selenium自动化Chase站点登录中找到相关的详细讨论

使用Akamai的Bot Manager服务

当使用Selenium和Python传递值时,您可以在https://www.nseindia.com/上的动态下拉菜单中找到相关的详细讨论

使用来自Datadome的Bot Protection服务

你可以在网站上找到相关的详细讨论,使用DataDome在使用Selenium和Python抓取时阻止验证码

然而,使用用户代理来检测浏览器看起来很简单,但实际上要做到这一点有点困难。

注意:在这一点上,值得一提的是:使用用户代理嗅探很少是个好主意。总有更好、更广泛兼容的方法来解决某个问题。


浏览器检测的注意事项

检测浏览器背后的想法可以是以下任何一种:

试图解决一个特定的错误在某些特定的变种或特定版本的网络浏览器。 试图检查某些浏览器还不支持的特定功能是否存在。 尝试根据所使用的浏览器提供不同的HTML。


通过UserAgents进行浏览器检测的替代方法

一些浏览器检测的替代方案如下:

Implementing a test to detect how the browser implements the API of a feature and determine how to use it from that. An example was Chrome unflagged experimental lookbehind support in regular expressions. Adapting the design technique of Progressive enhancement which would involve developing a website in layers, using a bottom-up approach, starting with a simpler layer and improving the capabilities of the site in successive layers, each using more features. Adapting the top-down approach of Graceful degradation in which we build the best possible site using all the features we want and then tweak it to make it work on older browsers.


解决方案

为了防止Selenium驱动的WebDriver被检测到,一个合适的方法应该包括下面提到的方法中的任何一种或所有方法:

Rotating the UserAgent in every execution of your Test Suite using fake_useragent module as follows: from selenium import webdriver from selenium.webdriver.chrome.options import Options from fake_useragent import UserAgent options = Options() ua = UserAgent() userAgent = ua.random print(userAgent) options.add_argument(f'user-agent={userAgent}') driver = webdriver.Chrome(chrome_options=options, executable_path=r'C:\WebDrivers\ChromeDriver\chromedriver_win32\chromedriver.exe') driver.get("https://www.google.co.in") driver.quit()

您可以在如何在Selenium中更改谷歌Chrome用户代理中找到相关的详细讨论?

Rotating the UserAgent in each of your Tests using Network.setUserAgentOverride through execute_cdp_cmd() as follows: from selenium import webdriver driver = webdriver.Chrome(executable_path=r'C:\WebDrivers\chromedriver.exe') print(driver.execute_script("return navigator.userAgent;")) # Setting user agent as Chrome/83.0.4103.97 driver.execute_cdp_cmd('Network.setUserAgentOverride', {"userAgent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'}) print(driver.execute_script("return navigator.userAgent;"))

您可以在如何使用Selenium和Python更改用户代理中找到相关的详细讨论

修改webdriver的navigator属性值为undefined,如下所示: driver.execute_cdp_cmd(“页面。addScriptToEvaluateOnNewDocument”,{ “源”:“” Object.defineProperty(导航器,'webdriver', { Get: () => undefined }) ”“” })

您可以在Selenium webdriver:修改导航器中找到相关的详细讨论。Webdriver标志,以防止硒检测

更改navigator的值。插件,导航器。语言,WebGL,发际线功能,缺失图像等。

您可以在“是否存在无法检测到的selenium webdriver版本?”中找到相关的详细讨论。

改变传统的视口

您可以在如何绕过谷歌验证码与硒和python中找到相关的详细讨论?


处理reCAPTCHA

在处理2captcha和recaptcha-v3而不是点击与文本相关的复选框时,我不是机器人,提取和使用data-sitekey可能更容易获得身份验证。

您可以在如何识别ReCaptcha V2的32位data-sitekey中找到相关的详细讨论,以使用Selenium和Python请求以编程方式获得有效的响应?


Tl;博士

你可以找到一个先进的解决方案,以逃避网络驱动检测:

硒隐身-一种行之有效的方法来逃避网络驱动检测

据说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规范中措辞略有不同的附录的注释。

我还发现一些网站使用了一个检查用户代理的平台。如果该值包含:"HeadlessChrome",则使用无头模式时行为可能会很奇怪。

解决方法是重写用户代理的值,例如在Java中:

chromeOptions.addArguments("--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36");

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

你可以尝试使用参数enable-automation

var options = new ChromeOptions();

// hide selenium
options.AddExcludedArguments(new List<string>() { "enable-automation" });

var driver = new ChromeDriver(ChromeDriverService.CreateDefaultService(), options);

但是,我想警告一下,这个能力在ChromeDriver 79.0.3945.16中被修复了。 所以你可能应该使用旧版本的chrome。

另外,作为另一种选择,你可以尝试使用InternetExplorerDriver而不是Chrome。对我来说,IE在没有任何hack的情况下根本不会阻塞。

想要了解更多信息,请看看这里:

Selenium webdriver:修改导航器。Webdriver标志,以防止硒检测

在Chrome v76中无法隐藏“Chrome被自动软件控制”信息栏