当您将 Selenium 与 chromedriver 一起使用时,网站可以检测到吗?
Can a website detect when you are using Selenium with chromedriver?
我一直在用 Chromedriver 测试 Selenium,我注意到有些页面可以检测到您正在使用 Selenium,即使根本没有自动化。即使我只是使用 Chrome 通过 Selenium 和 Xephyr 手动浏览,我也经常收到一个页面,说检测到可疑的 activity。我已经检查了我的用户代理和浏览器指纹,它们都与普通 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,您将在一两个请求中被重定向和 'blocked'。我一直在对此进行调查,但我无法弄清楚他们如何判断用户正在使用 Selenium。
他们是怎么做到的?
我在 Firefox 中安装了 Selenium IDE 插件,但在仅使用附加插件的普通 Firefox 浏览器中访问 stubhub.com 时,我被禁止了。
当我使用 Fiddler 查看来回发送的 HTTP 请求时,我注意到“假浏览器”的请求通常在响应 header 中包含 'no-cache'。
像这样的结果 Is there a way to detect that I'm in a Selenium Webdriver page from JavaScript 表明您在使用网络时应该无法检测到 driver。但这一证据表明情况并非如此。
该站点将指纹上传到他们的服务器,但我检查发现 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 正在 运行 检测硒。
听起来好像他们在 Web 应用程序防火墙后面。看看 modsecurity 和 OWASP 看看它们是如何工作的。
实际上,您问的是如何规避机器人检测。这不是 Selenium WebDriver 的用途。它用于测试您的 Web 应用程序而不影响其他 Web 应用程序。这是可能的,但基本上,你必须看看 WAF 在他们的规则集中寻找什么,如果可以的话,特别要避免使用 selenium。即便如此,它可能仍然无法工作,因为您不知道他们使用的是什么 WAF。
您做对了第一步,即伪造用户代理。如果这不起作用,那么 WAF 已经到位,您可能需要采取更多技巧。
取自其他答案的要点。首先确保您的用户代理确实设置正确。也许让它命中本地网络服务器或嗅探流量。
即使您发送了所有正确的数据(例如,Selenium 没有显示为扩展,您有一个合理的 resolution/bit-depth, &c),也有许多服务和工具可以分析访问者行为来确定参与者是用户还是自动化系统。
例如,访问一个站点然后立即通过将鼠标直接移动到相关按钮来执行某些操作,不到一秒钟,这是用户实际上不会做的事情。
使用诸如 https://panopticlick.eff.org/ 之类的站点来检查您的浏览器的独特性,作为调试工具也可能很有用;它还将帮助您验证是否有任何特定参数表明您在 Selenium 中 运行。
据说如果使用网络驱动程序,Firefox 会设置 window.navigator.webdriver === true
。那是根据一个较旧的规范(例如:archive.org) but I couldn't find it in the new one 除了附录中一些非常模糊的措辞。
在文件 fingerprint_test.js 中的硒代码中对其进行了测试,其中末尾的注释显示 "Currently only implemented in firefox" 但我无法通过一些简单的方法识别该方向的任何代码grep
ing,既不在当前 (41.0.2) Firefox 版本树中,也不在 Chromium 树中。
我还找到了关于 firefox 驱动程序中指纹识别的旧提交的评论 b82512999938 from January 2015。该代码仍在昨天在 javascript/firefox-driver/extension/content/server.js
下载的 Selenium GIT-master 中,其中的评论链接到当前 w3c webdriver 规范中措辞略有不同的附录。
使用以下代码编写一个 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>
尝试将 selenium 与 chrome 的特定用户配置文件一起使用,这样您就可以将其用作特定用户并定义任何您想要的东西,这样做时它将 运行 作为 'real' 用户,使用进程浏览器查看 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 标签列表 here
正如我们已经在问题和 posted 答案中弄清楚的那样,有一个名为 "Distil Networks" in play here. And, according to the company CEO's interview:
的反 Web 抓取和 Bot 检测服务
Even though they can create new bots, we figured out a way to identify
Selenium the a tool they’re using, so we’re blocking Selenium no
matter how many times they iterate on that bot. We’re doing that now
with Python and a lot of different technologies. Once we see a pattern
emerge from one type of bot, then we work to reverse engineer the
technology they use and identify it as malicious.
了解他们检测 Selenium 的准确程度需要时间和额外的挑战,但目前我们可以肯定地说:
- 它与您对 selenium 采取的操作无关 - 一旦您导航到该站点,您就会立即被检测到并被禁止。我试图在操作之间添加人为的随机延迟,在页面加载后暂停 - 没有任何帮助
- 这也与浏览器指纹无关 - 在多个浏览器中尝试过使用干净的配置文件而不是隐身模式 - 没有任何帮助
- 因为根据采访中的提示,这是 "reverse engineering",我怀疑这是通过在浏览器中执行的一些 JS 代码完成的,表明这是一个通过 selenium webdriver 自动运行的浏览器
决定post它作为答案,因为很明显:
Can a website detect when you are using selenium with chromedriver?
是的。
另外,我没有试验过的是较旧的 selenium 和较旧的浏览器版本 - 理论上,在 Distil Networks 机器人检测器当前所依赖的某个点上,selenium 可能有一些 implemented/added。然后,如果是这种情况,我们可能会检测(是的,让我们检测检测器)在什么 point/version 处进行了相关更改,查看更改日志和更改集,并且可能会为我们提供更多信息看看他们用什么来检测 webdriver 驱动的浏览器。这只是一个需要检验的理论。
如何在 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 !+""
基本上,Selenium 检测的工作方式是,它们测试在 运行 Selenium 时出现的预定义 JavaScript 变量。机器人检测脚本通常会在任何变量(在 window 对象上)中查找包含单词“selenium”/“webdriver”的任何内容,并且还会记录名为 $cdc_
和 $wdc_
的变量。当然,所有这些都取决于您使用的浏览器。所有不同的浏览器都会暴露不同的东西。
对我来说,我使用了 Chrome,所以,我必须做的就是确保 $cdc_
不再存在document变量,然后就可以了(下载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;
};
,也可以直接在十六进制编辑器中打开chromedriver.exe,手动替换,而不用实际编译。
partial interface Navigator {
readonly attribute boolean webdriver;
};
The webdriver IDL attribute of the Navigator interface must return the value of the webdriver-active flag, which is initially false.
This property allows websites to determine that the user agent is under control by WebDriver, and can be used to help mitigate denial-of-service attacks.
直接取自2017 W3C Editor's Draft of WebDriver。这在很大程度上意味着,至少,selenium 驱动程序的未来迭代将是可识别的,以防止滥用。最终,如果没有源代码,很难说清楚究竟是什么导致 chrome 驱动程序被检测到。
一些网站正在检测到这个:
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) {}
我看到的机器人检测似乎比我在下面的答案中读到的更复杂或至少不同。
实验 1:
- 我从 Python 控制台使用 Selenium 打开浏览器和网页。
- 鼠标已经在我知道页面加载后会出现 link 的特定位置。 我从不移动鼠标。
- 我按下鼠标左键一次(这是从控制台获取焦点所必需的,其中 Python 是 运行 浏览器)。
- 我再次按下鼠标左键(记住,光标位于给定 link 上方)。
- link 可以正常打开。
实验 2:
和以前一样,我从 Python 控制台打开浏览器和带有 Selenium 的网页。
这一次,我没有使用鼠标单击,而是使用 Selenium(在 Python 控制台中)单击具有随机偏移量的同一元素。
link 没有打开,但我被带到了注册页面。
影响:
- 通过 Selenium 打开 Web 浏览器并不妨碍我看起来像人
- 像人一样移动鼠标不必归类为人
- 通过带有偏移量的 Selenium 单击某些内容仍然会引发警报
看起来很神秘,但我猜他们只能确定一个动作是否源自Selenium,而他们并不关心浏览器本身是否是通过Selenium 打开的。或者他们可以确定 window 是否有焦点吗?很想听听是否有人有任何见解。
替换cdc_
字符串
您可以使用vim
或perl
替换chromedriver
中的cdc_
字符串。 请参阅 了解有关该字符串的更多信息以及它如何成为检测点 。
使用 vim
或 perl
使您不必重新编译源代码或使用十六进制编辑器。
确保在尝试编辑之前复制原件chromedriver
。
我们的目标是改变 cdc_
字符串,它看起来像 $cdc_lasutopfhvcZLmcfl
.
以下方法已在 chromedriver version 2.41.578706
.
上进行测试
使用Vim
vim /path/to/chromedriver
在上面的 运行 行之后,您可能会看到一堆乱码。执行以下操作:
- 通过键入
:%s/cdc_/dog_/g
将 cdc_
的所有实例替换为 dog_
。
dog_
只是一个例子。您可以选择任何字符,只要它与搜索字符串的字符数相同(例如 cdc_
),否则 chromedriver
将失败。
- 要保存更改并退出,请键入
:wq!
并按 return
。
- 如果您需要退出而不保存更改,请键入
:q!
并按 return
。
使用 Perl
下面的行将所有出现的 cdc_
替换为 dog_
。感谢:
perl -pi -e 's/cdc_/dog_/g' /path/to/chromedriver
确保替换字符串(如dog_
)与搜索字符串(如cdc_
)的字符数相同,否则chromedriver
将失败。
总结
验证所有出现的 cdc_
都被替换:
grep "cdc_" /path/to/chromedriver
如果没有返回输出,表示替换成功
转到更改后的 chromedriver
并双击它。终端 window 应该会打开。如果您在输出中没有看到 killed
,则您已成功更改驱动程序。
确保更改后的 chromedriver
二进制文件的名称是 chromedriver
,并且原始二进制文件已从其原始位置移动或重命名。
我使用此方法的经验
我之前在尝试登录时在网站上被检测到,但在用相同大小的字符串替换 cdc_
后,我能够登录。就像其他人所说的那样,如果你有已经被检测到,即使在使用此方法后,您也可能会由于多种其他原因而被阻止。因此,您可能必须尝试访问使用 VPN、不同网络等检测到您的站点。
在我看来,使用 Selenium 最简单的方法是拦截发回浏览器指纹的 XHR。
但由于这是一个仅限于 Selenium 的问题,最好还是使用其他东西。 Selenium 应该使这样的事情变得更容易,而不是更难。
混淆 JavaScript 结果
我检查了chrome驱动源代码。这会向浏览器注入一些 javascript 文件。
此 link 上的每个 javascript 文件都被注入网页:
https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver/js/
所以我使用了逆向工程,并通过十六进制编辑混淆js文件。现在我确定不再使用 javascript 变量、函数名称和固定字符串来发现 selenium activity。但仍有一些网站和 reCaptcha 检测到硒!
也许他们会检查由 chromedriver js 执行引起的修改:)
编辑 1:
Chrome 'navigator'参数修改
我发现 'navigator' 中有一些参数可以简单地揭示 chrome 驱动程序的使用。
这些是参数:
- "navigator.webdriver" 在非自动模式下为 'undefined'。在自动模式下它是 'true'.
- "navigator.plugins" 无头 chrome 的长度为 0。所以我添加了一些假元素来欺骗插件长度检查过程。
- "navigator.languages" 已设置为默认 chrome 值 '["en-US", "en", "es"]' .
所以我需要的是在网页上对 运行 javascript 进行 chrome 扩展。我使用 js code provided in the article and used another article 进行了扩展以将压缩扩展添加到我的项目中。 我已成功更改值;但还是没有任何改变!
我没有找到像这样的其他变量,但这并不意味着它们不存在。仍然 reCaptcha 检测到 chrome 驱动程序,因此应该有更多变量需要更改。 下一步 应该是我不想做的检测器服务的逆向工程。
现在我不确定是否值得花更多时间在这个自动化过程上或寻找替代方法!
除了 - 还有令人讨厌的 window.navigator.webdriver
并且它是只读的。如果您将其值更改为 false
,事件仍将具有 true
。这就是为什么自动化软件驱动的浏览器仍然可以被检测到的原因。
变量由chrome中的标志--enable-automation
管理。 chrome 驱动程序使用该标志启动 Chrome 并且 Chrome 将 window.navigator.webdriver
设置为 true
。你可以找到它 here. You need to add to "exclude switches" the flag. For instance (Go):
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))
}
我发现的另一件事是,某些网站使用检查用户代理的平台。如果该值包含:"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");
我发现像这样更改 JavaScript“关键”变量:
//Fools the website into believing a human is navigating it
((JavascriptExecutor)driver).executeScript("window.key = \"blahblah\";");
在将 Selenium WebDriver 与 Google Chrome 一起使用时适用于某些网站,因为许多网站会检查此变量以避免被 Selenium 抓取。
你可以尝试使用参数"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 没有任何黑客攻击根本不会阻止。
有关更多信息,请尝试查看此处:
关于被检测到由 controlled 驱动的网站,已经进行了很多分析和讨论。这是我的两分钱:
根据文章 Browser detection using the user agent 为不同的浏览器提供不同的网页或服务通常不是最好的主意。无论用户使用哪种浏览器或设备,每个人都可以访问网络。概述了开发网站以根据功能可用性而不是针对特定浏览器逐步增强自身的最佳实践。
然而,浏览器和标准并不完美,仍然存在一些边缘情况,一些网站仍然检测到浏览器,如果浏览器由 Selenium 驱动 .可以通过不同的方式检测浏览器,一些常用的机制如下:
You can find a relevant detailed discussion in How does recaptcha 3 know I'm using selenium/chromedriver?
- 检测 HeadlessChrome 在 headless Chrome UserAgent
中
You can find a relevant detailed discussion in
- 使用来自 Distil Networks
的 Bot 管理服务
You can find a relevant detailed discussion in
- 使用来自 Akamai
的 Bot Manager 服务
You can find a relevant detailed discussion in
- 使用来自 Datadome
的 Bot Protection 服务
You can find a relevant detailed discussion in Website using DataDome gets captcha blocked while scraping using Selenium and Python
不过,用user-agent检测浏览器,看似简单,做好其实有点难。
Note: At this point it's worth to mention that: it's very rarely a good idea to use user agent sniffing. There are always better and more broadly compatible way to address a certain issue.
浏览器检测注意事项
检测浏览器背后的想法可以是以下之一:
- 尝试解决网络浏览器的某些特定变体或特定版本中的特定错误。
- 正在尝试检查是否存在某些浏览器尚不支持的特定功能。
- 尝试根据使用的浏览器提供不同的 HTML。
通过 UserAgents 检测浏览器的替代方法
浏览器检测的部分备选方案如下:
- 实施测试以检测浏览器如何实施某项功能的 API 并确定如何使用该功能。一个例子是 Chrome unflagged experimental lookbehind support in regular expressions.
- 采用渐进增强的设计技术,这将涉及在层中开发一个网站,使用自下而上的方法,从一个更简单的层,并在连续的层中改进站点的功能,每个层使用更多的功能。
- 采用自上而下的优雅降级方法,我们使用我们想要的所有功能构建尽可能最好的网站,然后对其进行调整以使其在旧浏览器上运行。
解决方案
为了防止 Selenium 驱动的 WebDriver 被检测到,一个利基方法将包括 either/all 下面提到的方法:
在使用 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()
You can find a relevant detailed discussion in
使用Network.setUserAgentOverride
到execute_cdp_cmd()
在每个测试中轮换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;"))
You can find a relevant detailed discussion in
将 webdriver navigator
的 属性 值更改为 undefined
如下:
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
"source": """
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
"""
})
You can find a relevant detailed discussion in
- 更改
navigator.plugins
、navigator.languages
、WebGL[=140] 的值=]、发际线特征、图像缺失等
You can find a relevant detailed discussion in
- 改变常规Viewport
You can find a relevant detailed discussion in
处理 reCAPTCHA
在处理与文本 我不是机器人 关联的 2captcha and recaptcha-v3 rather clicking on checkbox 时,提取和使用 data-sitekey
可能更容易获得身份验证.
You can find a relevant detailed discussion in
tl;博士
您可以在以下位置找到逃避 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;"
})
回答:是
有些网站会通过浏览器的指纹和其他数据来检测 selenium,其他网站会根据行为来检测 selenium,不仅根据您做了什么,还根据您没有做什么。
通常用selenium提供的数据就可以检测到。
您可以在此类网站中检查浏览器指纹
https://bot.sannysoft.com
https://fingerprintjs.github.io/fingerprintjs/
https://antoinevastel.com/bots/
尝试使用您的用户浏览器,然后尝试使用 selenium,您会看到不同之处。
有些指纹可以通过options()修改,比如user agent之类的,自己看效果。
你可以尝试通过多种方式避免这种检测,我推荐使用这种方式library:undetected_chromedriver:
https://github.com/ultrafunkamsterdam/undetected-chromedriver
import undetected_chromedriver.v2 as uc
否则您可以尝试使用硒的替代品。听说过PhantomJS,没试过
我有同样的问题,并通过以下配置解决了问题(在 c# 中)
options.AddArguments("start-maximized");
options.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");
options.AddExcludedArgument("enable-automation");//for hiding chrome being controlled by automation..
options.AddAdditionalCapability("useAutomationExtension", false);
//import cookies
options.AddArguments("user-data-dir=" + userDataDir);
options.AddArguments("profile-directory=" + profileDir);
随着 Selenium Stealth evading the detection of driven initiated google-chrome 浏览上下文 的可用性变得更加容易。
selenium-stealth
selenium-stealth 是一个 python 包来防止检测。该程序试图使 python selenium 更加隐蔽。但是,截至目前,selenium-stealth 仅支持 Selenium Chrome.
目前 selenium-stealth 可以提供的功能:
selenium-stealth with stealth 通过所有 public 机器人测试。
用selenium-stealth selenium可以做google账号登录。
selenium-stealth 有助于维持正常的 reCAPTCHA v3 分数
安装
PyPI 上提供了 Selenium-stealth,因此您可以按如下方式使用 pip 安装:
$ pip install selenium-stealth
selenium4 compatible code
代码块:
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/")
浏览器截图:
tl;博士
您可以在以下位置找到一些相关的详细讨论:
- How to automate login to a site which is detecting my attempts to login using selenium-stealth
我所要做的就是:
my_options = webdriver.ChromeOptions()
my_options.add_argument( '--disable-blink-features=AutomationControlled' )
更多信息:这与网站 skyscanner.com 有关。在过去,我已经能够刮掉它。是的,它确实检测到浏览器自动化,它给了我一个验证码来按住一个按钮。我曾经能够手动完成验证码,然后搜索航班然后抓取。但是这次在完成验证码后我一次又一次地得到相同的验证码,似乎无法逃脱它。我尝试了一些最流行的建议来避免检测到自动化,但它们没有用。然后我发现 this article 确实有效,通过排除过程我发现它只采用了上面的选项来绕过他们的浏览器自动检测。现在我什至没有得到验证码,其他一切似乎都正常工作。
我目前 运行 的版本:
- OS: Windows 7 64 位
- 浏览器:Chrome版本100.0.4896.60(官方
构建)(64 位)
- 硒 4.1.3
- Chrome驱动程序 100.0.4896.60 chromedriver_win32.zip 930ff33ae8babeaa74e0dd1ce1dae7ff
我一直在用 Chromedriver 测试 Selenium,我注意到有些页面可以检测到您正在使用 Selenium,即使根本没有自动化。即使我只是使用 Chrome 通过 Selenium 和 Xephyr 手动浏览,我也经常收到一个页面,说检测到可疑的 activity。我已经检查了我的用户代理和浏览器指纹,它们都与普通 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,您将在一两个请求中被重定向和 'blocked'。我一直在对此进行调查,但我无法弄清楚他们如何判断用户正在使用 Selenium。
他们是怎么做到的?
我在 Firefox 中安装了 Selenium IDE 插件,但在仅使用附加插件的普通 Firefox 浏览器中访问 stubhub.com 时,我被禁止了。
当我使用 Fiddler 查看来回发送的 HTTP 请求时,我注意到“假浏览器”的请求通常在响应 header 中包含 'no-cache'。
像这样的结果 Is there a way to detect that I'm in a Selenium Webdriver page from JavaScript 表明您在使用网络时应该无法检测到 driver。但这一证据表明情况并非如此。
该站点将指纹上传到他们的服务器,但我检查发现 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 正在 运行 检测硒。
听起来好像他们在 Web 应用程序防火墙后面。看看 modsecurity 和 OWASP 看看它们是如何工作的。
实际上,您问的是如何规避机器人检测。这不是 Selenium WebDriver 的用途。它用于测试您的 Web 应用程序而不影响其他 Web 应用程序。这是可能的,但基本上,你必须看看 WAF 在他们的规则集中寻找什么,如果可以的话,特别要避免使用 selenium。即便如此,它可能仍然无法工作,因为您不知道他们使用的是什么 WAF。
您做对了第一步,即伪造用户代理。如果这不起作用,那么 WAF 已经到位,您可能需要采取更多技巧。
取自其他答案的要点。首先确保您的用户代理确实设置正确。也许让它命中本地网络服务器或嗅探流量。
即使您发送了所有正确的数据(例如,Selenium 没有显示为扩展,您有一个合理的 resolution/bit-depth, &c),也有许多服务和工具可以分析访问者行为来确定参与者是用户还是自动化系统。
例如,访问一个站点然后立即通过将鼠标直接移动到相关按钮来执行某些操作,不到一秒钟,这是用户实际上不会做的事情。
使用诸如 https://panopticlick.eff.org/ 之类的站点来检查您的浏览器的独特性,作为调试工具也可能很有用;它还将帮助您验证是否有任何特定参数表明您在 Selenium 中 运行。
据说如果使用网络驱动程序,Firefox 会设置 window.navigator.webdriver === true
。那是根据一个较旧的规范(例如:archive.org) but I couldn't find it in the new one 除了附录中一些非常模糊的措辞。
在文件 fingerprint_test.js 中的硒代码中对其进行了测试,其中末尾的注释显示 "Currently only implemented in firefox" 但我无法通过一些简单的方法识别该方向的任何代码grep
ing,既不在当前 (41.0.2) Firefox 版本树中,也不在 Chromium 树中。
我还找到了关于 firefox 驱动程序中指纹识别的旧提交的评论 b82512999938 from January 2015。该代码仍在昨天在 javascript/firefox-driver/extension/content/server.js
下载的 Selenium GIT-master 中,其中的评论链接到当前 w3c webdriver 规范中措辞略有不同的附录。
使用以下代码编写一个 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>
尝试将 selenium 与 chrome 的特定用户配置文件一起使用,这样您就可以将其用作特定用户并定义任何您想要的东西,这样做时它将 运行 作为 'real' 用户,使用进程浏览器查看 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 标签列表 here
正如我们已经在问题和 posted 答案中弄清楚的那样,有一个名为 "Distil Networks" in play here. And, according to the company CEO's interview:
的反 Web 抓取和 Bot 检测服务Even though they can create new bots, we figured out a way to identify Selenium the a tool they’re using, so we’re blocking Selenium no matter how many times they iterate on that bot. We’re doing that now with Python and a lot of different technologies. Once we see a pattern emerge from one type of bot, then we work to reverse engineer the technology they use and identify it as malicious.
了解他们检测 Selenium 的准确程度需要时间和额外的挑战,但目前我们可以肯定地说:
- 它与您对 selenium 采取的操作无关 - 一旦您导航到该站点,您就会立即被检测到并被禁止。我试图在操作之间添加人为的随机延迟,在页面加载后暂停 - 没有任何帮助
- 这也与浏览器指纹无关 - 在多个浏览器中尝试过使用干净的配置文件而不是隐身模式 - 没有任何帮助
- 因为根据采访中的提示,这是 "reverse engineering",我怀疑这是通过在浏览器中执行的一些 JS 代码完成的,表明这是一个通过 selenium webdriver 自动运行的浏览器
决定post它作为答案,因为很明显:
Can a website detect when you are using selenium with chromedriver?
是的。
另外,我没有试验过的是较旧的 selenium 和较旧的浏览器版本 - 理论上,在 Distil Networks 机器人检测器当前所依赖的某个点上,selenium 可能有一些 implemented/added。然后,如果是这种情况,我们可能会检测(是的,让我们检测检测器)在什么 point/version 处进行了相关更改,查看更改日志和更改集,并且可能会为我们提供更多信息看看他们用什么来检测 webdriver 驱动的浏览器。这只是一个需要检验的理论。
如何在 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 !+""
基本上,Selenium 检测的工作方式是,它们测试在 运行 Selenium 时出现的预定义 JavaScript 变量。机器人检测脚本通常会在任何变量(在 window 对象上)中查找包含单词“selenium”/“webdriver”的任何内容,并且还会记录名为 $cdc_
和 $wdc_
的变量。当然,所有这些都取决于您使用的浏览器。所有不同的浏览器都会暴露不同的东西。
对我来说,我使用了 Chrome,所以,我必须做的就是确保 $cdc_
不再存在document变量,然后就可以了(下载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;
};
partial interface Navigator { readonly attribute boolean webdriver; };
The webdriver IDL attribute of the Navigator interface must return the value of the webdriver-active flag, which is initially false.
This property allows websites to determine that the user agent is under control by WebDriver, and can be used to help mitigate denial-of-service attacks.
直接取自2017 W3C Editor's Draft of WebDriver。这在很大程度上意味着,至少,selenium 驱动程序的未来迭代将是可识别的,以防止滥用。最终,如果没有源代码,很难说清楚究竟是什么导致 chrome 驱动程序被检测到。
一些网站正在检测到这个:
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) {}
我看到的机器人检测似乎比我在下面的答案中读到的更复杂或至少不同。
实验 1:
- 我从 Python 控制台使用 Selenium 打开浏览器和网页。
- 鼠标已经在我知道页面加载后会出现 link 的特定位置。 我从不移动鼠标。
- 我按下鼠标左键一次(这是从控制台获取焦点所必需的,其中 Python 是 运行 浏览器)。
- 我再次按下鼠标左键(记住,光标位于给定 link 上方)。
- link 可以正常打开。
实验 2:
和以前一样,我从 Python 控制台打开浏览器和带有 Selenium 的网页。
这一次,我没有使用鼠标单击,而是使用 Selenium(在 Python 控制台中)单击具有随机偏移量的同一元素。
link 没有打开,但我被带到了注册页面。
影响:
- 通过 Selenium 打开 Web 浏览器并不妨碍我看起来像人
- 像人一样移动鼠标不必归类为人
- 通过带有偏移量的 Selenium 单击某些内容仍然会引发警报
看起来很神秘,但我猜他们只能确定一个动作是否源自Selenium,而他们并不关心浏览器本身是否是通过Selenium 打开的。或者他们可以确定 window 是否有焦点吗?很想听听是否有人有任何见解。
替换cdc_
字符串
您可以使用vim
或perl
替换chromedriver
中的cdc_
字符串。 请参阅
使用 vim
或 perl
使您不必重新编译源代码或使用十六进制编辑器。
确保在尝试编辑之前复制原件chromedriver
。
我们的目标是改变 cdc_
字符串,它看起来像 $cdc_lasutopfhvcZLmcfl
.
以下方法已在 chromedriver version 2.41.578706
.
使用Vim
vim /path/to/chromedriver
在上面的 运行 行之后,您可能会看到一堆乱码。执行以下操作:
- 通过键入
:%s/cdc_/dog_/g
将cdc_
的所有实例替换为dog_
。dog_
只是一个例子。您可以选择任何字符,只要它与搜索字符串的字符数相同(例如cdc_
),否则chromedriver
将失败。
- 要保存更改并退出,请键入
:wq!
并按return
。- 如果您需要退出而不保存更改,请键入
:q!
并按return
。
- 如果您需要退出而不保存更改,请键入
使用 Perl
下面的行将所有出现的 cdc_
替换为 dog_
。感谢
perl -pi -e 's/cdc_/dog_/g' /path/to/chromedriver
确保替换字符串(如dog_
)与搜索字符串(如cdc_
)的字符数相同,否则chromedriver
将失败。
总结
验证所有出现的 cdc_
都被替换:
grep "cdc_" /path/to/chromedriver
如果没有返回输出,表示替换成功
转到更改后的 chromedriver
并双击它。终端 window 应该会打开。如果您在输出中没有看到 killed
,则您已成功更改驱动程序。
确保更改后的 chromedriver
二进制文件的名称是 chromedriver
,并且原始二进制文件已从其原始位置移动或重命名。
我使用此方法的经验
我之前在尝试登录时在网站上被检测到,但在用相同大小的字符串替换 cdc_
后,我能够登录。就像其他人所说的那样,如果你有已经被检测到,即使在使用此方法后,您也可能会由于多种其他原因而被阻止。因此,您可能必须尝试访问使用 VPN、不同网络等检测到您的站点。
在我看来,使用 Selenium 最简单的方法是拦截发回浏览器指纹的 XHR。
但由于这是一个仅限于 Selenium 的问题,最好还是使用其他东西。 Selenium 应该使这样的事情变得更容易,而不是更难。
混淆 JavaScript 结果
我检查了chrome驱动源代码。这会向浏览器注入一些 javascript 文件。
此 link 上的每个 javascript 文件都被注入网页:
https://chromium.googlesource.com/chromium/src/+/master/chrome/test/chromedriver/js/
所以我使用了逆向工程,并通过十六进制编辑混淆js文件。现在我确定不再使用 javascript 变量、函数名称和固定字符串来发现 selenium activity。但仍有一些网站和 reCaptcha 检测到硒!
也许他们会检查由 chromedriver js 执行引起的修改:)
编辑 1:
Chrome 'navigator'参数修改
我发现 'navigator' 中有一些参数可以简单地揭示 chrome 驱动程序的使用。 这些是参数:
- "navigator.webdriver" 在非自动模式下为 'undefined'。在自动模式下它是 'true'.
- "navigator.plugins" 无头 chrome 的长度为 0。所以我添加了一些假元素来欺骗插件长度检查过程。
- "navigator.languages" 已设置为默认 chrome 值 '["en-US", "en", "es"]' .
所以我需要的是在网页上对 运行 javascript 进行 chrome 扩展。我使用 js code provided in the article and used another article 进行了扩展以将压缩扩展添加到我的项目中。 我已成功更改值;但还是没有任何改变!
我没有找到像这样的其他变量,但这并不意味着它们不存在。仍然 reCaptcha 检测到 chrome 驱动程序,因此应该有更多变量需要更改。 下一步 应该是我不想做的检测器服务的逆向工程。
现在我不确定是否值得花更多时间在这个自动化过程上或寻找替代方法!
除了 window.navigator.webdriver
并且它是只读的。如果您将其值更改为 false
,事件仍将具有 true
。这就是为什么自动化软件驱动的浏览器仍然可以被检测到的原因。
变量由chrome中的标志--enable-automation
管理。 chrome 驱动程序使用该标志启动 Chrome 并且 Chrome 将 window.navigator.webdriver
设置为 true
。你可以找到它 here. You need to add to "exclude switches" the flag. For instance (Go):
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))
}
我发现的另一件事是,某些网站使用检查用户代理的平台。如果该值包含:"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");
我发现像这样更改 JavaScript“关键”变量:
//Fools the website into believing a human is navigating it
((JavascriptExecutor)driver).executeScript("window.key = \"blahblah\";");
在将 Selenium WebDriver 与 Google Chrome 一起使用时适用于某些网站,因为许多网站会检查此变量以避免被 Selenium 抓取。
你可以尝试使用参数"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 没有任何黑客攻击根本不会阻止。
有关更多信息,请尝试查看此处:
关于被检测到由
根据文章 Browser detection using the user agent 为不同的浏览器提供不同的网页或服务通常不是最好的主意。无论用户使用哪种浏览器或设备,每个人都可以访问网络。概述了开发网站以根据功能可用性而不是针对特定浏览器逐步增强自身的最佳实践。
然而,浏览器和标准并不完美,仍然存在一些边缘情况,一些网站仍然检测到浏览器,如果浏览器由 Selenium 驱动
You can find a relevant detailed discussion in How does recaptcha 3 know I'm using selenium/chromedriver?
- 检测 HeadlessChrome 在 headless Chrome UserAgent 中
You can find a relevant detailed discussion in
- 使用来自 Distil Networks 的 Bot 管理服务
You can find a relevant detailed discussion in
- 使用来自 Akamai 的 Bot Manager 服务
You can find a relevant detailed discussion in
- 使用来自 Datadome 的 Bot Protection 服务
You can find a relevant detailed discussion in Website using DataDome gets captcha blocked while scraping using Selenium and Python
不过,用user-agent检测浏览器,看似简单,做好其实有点难。
Note: At this point it's worth to mention that: it's very rarely a good idea to use user agent sniffing. There are always better and more broadly compatible way to address a certain issue.
浏览器检测注意事项
检测浏览器背后的想法可以是以下之一:
- 尝试解决网络浏览器的某些特定变体或特定版本中的特定错误。
- 正在尝试检查是否存在某些浏览器尚不支持的特定功能。
- 尝试根据使用的浏览器提供不同的 HTML。
通过 UserAgents 检测浏览器的替代方法
浏览器检测的部分备选方案如下:
- 实施测试以检测浏览器如何实施某项功能的 API 并确定如何使用该功能。一个例子是 Chrome unflagged experimental lookbehind support in regular expressions.
- 采用渐进增强的设计技术,这将涉及在层中开发一个网站,使用自下而上的方法,从一个更简单的层,并在连续的层中改进站点的功能,每个层使用更多的功能。
- 采用自上而下的优雅降级方法,我们使用我们想要的所有功能构建尽可能最好的网站,然后对其进行调整以使其在旧浏览器上运行。
解决方案
为了防止 Selenium 驱动的 WebDriver 被检测到,一个利基方法将包括 either/all 下面提到的方法:
在使用
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()
You can find a relevant detailed discussion in
使用
Network.setUserAgentOverride
到execute_cdp_cmd()
在每个测试中轮换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;"))
You can find a relevant detailed discussion in
将 webdriver
navigator
的 属性 值更改为undefined
如下:driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", { "source": """ Object.defineProperty(navigator, 'webdriver', { get: () => undefined }) """ })
You can find a relevant detailed discussion in
- 更改
navigator.plugins
、navigator.languages
、WebGL[=140] 的值=]、发际线特征、图像缺失等
You can find a relevant detailed discussion in
- 改变常规Viewport
You can find a relevant detailed discussion in
处理 reCAPTCHA
在处理与文本 我不是机器人 关联的 2captcha and recaptcha-v3 rather clicking on checkbox 时,提取和使用 data-sitekey
可能更容易获得身份验证.
You can find a relevant detailed discussion in
tl;博士
您可以在以下位置找到逃避 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;"
})
回答:是
有些网站会通过浏览器的指纹和其他数据来检测 selenium,其他网站会根据行为来检测 selenium,不仅根据您做了什么,还根据您没有做什么。
通常用selenium提供的数据就可以检测到。
您可以在此类网站中检查浏览器指纹
https://bot.sannysoft.com
https://fingerprintjs.github.io/fingerprintjs/
https://antoinevastel.com/bots/
尝试使用您的用户浏览器,然后尝试使用 selenium,您会看到不同之处。
有些指纹可以通过options()修改,比如user agent之类的,自己看效果。
你可以尝试通过多种方式避免这种检测,我推荐使用这种方式library:undetected_chromedriver:
https://github.com/ultrafunkamsterdam/undetected-chromedriver
import undetected_chromedriver.v2 as uc
否则您可以尝试使用硒的替代品。听说过PhantomJS,没试过
我有同样的问题,并通过以下配置解决了问题(在 c# 中)
options.AddArguments("start-maximized");
options.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");
options.AddExcludedArgument("enable-automation");//for hiding chrome being controlled by automation..
options.AddAdditionalCapability("useAutomationExtension", false);
//import cookies
options.AddArguments("user-data-dir=" + userDataDir);
options.AddArguments("profile-directory=" + profileDir);
随着 Selenium Stealth evading the detection of
selenium-stealth
selenium-stealth 是一个 python 包来防止检测。该程序试图使 python selenium 更加隐蔽。但是,截至目前,selenium-stealth 仅支持 Selenium Chrome.
目前 selenium-stealth 可以提供的功能:
selenium-stealth with stealth 通过所有 public 机器人测试。
用selenium-stealth selenium可以做google账号登录。
selenium-stealth 有助于维持正常的 reCAPTCHA v3 分数
安装
PyPI 上提供了 Selenium-stealth,因此您可以按如下方式使用 pip 安装:
$ pip install selenium-stealth
selenium4 compatible code
代码块:
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/")
浏览器截图:
tl;博士
您可以在以下位置找到一些相关的详细讨论:
- How to automate login to a site which is detecting my attempts to login using selenium-stealth
我所要做的就是:
my_options = webdriver.ChromeOptions()
my_options.add_argument( '--disable-blink-features=AutomationControlled' )
更多信息:这与网站 skyscanner.com 有关。在过去,我已经能够刮掉它。是的,它确实检测到浏览器自动化,它给了我一个验证码来按住一个按钮。我曾经能够手动完成验证码,然后搜索航班然后抓取。但是这次在完成验证码后我一次又一次地得到相同的验证码,似乎无法逃脱它。我尝试了一些最流行的建议来避免检测到自动化,但它们没有用。然后我发现 this article 确实有效,通过排除过程我发现它只采用了上面的选项来绕过他们的浏览器自动检测。现在我什至没有得到验证码,其他一切似乎都正常工作。
我目前 运行 的版本:
- OS: Windows 7 64 位
- 浏览器:Chrome版本100.0.4896.60(官方 构建)(64 位)
- 硒 4.1.3
- Chrome驱动程序 100.0.4896.60 chromedriver_win32.zip 930ff33ae8babeaa74e0dd1ce1dae7ff