当您将 Selenium 与 chromedriver 一起使用时,网站可以检测到吗?

IT技术 javascript python google-chrome selenium selenium-chromedriver
2021-01-09 20:20:21

我一直在用 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 请求时,我注意到“假浏览器”的请求通常在响应标头中包含“无缓存”。

像这样的结果Is there a way to detection that I is in a Selenium Webdriver page from JavaScript建议当您使用 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。

6个回答

基本上,Selenium 检测的工作方式是测试在使用 Selenium 运行时出现的预定义 JavaScript 变量。bot 检测脚本通常会在任何变量(在 window 对象上)中查找包含“selenium”/“webdriver”一词的任何内容,并且还会记录名为$cdc_and 的变量$wdc_当然,所有这些都取决于您使用的是哪种浏览器。所有不同的浏览器都会暴露不同的东西。

对我来说,我使用了 Chrome,所以,我所要做的就是确保它$cdc_不再作为文档变量存在,瞧(下载 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,然后手动进行替换,而无需实际进行任何编译。

我找到了文件“/Users/your_username/chromium/src/chrome/test/chromedriver/js”
2021-03-21 20:20:21
这是在 windows、osx 还是 linux 上?osx 上的十六进制编辑似乎不起作用。
2021-03-24 20:20:21
使用 $zzz_zzzzzzzzzzzzzzzzzzzzzz_(相同数量的字符)进行十六进制编辑但没有用。
2021-03-28 20:20:21
是的,它在没有问题的情况下工作,请注意一个问题是,如果您在此更改之前落入“黑名单”,则很难摆脱。如果你想摆脱现有的黑名单,你需要实现假画布指纹识别、禁用闪存、更改 IP 和更改请求头顺序(交换语言和接受头)。一旦你落入黑名单,他们有很好的手段来追踪你,即使你改变了IP,即使你在隐身模式下打开chrome等等
2021-04-01 20:20:21
我只是在十六进制编辑器中替换$cdcxxxxinchromedriver.exe并且它起作用了!我还注意到,如果您最大化浏览器窗口(而不是使用预定义的大小),则检测到的频率会降低。
2021-04-06 20:20:21

替换cdc_字符串

您可以使用vimperl替换 中的cdc_字符串chromedriver请参阅@Erti-Chris Eelmaa 的回答以了解有关该字符串及其如何成为检测点的更多信息

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

chromedriver在尝试编辑它之前,请确保制作原始副本

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

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


使用 Vim

vim /path/to/chromedriver

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

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

使用 Perl

下面的行将所有cdc_出现的内容替换dog_感谢维克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、不同网络等检测您的站点。

TLDR;在十六进制编辑器中打开二进制文件,将字符串开头更改$cdc为其他相同长度的字符串,然后保存并运行修改后的二进制文件。
2021-03-11 20:20:21
@LekaBaper 感谢您的提醒。我使用的 chromedriver 版本是 2.41.578706 版。
2021-03-14 20:20:21
即使我在不​​同网络上的新物理计算机上使用这个 chromedriver.exe 修改也没有工作。
2021-03-23 20:20:21
请注意,chromedriver 人员已声明此问题不会解决,因此您可以期望在不确定的将来必须使用 fork 或编辑二进制文件。bugs.chromium.org/p/chromedriver/issues/detail?id=3220
2021-04-04 20:20:21
@db 替换所有这些。我会更新 Vim 说明。
2021-04-07 20:20:21

正如我们在问题和发布的答案中已经发现的那样,这里有一个反网络抓取和一个名为“Distil Networks”的机器人检测服务而且,根据公司 CEO 的采访

尽管他们可以创建新的机器人,但我们找到了一种方法来识别 Selenium 是他们正在使用的工具,因此无论他们在该机器人上迭代多少次,我们都会阻止 Selenium我们现在正在使用 Python 和许多不同的技术来做到这一点。一旦我们看到一种模式从一种机器人中出现,我们就会对他们使用的技术进行逆向工程,并将其识别为恶意的。

了解他们究竟如何检测 Selenium 需要时间和额外的挑战,但目前我们可以肯定地说:

  • 它与您对 selenium 采取的操作无关 - 一旦您导航到该站点,您就会立即被检测到并被禁止。我试图在动作之间添加人为的随机延迟,在页面加载后暂停 - 没有任何帮助
  • 这也不是关于浏览器指纹 - 在多个浏览器中尝试使用干净的配置文件而不是隐身模式 - 没有任何帮助
  • 因为,根据采访中的提示,这是“逆向工程”,我怀疑这是通过在浏览器中执行一些 JS 代码来完成的,这表明这是一个通过 selenium webdriver 自动化的浏览器

决定将其发布为答案,因为很明显:

当您在 chromedriver 中使用 selenium 时,网站可以检测到吗?

是的。


此外,我还没有尝试过旧的 selenium 和旧的浏览器版本 - 从理论上讲,可能在某个点实现/添加到 selenium 中,这是 Distil Networks bot 检测器当前依赖的。然后,如果是这种情况,我们可能会检测(是的,让我们检测检测器)在哪个点/版本进行了相关更改,查看变更日志和变更集,并且可能是,这可以为我们提供有关在哪里查看的更多信息他们用什么来检测由 webdriver 驱动的浏览器。这只是一个需要检验的理论。

我认为他们正在 chrome webdriver 中检测 navigator.webdriver。我试图在intoli.com/blog/not-possible-to-block-chrome-headlessstackoverflow.com/questions/47297877/...的帮助下使 navigator.webdriver = false 它返回一个机器人检测页面而不是distilnetworks.com/distil_identify_cookie.html
2021-03-17 20:20:21
@RyanWeinstein 好吧,我们没有实际证据,只能推测和测试。现在,我想说他们有办法使用selenium来检测我们。尝试使用 selenium 版本进行试验 - 这可能会给您一些线索。
2021-03-24 20:20:21
是否与如何确定临时端口有关?该方法远离众所周知的范围。github.com/SeleniumHQ/selenium/blob/...
2021-03-24 20:20:21
Easyjet 正在使用 distilnetwork 服务,是的,它可以阻止虚拟机器人,但不能阻止复杂的机器人,因为我们每天测试了来自不同 IP(我们再次使用“相同”地址)的 2000 多个请求,因此基本上每个 IP 都适用每天 5-10 个请求,由此我可以看出所有这些机器人检测服务只是为了开发和销售大约 45% 的工作算法,我们使用的刮板很容易检测到我可以在 destilnetworks、squareshield 等时阻止它不能,这促使我从不使用它们中的任何一个。
2021-03-31 20:20:21

关于检测到由Selenium控制的ChromeDriver驱动的网站,已经分析和讨论了很多这是我的两分钱:

根据文章浏览器检测使用用户代理为不同的浏览器提供不同的网页或服务通常不是最好的主意。无论用户使用哪种浏览器或设备,每个人都可以访问网络。概述了开发网站以根据功能可用性而不是针对特定浏览器逐步增强自身的最佳实践。

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

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

  • 无头 Chrome UserAgent 中检测术语HeadlessChrome

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

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

当使用 Selenium 和 Python 传递值时,您可以在 https://www.nseindia.com/ 上的 Dynamic dropdown does not populate with autoSuggestions 中找到相关的详细讨论

  • 使用机器人的保护服务Datadome

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

然而,使用 检测浏览器看起来很简单,但做得好实际上有点困难。

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


浏览器检测的注意事项

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

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

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

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

  • 实施测试以检测浏览器如何实施功能的 API 并由此确定如何使用它。一个例子是Chrome 未标记的正则表达式中的实验性后视支持
  • 适应渐进式增强的设计技术,这将涉及分层开发网站,使用自下而上的方法,从更简单的层开始,并在连续的层中提高站点的功能,每个层都使用更多的功能。
  • 调整优雅降级的自上而下的方法,在这种方法中,我们使用我们想要的所有功能构建最好的站点,然后对其进行调整以使其在旧浏览器上运行。

解决方案

为了防止Selenium驱动的WebDriver被检测到,一个小众方法将包括以下提到的任一/所有方法:

  • 旋转的UserAgent在你的每一个执行测试套件使用fake_useragentmodule如下:

    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()
    

您可以在Way to change Google Chrome user agent in Selenium 中找到相关的详细讨论

  • 旋转的UserAgent在每个你的测试使用Network.setUserAgentOverride通过execute_cdp_cmd()如下:

    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;"))
    

您可以在How to change the User Agent using Selenium and Python 中找到相关的详细讨论

  • for webdriver属性更改为如下:navigatorundefined

    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
      "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined
        })
      """
    })
    

您可以在Selenium webdriver: Modifying navigator.webdriver flag to prevent selenium detection 中找到相关的详细讨论

  • 更改navigator.plugins, navigator.languages, WebGL , hairline feature , missing image等的值。

您可以在Is there a version of selenium webdriver that is not detection? 中找到相关的详细讨论

您可以在How to bypass Google captcha with Selenium and python 中找到相关的详细讨论


处理 reCAPTCHA

在处理的同时 而是点击 与文本相关联,我不是机器人,可能更容易通过身份验证提取和使用data-sitekey.

您可以在如何使用 Selenium 和 Python 请求以编程方式识别 ReCaptcha V2 的 32 位数据站点密钥以获取有效响应中找到相关的详细讨论


tl; 博士

您可以在以下位置找到避免 Webdriver 检测的尖端解决方案:

我在bloomberg.com 上测试了你的python 代码。仍然认出我是机器人。
2021-03-29 20:20:21

它是如何在 wellsfargo.com 上实施的示例:

try {
 if (window.document.documentElement.getAttribute("webdriver")) return !+[]
} catch (IDLMrxxel) {}
try {
 if ("_Selenium_IDE_Recorder" in window) return !+""
} catch (KknKsUayS) {}
try {
 if ("__webdriver_script_fn" in document) return !+""
为什么最后一次尝试没有关闭?另外你能不能解释一下你的答案。
2021-03-13 20:20:21