我问这个是因为我知道这个线程和这个线程,以及其他关于同一主题的线程,但是每个人在第一个线程中转发的解决方案不再有效。因此,请不要将其标记为已关闭,因为第一个线程存在。答案是从 2016 年开始的,您可以看到最近的评论遇到问题。
我正在使用硒来做一些轻便的网页抓取。我正在与之交互的一个站点清楚地检测到我的浏览器是自动化的(但奇怪的是,只要我也访问我所在地区以外的站点版本,它就只关心,但这既不在这里也不在那里(。
第一个线程中的解决方案建议从此处下载的chromedriver并进行修改。它说要摆脱对带有"$cdc$"的变量的提及。所以我做了以下几点。从该站点下载v2.41,解压缩。这个版本允许我通过br = webdriver.Chrome('./chromedriver')
使用带有硒的Chrome,但存在自动化检测问题。所以,我cp
这个来修改chromedriver。
在 chromedriver 修改中,我使用 vim 打开它并搜索$cdc。我发现一个与第 1934 行左右链接线程中的函数相似(但略有不同(的函数:
function getPageCache(opt_doc, opt_w3c) {
var doc = opt_doc || document;
var w3c = opt_w3c || false;
// var key = '$cdc_asdjflasutopfhvcZLmcfl_';
var key = 'xxxx_asdjflasutopfhvcZLmcfl_';
// var key = 'randomblahhh_';
if (w3c) {
if (!(key in doc))
doc[key] = new CacheWithUUID();
return doc[key];
} else {
if (!(key in doc))
doc[key] = new Cache();
return doc[key];
}
}
我尝试用随机的东西(randomblahhh_
var(和只替换$cdc
的前 4 个字符的东西替换这个变量,因为我在该线程的评论中看到两者都建议(我不知道变量的某些格式在这里是否重要。
两者都不起作用。我的意思是,当我尝试使用chromedriver-modified
运行它时,网络驱动程序甚至不会启动:
>>> from selenium import webdriver
>>> br = webdriver.Chrome(executable_path='./chromedriver-modified')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3/dist-packages/selenium/webdriver/chrome/webdriver.py", line 68, in __init__
self.service.start()
File "/usr/lib/python3/dist-packages/selenium/webdriver/common/service.py", line 96, in start
self.assert_process_still_running()
File "/usr/lib/python3/dist-packages/selenium/webdriver/common/service.py", line 109, in assert_process_still_running
% (self.path, return_code)
selenium.common.exceptions.WebDriverException: Message: Service ./chromedriver-modified unexpectedly exited. Status code was: -11
我在谷歌上搜索并弄清楚这个状态代码的含义时遇到了麻烦。事实上,我发现这个未回答的 reddit 线程具有相同的确切问题。
第一个线程也提到了$wdc变量,但我在 chromedriver 中没有提到它们。
只是为了抢占可能的建议:我几乎 100% 确信它检测到我正在使用自动浏览器,因为它是自动化的,而不是因为鼠标点击速度或其他任何东西。如果我使用硒启动浏览器,然后手动完成其余的工作,它仍然会导致问题。
编辑:我正在使用来自Ubuntu存储库的Chrome v68,google-chrome-stable。老实说,我不需要专门使用Chrome,但我找到的答案似乎围绕着它而不是Firefox。
edit2:最后一条评论 - 我在第一个链接线程中注意到有些人正在"重新编译":
对我来说,我使用了chrome,所以,我所要做的就是确保 $cdc_ 不再作为文档变量存在,瞧(下载 Chrome Driver 源代码,修改 Chrome Driver 并重新编译 $cdc_ 以不同的名称。
我不确定这意味着什么 - 他们是否在重新编译Chrome本身?我所做的只是更改chromedriver文件中的变量。
删除
有多种可行的方法
1. 使用 chrome-developer-protocoll 和Page.removeScriptToEvaluateOnNewDocument
就像在硒配置文件中一样
使用蟒蛇
# driver allready initialized here
driver.execute_cdp_cmd("Page.removeScriptToEvaluateOnNewDocument", {"identifier":"1"})
请参阅其他编程语言的文档
2. 使用 chrome-developer-protocoll 与Page.addScriptToEvaluateOnNewDocument
使用来自未检测到的 chromedriver 的脚本
使用蟒蛇
# driver allready initialized here
js = """
let objectToInspect = window,
result = [];
while(objectToInspect !== null)
{ result = result.concat(Object.getOwnPropertyNames(objectToInspect));
objectToInspect = Object.getPrototypeOf(objectToInspect); }
result.forEach(p => p.match(/.+_.+_(Array|Promise|Symbol)/ig)
&&delete window[p]&&console.log('removed',p))
"""
driver.execute_cdp_cmd("Page.removeScriptToEvaluateOnNewDocument", {"source":js})
请注意,这个可能是可检测到的。
3.通过修补编译的chrome驱动程序。
这意味着只需删除 chromedriver-binary :) 中出现的所有cdc_
*
有关Python脚本,请参阅 undetected_chromedriver/patcher.py
详
window.cdc_adoQpoasnfa76pfcZLmcfl_
xxxxx 变量从每个新页面上的 chromedriver 添加,使用带有脚本Page.addScriptToEvaluateOnNewDocument
的 chrome-developer-protocoll:
(function () {
window.cdc_adoQpoasnfa76pfcZLmcfl_Array = window.Array;
window.cdc_adoQpoasnfa76pfcZLmcfl_Object = window.Object;
window.cdc_adoQpoasnfa76pfcZLmcfl_Promise = window.Promise;
window.cdc_adoQpoasnfa76pfcZLmcfl_Proxy = window.Proxy;
window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol = window.Symbol;
}) ();
幸运的是,它总是第一个脚本==>identifier="1"
。这也是为什么1.方法有效。
它们似乎被硬编码到chromedriver中并用于制作shure,如果javascript属性被覆盖代码,chromedriver仍然可以工作
注意:我是Selenium-Profiles的开发者
除非您想构造具有某些功能的单个 chrome,否则无需再次重新编译它。尝试将$cdc_asdjflasutopfhvcZLmcfl_
更改为$abc_asdjflasutopfhvcZLmcfl_
.
请记住不要注意此行或将其更改为具有不同长度的其他变量名称。由于编译的文件对此很敏感,这可能会导致运行错误。