有小伙伴说使用selenium没能绕过机器人检测,盘他。
selenium机器人检测有2种,一是cdp检测,二是webdriver特征检测。cdp检测前面的博客已写过,这里就提下webdriver特征检测。
一、selenium简介
Selenium 是一个强大的工具,用于Web浏览器自动化,更常被用于爬虫。
但selenium需要通过webdriver来驱动chrome,每次运行selenium时,都要先找到对应版本的chromedriver.exe。
chromedriver自动化会对浏览器的部分属性进行修改,非常容易被识别为机器人。
pypeeteer却没有这种烦恼,它不需要中间驱动,所以还是建议大家使用pyppeteer。但如果你已经写了上万行selenium代码了,那还是编译一个驱动吧。
二、机器人识别网站
1.https://www.browserscan.net/bot-detection
2.https://fingerprintjs.github.io/BotD/main/
很明显,常规网站都能检测到selenium机器人。
三、检测原理
1:cdp检测,
cdp检测的原理一般是利用console.debug()函数来实现,当你打开consle控制台时,console.debug()才会真正的被调用。
一旦console.debug()函数被触发,我们就可以认定你打开了F12控制台。
<!DOCTYPE html><html><head><title>Detect Chrome DevTools Protocol</title><script>function genNum(e){return1000 * e.Math.random()|0;}function catchCDP(e){if(e.chrome){
var rng1 =0;
var rng2 =1;
var acc = rng1;
var result =false;
try {
var errObj = new e.Error();
var propertyDesc ={
configurable: false,
enumerable: false,
get: function(){
acc += rng2;return'';}};
Object.defineProperty(errObj, "stack", propertyDesc);
console.debug(errObj);
errObj.stack;if(rng1 + rng2 != acc){
result =true;}} catch {}return result;}}functionisCDPOn(){
if(!window)return;
const el = document.querySelector('span#status');
if(!el)return;
el.innerText = catchCDP(window) ? "yes":"no";}functioninit(){
isCDPOn();
setInterval(isCDPOn, 100);}
document.addEventListener("DOMContentLoaded", init);</script></head><body><p>CDP Detected: <span id="status">-</span></p></body></html>
2 :webdriver特征检测
将下面的js代码复制粘贴进F12控制台:
// 定义正则表达式
let regex = /^([a-z]){3}_.*_(Array|Promise|Symbol|JSON|Object|Proxy)$/;
// 获取window对象的所有属性名称
let allProps = Object.getOwnPropertyNames(window);
// 过滤出符合正则表达式的属性名称
let filteredProps = allProps.filter(prop => regex.test(prop));
// 输出匹配的属性名
console.log(filteredProps);
在这里插入图片描述
注意:这就是这2个站检测selenium机器人的核心逻辑。
四、编译crhomedriver.exe
打开chromium源码文件:\chrome\test\chromedriver\chrome\devtools_client_impl.cc
1 绕过cdp检测
找到下面的代码
void V8Console::Debug(const v8::debug::ConsoleCallArguments& info,
const v8::debug::ConsoleContext& consoleContext){
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Debug");
ConsoleHelper(info, consoleContext, m_inspector)
.reportCall(ConsoleAPIType::kDebug);}
替换为
void V8Console::Debug(const v8::debug::ConsoleCallArguments& info,
const v8::debug::ConsoleContext& consoleContext){
//TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.inspector"), "V8Console::Debug");
//ConsoleHelper(info, consoleContext, m_inspector)
// .reportCall(ConsoleAPIType::kDebug);}
2 绕过webdriver特征检测
找到下面的代码
std::string script ="(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;""window.cdc_adoQpoasnfa76pfcZLmcfl_JSON = window.JSON;""}) ();";
params.Set("source", script);
替换为:
std::string script ="(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;"
//"window.cdc_adoQpoasnfa76pfcZLmcfl_JSON = window.JSON;""}) ();";
params.Set("source", script);
3.编译:
ninja -C out/Default chromedriver
注意:编译完后,会在out/Default目录下生成一个chromedriver.exe文件,这就是驱动。
五、验证
将生成的chromedriver.exe拿过来,运行下面的python代码:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
importtime# 指定chromedriver的路径
s = Service(r"chromedriver.exe")# 请将这里替换为你的chromedriver路径# 初始化Chrome选项
chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r"C:\Users\Administrator\AppData\Local\Chromium\Application\chrome.exe"# 请将这里替换为你的Chrome浏览器路径
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--fingerprints=11111111")# 使用Service对象初始化driver
driver = webdriver.Chrome(service=s, options=chrome_options)
driver.delete_all_cookies()# driver.get("https://www.browserscan.net/bot-detection")
driver.get("https://fingerprintjs.github.io/BotD/main/")
time.sleep(99999)
指定chromedriver的路径
s = Service(r"chromedriver.exe") # 请将这里替换为你的chromedriver路径
初始化Chrome选项
chrome_options = webdriver.ChromeOptions()
chrome_options.binary_location = r"C:\Users\Administrator\AppData\Local\Chromium\Application\chrome.exe" # 请将这里替换为你的Chrome浏览器路径
chrome_options.add_argument(“–no-sandbox”)
chrome_options.add_argument(“–fingerprints=11111111”)
使用Service对象初始化driver
driver = webdriver.Chrome(service=s, options=chrome_options)
driver.delete_all_cookies()
driver.get(“https://www.browserscan.net/bot-detection”)
driver.get(“https://fingerprintjs.github.io/BotD/main/”)
time.sleep(99999)
可以看到,依旧是自动化控制,官网却已经检测不到了。browserscan也一样。
六、成品
有能力的小伙伴建议自己把流程全部跑一边,编译个自己的指纹浏览器和驱动。
版权归原作者 风控牛 所有, 如有侵权,请联系我们删除。