【chromedriver编译-绕过selenium机器人检测】

有小伙伴说使用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控制台。

bash 复制代码
<!DOCTYPE html>
<html>

<head>
	<title>Detect Chrome DevTools Protocol</title>
	<script>
		function genNum(e) {
			return 1000 * 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;
			}
		}
		function isCDPOn() {
			if(!window)
				return;
			const el = document.querySelector('span#status');
			if(!el)
				return;
			el.innerText = catchCDP(window) ? "yes":"no";
		}
		function init() {
			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控制台:
bash 复制代码
// 定义正则表达式
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检测

找到下面的代码

bash 复制代码
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);
}

替换为

bash 复制代码
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特征检测

找到下面的代码

bash 复制代码
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);

替换为:

bash 复制代码
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代码:
bash 复制代码
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import time

# 指定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也一样。

六、成品

有能力的小伙伴建议自己把流程全部跑一边,编译个自己的指纹浏览器和驱动。
相关推荐
鲨鱼辣椒不吃辣c1 分钟前
拦截器魔法:Spring MVC中的防重放守护者
java·spring·mvc
winks38 分钟前
Spring Task的使用
java·后端·spring
不爱缺氧i8 分钟前
dvwa靶场
安全
Null箘9 分钟前
从零创建一个 Django 项目
后端·python·django
云空13 分钟前
《解锁 Python 数据挖掘的奥秘》
开发语言·python·数据挖掘
秋意钟19 分钟前
Spring新版本
java·后端·spring
椰椰椰耶20 分钟前
【文档搜索引擎】缓冲区优化和索引模块小结
java·spring·搜索引擎
mubeibeinv22 分钟前
项目搭建+图片(添加+图片)
java·服务器·前端
霍格沃兹测试开发学社测试人社区23 分钟前
软件测试丨性能测试工具-JMeter
软件测试·测试开发·测试工具·jmeter·性能测试
青莳吖23 分钟前
Java通过Map实现与SQL中的group by相同的逻辑
java·开发语言·sql