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


当前回答

部分接口导航器{只读属性布尔webdriver;};

Navigator接口的webdriver IDL属性必须返回webdriver-active标志的值,初始值为false。

此属性允许网站确定用户代理受WebDriver控制,并可用于帮助减轻拒绝服务攻击。

直接摘自2017年W3C WebDriver编辑草案。这在很大程度上意味着,至少Selenium驱动程序的未来迭代将是可识别的,以防止误用。最终,如果没有源代码,就很难判断到底是什么原因导致chrome驱动程序被检测到。

其他回答

我所要做的就是

my_options = webdriver.ChromeOptions()
my_options.add_argument( '--disable-blink-features=AutomationControlled' )

Some more information to this: This relates to website skyscanner.com. In the past I have been able to scrape it. Yes, it did detect the browser automation and it gave me a captcha to press and hold a button. I used to be able to complete the captcha manually, then search flights and then scrape. But this time around after completing the captcha I get the same captcha again and again, just can't seem to escape from it. I tried some of the most popular suggestions to avoid automation being detected, but they didn't work. Then I found this article which did work, and by process of elimination I found out it only took the option above to get around their browser automation detection. Now I don't even get the captcha and everything else seems to be working normally.

我目前正在运行的版本:

操作系统:Windows 7 64位 win32上的Python 3.8.0 (tags/v3.8.0:fa919fd, 2019-10-14) (MSC v.1916 64位(AMD64)) 浏览器:Chrome版本100.0.4896.60(官方 构建)(64位) 4.1.3硒 ChromeDriver 100.0.4896.60 chromedriver_win32.zip 930ff33ae8babeaa74e0dd1ce1dae7ff

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

尽管他们可以创造新的机器人,但我们找到了识别的方法 硒是他们使用的一个工具,所以我们阻止硒不 不管他们在机器人上迭代了多少次。我们现在正在做 使用Python和许多不同的技术。一旦我们发现了规律 从一种机器人中脱颖而出,然后我们对其进行逆向工程 他们使用的技术并将其识别为恶意的。

要了解他们究竟是如何检测硒的,还需要时间和更多的挑战,但目前我们可以肯定地说:

it's not related to the actions you take with Selenium. Once you navigate to the site, you get immediately detected and banned. I've tried to add artificial random delays between actions, take a pause after the page is loaded - nothing helped it's not about browser fingerprint either. I tried it in multiple browsers with clean profiles and not, incognito modes, but nothing helped since, according to the hint in the interview, this was "reverse engineering", I suspect this is done with some JavaScript code being executed in the browser revealing that this is a browser automated via Selenium WebDriver

我决定把它作为一个答案,因为很明显:

当你用chromedriver使用selenium时,网站能检测到吗?

Yes.


Also, I haven't experimented with older Selenium and older browser versions. In theory, there could be something implemented/added to Selenium at a certain point that Distil Networks bot detector currently relies on. Then, if this is the case, we might detect (yeah, let's detect the detector) at what point/version a relevant change was made, look into changelog and changesets and, may be, this could give us more information on where to look and what is it they use to detect a webdriver-powered browser. It's just a theory that needs to be tested.

我所看到的机器人检测似乎更复杂,或者至少与我在下面阅读的答案不同。

实验1

我从Python控制台用Selenium打开浏览器和网页。 鼠标已经在一个特定的位置,我知道一旦页面加载,就会出现一个链接。我从不移动鼠标。 我按一次鼠标左键(这对于将焦点从运行Python的控制台转移到浏览器是必要的)。 我再次按下鼠标左键(记住,光标在给定链接的上方)。 链接正常打开,就像它应该的那样。

实验2

像以前一样,我从Python控制台打开一个浏览器和带有Selenium的web页面。 这一次,我不再使用鼠标单击,而是使用Selenium(在Python控制台中)单击带有随机偏移量的同一元素。 链接没有打开,但我被带到一个注册页面。

影响

通过Selenium打开网页浏览器并不妨碍我看起来像人类 像人类一样移动鼠标并不一定要被归类为人类 通过Selenium点击带有偏移量的内容仍然会引起警报

这看起来很神秘,但我猜他们可以确定一个操作是否起源于Selenium,而他们并不关心浏览器本身是否是通过Selenium打开的。或者他们能确定窗口是否有焦点吗?如果有人有什么见解,我会很有趣。

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

我还发现一些网站使用了一个检查用户代理的平台。如果该值包含:"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");