我一直在用Chromedriver测试Selenium,我注意到有些页面可以检测到你正在使用Selenium,即使根本没有自动化。即使我只是通过Selenium和Xephyr使用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请求时,我注意到了虚假的浏览器' s'请求通常具有“无缓存”功能。在响应标题中。
编辑:
像这样Is there a way to detect that I'm in a Selenium Webdriver page from Javascript的结果表明,无法检测何时使用webdriver。但是这个证据表明不然。编辑:
网站将指纹上传到他们的服务器,但我检查了使用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":"WidevineContentDecryptionModule","3":"NativeClient","4":"ChromePDFViewer"},"mimeTypes":{"0":"application/pdf","1":"ShockwaveFlashapplication/x-shockwave-flash","2":"FutureSplashPlayerapplication/futuresplash","3":"WidevineContentDecryptionModuleapplication/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":"TrebuchetMS","5":"Verdana","6":"AndaleMono","7":"DejaVuSansMono","8":"LiberationMono","9":"NimbusMonoL","10":"CourierNew","11":"Courier"}}
在硒和铬中相同
编辑:
VPN仅供一次使用,但在我加载第一页后会被检测到。很明显,正在运行一些javascript来检测Selenium。
答案 0 :(得分:114)
基本上,硒检测的工作方式是,它们测试使用selenium运行时出现的预定义javascript变量。机器人检测脚本通常在任何变量(在窗口对象上)中查找包含单词“selenium”/“webdriver”的任何内容,还包含名为$cdc_
和$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,然后手动进行替换,而不实际进行任何编译。
答案 1 :(得分:78)
正如我们已经在问题和发布的答案中已经找到的那样,这里有一个反网络抓取和一个名为"Distil Networks"的Bot检测服务。而且,根据公司首席执行官interview:
即使他们可以创建新的机器人,我们找到了一种识别方法 Selenium是他们正在使用的工具,因此我们阻止了Selenium no 无论他们多少次迭代该机器人。我们现在正在这样做 使用Python和许多不同的技术。一旦我们看到一个模式 从一种类型的机器人出现,然后我们努力逆向工程 他们使用的技术并将其识别为恶意。
了解他们究竟是如何检测Selenium需要时间和其他挑战,但目前我们可以肯定地说:
明确地决定将其作为答案发布:
当您使用含有氯化物的硒时,网站是否可以检测到?
是
此外,我还没有尝试过的是旧的硒和旧的浏览器版本 - 理论上,在Distil Networks机器人探测器目前依赖的特定点上可能会有一些实现/添加到硒的东西。然后,如果是这种情况,我们可能会检测(是的,让我们检测探测器)在什么点/版本进行相关更改,查看更改日志和更改集,可能会给我们提供更多信息在哪里查看以及它们用于检测由webdriver驱动的浏览器的内容。它只是一个需要测试的理论。
答案 2 :(得分:19)
在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 !+""
答案 3 :(得分:17)
已经进行了很多分析和讨论,涉及由Selenium控制的ChromeDriver驱动的网站被检测到。这是我的两分钱。
根据文章Browser detection using the user agent,为不同的浏览器提供不同的网页或服务通常不是最好的主意。不论用户使用哪种浏览器或设备,每个人都可以访问Web。概述了开发网站的最佳实践,以根据功能的可用性而不是针对特定的浏览器来逐步增强自身。
但是,浏览器和标准并不完美,在某些极端情况下,某些网站仍会检测到该浏览器,并且该浏览器是由 Selenium 控制的WebDriver驱动的。可以通过不同的方式来检测浏览器,一些常用的机制如下:
您可以在How does recaptcha 3 know I'm using selenium/chromedriver?
中找到相关的详细讨论
中找到相关的详细讨论
中找到相关的详细讨论
中找到相关的详细讨论
您可以在Website using DataDome gets captcha blocked while scraping using Selenium and Python
中找到相关的详细讨论
但是,使用user-agent检测浏览器看起来很简单,但实际上做起来要困难一些。
注意:在这一点上值得一提:使用用户代理嗅探很少是一个好主意。总有更好,更广泛兼容的方法来解决特定问题。
检测浏览器的想法可能是以下之一:
浏览器检测的一些替代方法如下:
为防止检测到由 Selenium 驱动的 WebDriver ,利基方法将包括以下一种或所有以下方法:
使用fake_useragent
模块在 Test Suite 的每次执行中旋转 UserAgent ,如下所示:
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()
中找到相关的详细讨论
使用Network.setUserAgentOverride
至execute_cdp_cmd()
,在每个 Tests 中旋转 UserAgent ,如下所示:
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;"))
中找到相关的详细讨论
将网络驱动程序的navigator
的属性值更改为 undefined
,如下所示:
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 ,细线特征,缺少图片等您可以在Is there a version of selenium webdriver that is not detectable?
中找到相关的详细讨论
中找到相关的详细讨论
在处理2captcha和recaptcha-v3而不是单击与文本我不是机器人相关的checkbox时,通过身份验证可能会更容易提取并使用data-sitekey
。
中找到相关的详细讨论
答案 4 :(得分:12)
使用Vim或Perl替换cdc_
变量
您可以使用vim
或@Vic Seedoubleyew在@ Erti-Chris Eelmaa perl
的答案中指出,替换{{1}中的cdc_
变量}(请参阅@ Erti-Chris Eelmaa的帖子,以了解有关该变量的更多信息)。使用chromedriver
或vim
可防止您不得不重新编译源代码或使用十六进制编辑器。在尝试编辑原始perl
之前,请确保对其进行复制。另外,以下方法已在chromedriver
上进行了测试。
chromedriver version 2.41.578706
运行完上面的行后,您可能会看到一堆乱码。请执行以下操作:
vim /path/to/chromedriver
并按cdc_
来搜索/cdc_
。return
启用编辑。a
,并用相等数量的字符替换删除的内容。否则,$cdc_lasutopfhvcZLmcfl
将失败。chromedriver
。esc
并按:wq!
。return
并按:q!
。转到更改后的return
,然后双击它。 chromedriver
窗口应打开。如果在输出中看不到terminal
,则说明您成功更改了驱动程序。
下面的行将killed
替换为cdc_
:
dog_
请确保替换字符串的字符数与搜索字符串的字符数相同,否则perl -pi -e 's/cdc_/dog_/g' /path/to/chromedriver
将失败。
Perl说明
chromedriver
表示您要搜索一个字符串并将其全局替换为另一个字符串(替换所有出现的字符串)。
例如
s///g
所以
s/string/replacment/g
表示搜索和替换字符串。
s///
是搜索字符串。
cdc_
是替换字符串。
dog_
是全局密钥,它将替换每次出现的字符串。
如何检查Perl替代产品是否有效
以下行将打印每次出现的搜索字符串g
:
cdc_
如果未返回任何内容,则perl -ne 'while(/cdc_/g){print "$&\n";}' /path/to/chromedriver
已被替换。
相反,您可以使用以下代码:
cdc_
查看您的替换字符串perl -ne 'while(/dog_/g){print "$&\n";}' /path/to/chromedriver
是否现在位于dog_
二进制文件中。如果是这样,替换字符串将被打印到控制台。
转到更改后的chromedriver
,然后双击它。 chromedriver
窗口应打开。如果在输出中看不到terminal
,则说明您成功更改了驱动程序。
更改killed
二进制文件后,请确保更改后的chromedriver
二进制文件的名称为chromedriver
,并确保原始二进制文件已从其原始位置移动或重命名。 / p>
以前我在尝试登录时在网站上被检测到,但是用相同大小的字符串替换了chromedriver
之后,我得以登录。就像其他人所说的那样,如果您已经检测到该错误后,即使使用此方法也可能由于多种其他原因而被阻止。因此,您可能必须尝试使用VPN,其他网络或拥有什么的站点访问检测到您的站点。
答案 5 :(得分:10)
partial interface Navigator { readonly attribute boolean webdriver; };
Navigator接口的webdriver IDL属性必须返回webdriver-active标志的值,该标志最初为false。
此属性允许网站确定用户代理受WebDriver控制,并可用于帮助缓解拒绝服务攻击。
直接来自2017 W3C Editor's Draft of WebDriver。这在很大程度上意味着,至少,未来的硒驱动程序迭代将被识别以防止滥用。最终,没有源代码很难分辨,究竟是什么原因导致特定的chrome驱动程序是可检测的。
答案 6 :(得分:9)
尝试使用具有特定用户配置文件chrome的selenium,这样您就可以将其用作特定用户并定义您想要的任何内容。这样做时它将作为一个真实的'运行。用户,使用某个进程资源管理器查看chrome进程,您将看到与标记的区别。
例如:
username = os.getenv("USERNAME")
userProfile = "C:\\Users\\" + username + "\\AppData\\Local\\Google\\Chrome\\User Data\\Default"
options = webdriver.ChromeOptions()
options.add_argument("user-data-dir={}".format(userProfile))
# add here any tag you want.
options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors", "safebrowsing-disable-download-protection", "safebrowsing-disable-auto-update", "disable-client-side-phishing-detection"])
chromedriver = "C:\Python27\chromedriver\chromedriver.exe"
os.environ["webdriver.chrome.driver"] = chromedriver
browser = webdriver.Chrome(executable_path=chromedriver, chrome_options=options)
chrome tag list here
答案 7 :(得分:7)
我已经检查了chromedriver源代码。这会将一些javascript文件注入浏览器。
此链接上的每个javascript文件都会注入到网页中:
https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver/js/
所以我使用了逆向工程,并通过十六进制编辑混淆了js文件。现在,我确定不再使用JavaScript变量,函数名称和固定字符串来发现硒的活动。但是仍然有些站点和reCaptcha可以检测到硒!
也许他们检查由chromedriver js执行引起的修改:)
编辑1:
我发现“导航器”中有一些参数可以简要介绍chromedriver的使用。 这些是参数:
所以我需要一个Chrome扩展程序来在网页上运行javascript。我使用本文提供的js code进行了扩展,并使用another article将压缩后的扩展添加到了我的项目中。 我已经成功更改了值;但是仍然没有任何改变!
我没有找到其他类似的变量,但这并不意味着它们不存在。 reCaptcha仍然检测到chromedriver,因此应该有更多变量要更改。 下一步应该是我不想做的探测器服务的逆向工程。
现在,我不确定是否值得在此自动化过程上花费更多时间或寻找替代方法!
答案 8 :(得分:6)
它适用于某些网站,从导航器中删除属性 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;"
})
答案 9 :(得分:5)
即使你发送了所有正确的数据(例如Selenium没有显示为扩展名,你有一个合理的分辨率/位深度,& c),有很多服务和工具可以访问确定演员是用户还是自动系统的行为。
例如,访问一个网站,然后立即通过将鼠标直接移动到相关按钮,在不到一秒的时间内执行某些操作,这是用户实际上无法做到的事情。
作为调试工具,使用https://panopticlick.eff.org/等网站来检查浏览器的独特性也可能很有用;它还可以帮助您验证是否有任何特定参数表明您在Selenium中运行。
答案 10 :(得分:5)
如果使用webdriver,Firefox会设置为window.navigator.webdriver === true
。这是根据一个较旧的规范(例如:archive.org)但我无法在new one中找到它,除了附录中的一些非常含糊的措辞。
对它的测试在文件fingerprint_test.js的selenium代码中,最后的注释表示"目前只在firefox"中实现。但是我无法通过一些简单的grep
来识别该方向的任何代码,无论是在当前(41.0.2)的Firefox版本树还是在Chromium树中。
我还在firefox驱动程序b82512999938 from January 2015中找到了关于指纹识别的旧提交的注释。该代码仍在昨天在javascript/firefox-driver/extension/content/server.js
下载的Selenium GIT-master中,其中的评论链接到当前w3c webdriver规范中略有不同措辞的附录。
答案 11 :(得分:5)
听起来他们是Web应用程序防火墙的幕后推手。看看modsecurity和owasp,看看它们是如何工作的。实际上,您要问的是如何进行机器人检测规避。这不是selenium web驱动程序的用途。它用于测试您的Web应用程序而不是其他Web应用程序。这是可能的,但基本上,您必须查看WAF在其规则集中查找的内容,如果可以,请特别使用硒来避免它。即使这样,它仍然可能无法工作,因为你不知道他们正在使用什么样的WAF。你做了正确的第一步,即伪造用户代理。如果那不起作用,那么WAF已经到位,你可能需要更加棘手。
编辑: 从其他答案中取得的一点。确保首先正确设置了用户代理。也许让它击中本地网络服务器或嗅到流出的流量。
答案 12 :(得分:4)
我见过的机器人检测似乎比我在下面的答案中读到的内容更复杂或至少有所不同。
实验1:
实验2:
和以前一样,我从Python控制台打开浏览器和Selenium的网页。
这一次,我使用Selenium(在Python控制台中)点击具有随机偏移量的相同元素,而不是单击鼠标。
该链接未打开,但我已进入注册页面。
<强>意义:强>
看起来很神秘,但我想他们可以确定一个动作是否来自Selenium,而他们并不关心浏览器本身是否是通过Selenium打开的。或者他们可以确定窗口是否有焦点?如果有人有任何见解,那将会很有趣。
答案 13 :(得分:4)
有些网站正在检测到这一点:
function d() {
try {
if (window.document.$cdc_asdjflasutopfhvcZLmcfl_.cache_)
return !0
} catch (e) {}
try {
//if (window.document.documentElement.getAttribute(decodeURIComponent("%77%65%62%64%72%69%76%65%72")))
if (window.document.documentElement.getAttribute("webdriver"))
return !0
} catch (e) {}
try {
//if (decodeURIComponent("%5F%53%65%6C%65%6E%69%75%6D%5F%49%44%45%5F%52%65%63%6F%72%64%65%72") in window)
if ("_Selenium_IDE_Recorder" in window)
return !0
} catch (e) {}
try {
//if (decodeURIComponent("%5F%5F%77%65%62%64%72%69%76%65%72%5F%73%63%72%69%70%74%5F%66%6E") in document)
if ("__webdriver_script_fn" in document)
return !0
} catch (e) {}
答案 14 :(得分:2)
我发现的另一件事是,某些网站使用检查用户代理的平台。如果值包含:“ HeadlessChrome”,则在使用无头模式时,该行为可能会很奇怪。
解决方法是覆盖用户代理值,例如在Java中: chromeOptions.addArguments(“-user-agent = Mozilla / 5.0(Macintosh; Intel Mac OS X 10_13_6)AppleWebKit / 537.36(KHTML,Gecko一样)Chrome / 73.0.3683.86 Safari / 537.36”);
答案 15 :(得分:2)
使用以下代码编写html页面。您将看到在DOM中,selenium在outerHTML中应用了webdriver属性
<html>
<head>
<script type="text/javascript">
<!--
function showWindow(){
javascript:(alert(document.documentElement.outerHTML));
}
//-->
</script>
</head>
<body>
<form>
<input type="button" value="Show outerHTML" onclick="showWindow()">
</form>
</body>
</html>
答案 16 :(得分:1)
在我看来,使用Selenium做到这一点最简单的方法是拦截XHR,该XHR会发回浏览器指纹。
但是,由于这是仅硒的问题,因此最好使用其他方法。硒应该使这种事情变得容易,而不是更困难。
答案 17 :(得分:1)
除了 @ Erti-Chris Eelmaa 的出色答案之外,还有令人讨厌的window.navigator.webdriver
,它是只读的。事件,如果将其值更改为false
,它将仍然具有true
。因此,仍然可以检测到由自动化软件驱动的浏览器。
MDN
该变量由chrome中的标志--enable-automation
管理。 chromedriver使用该标志启动chrome,然后chrome将window.navigator.webdriver
设置为true
。您可以找到它here。您需要将标记添加到“排除开关”中。例如(golang):
package main
import (
"github.com/tebeka/selenium"
"github.com/tebeka/selenium/chrome"
)
func main() {
caps := selenium.Capabilities{
"browserName": "chrome",
}
chromeCaps := chrome.Capabilities{
Path: "/path/to/chrome-binary",
ExcludeSwitches: []string{"enable-automation"},
}
caps.AddChrome(chromeCaps)
wd, err := selenium.NewRemote(caps, fmt.Sprintf("http://localhost:%d/wd/hub", 4444))
}
答案 18 :(得分:1)
您可以尝试使用参数“启用自动化”
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不会在没有任何黑客攻击的情况下完全阻止。
有关更多信息,请尝试在此处查看:
Selenium webdriver: Modifying navigator.webdriver flag to prevent selenium detection
Unable to hide "Chrome is being controlled by automated software" infobar within Chrome v76
答案 19 :(得分:0)
我发现这样更改javascript“ key”变量:
//Fools the website into believing a human is navigating it
((JavascriptExecutor)driver).executeScript("window.key = \"blahblah\";");
在将Selenium Webdriver和Google Chrome结合使用时,某些网站可以使用,因为许多网站都会检查此变量,以避免被Selenium废弃。
答案 20 :(得分:0)
答案:是
有些网站会根据浏览器的指纹和其他数据检测硒,其他网站会根据行为检测硒,不仅根据您做了什么,还根据您不做什么。
通常使用 selenium 提供的数据就足以检测它。
您可以在此类网站中查看浏览器指纹
https://bot.sannysoft.com
https://fingerprintjs.github.io/fingerprintjs/
https://antoinevastel.com/bots/
尝试使用您的用户浏览器,然后尝试使用 selenium,您会看到不同之处。
您可以使用options()更改一些指纹,例如用户代理等,请自行查看结果。
你可以通过多种方式尝试避免这种检测,我推荐使用这个库:undetected_chromedriver:
https://github.com/ultrafunkamsterdam/undetected-chromedriver
import undetected_chromedriver.v2 as uc
否则您可以尝试使用硒的替代品。我听说过 PhantomJS,但没有尝试过。