当前位置: 首页 > news >正文

【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控制台。


<!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控制台:
// 定义正则表达式
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
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也一样。

六、成品

有能力的小伙伴建议自己把流程全部跑一边,编译个自己的指纹浏览器和驱动。

相关文章:

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

有小伙伴说使用selenium没能绕过机器人检测&#xff0c;盘他。 selenium机器人检测有2种&#xff0c;一是cdp检测&#xff0c;二是webdriver特征检测。cdp检测前面的博客已写过&#xff0c;这里就提下webdriver特征检测。一、selenium简介 Selenium 是一个强大的工具&#xff…...

【JavaEE精炼宝库】HTTP | HTTPS 协议详解

文章目录 一、HTTP 简介二、HTTP 协议格式&#xff1a;2.1 抓包工具的使用&#xff1a;2.2 HTTP 请求报文格式&#xff1a;2.3 HTTP 响应报文格式&#xff1a;2.4 HTTP 协议格式总结&#xff1a; 三、HTTP 请求详解&#xff1a;3.1 刨析 URL&#xff1a;3.2 方法(method)&#…...

Go语言基础学习01

目录 Linux环境下配置安装VScode并配置Go语言开发环境工作区和GOPATH 之前学习过Go语言&#xff0c;学习的时候没有记录笔记&#xff0c;最近找了个极客时间的Go语言36讲&#xff0c;打算时间学习并记录学习过程。 自己抽空看了一点内容&#xff0c;发现这个内容对于0基础解除G…...

基于SSM+Vue+MySQL的酒店管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着旅游业的蓬勃发展&#xff0c;酒店业作为旅游产业链中的重要一环&#xff0c;面临着日益增长的客户需求和激烈的市场竞争。传统的人工酒店管理模式已难以满足高效、精准、个性化的服务要求。因此&#xff0c;开发一套基于SS…...

在WPF中保存控件内容为图片

在WPF中保存控件内容为图片 实现代码如下 1 private void SaveControlContentAsImage(FrameworkElement element,string fileName)2 {3 var render new RenderTargetBitmap((int)element.ActualWidth, (int)element.ActualHeight, 96, 96, PixelFormats…...

C#用SDK打开海康工业相机,callback取图Bitmap格式,并保存

上次写了python版本的,但是python虽好不方便发布,她带着重重的解释器有时候不方便玩耍.于是C#来了哦. C#图像一般用Bitmap表示,所以完全C#就够,别的格式可以自行想转换. 命令行哦,没界面. MVCamera.cs从MVS示例里面添加到项目中,using MvCamCtrl.NET; 就可以,不需要添加mvca…...

C语言字符学习初级优先看这个就够了

1. 字符的基本概念 在C语言中&#xff0c;字符&#xff08;char&#xff09;是一个基本的数据类型&#xff0c;用来表示单个字符。字符用单引号&#xff08; &#xff09;括起来&#xff0c;例如 a、1 等。字符在内存中实际上是以整数的形式存储的&#xff0c;即 ASCII 码。例…...

Python JSON

JSON 函数 json.dumps 语法 实例 json.loads 语法 实例 使用第三方库&#xff1a;Demjson 环境配置 JSON 函数 encode 语法 实例 decode 语法 实例 JSON 函数 使用 JSON 函数需要导入 json 库&#xff1a;import json。 函数描述json.dumps将 Python 对象编码…...

【华为杯】2024华为杯数模研赛F题 解题思路

题目 X射线脉冲星光子到达时间建模 问题背景 高速公路拥堵现象的原因众多&#xff0c;除了交通事故外&#xff0c;最典型的就是部分路段出现瓶颈现象&#xff0c;主要原因是车辆汇聚&#xff0c;而拥堵后又容易蔓延。高速公路一些特定的路段容易形成堵点&#xff0c;如匝道出…...

Object Pascal 结构化程序设计

Object Pascal 关系运算符 运算符名称等于<>不等于>大于<小于>大于等于<小于等于< (属于元素的)包含于> (属于元素的)包含in (属于元素的)属于 # Object Pascal 逻辑运算符 运算符名称含义Not逻辑非单目运算符&#xff0c;进行取反操作&#xff0c;由T…...

机器学习算法与实践_03概率论与贝叶斯算法笔记

1、概率论基础知识介绍 人工智能项目本质上是一个统计学项目&#xff0c;是通过对 样本 的分析&#xff0c;来评估/估计 总体 的情况&#xff0c;与数学知识相关联 高等数学 ——> 模型优化 概率论与数理统计 ——> 建模思想 线性代数 ——> 高性能计算 在机器学…...

如何使用Privoxy将SOCKS5代理转换为HTTP代理?

在这篇博客中&#xff0c;我将介绍如何使用Privoxy将SOCKS5代理转换为HTTP代理。我们将从下载和安装Privoxy开始&#xff0c;接着配置Privoxy&#xff0c;最后配置Windows以便浏览器使用该代理。 1. 下载并安装Privoxy 首先&#xff0c;您需要下载并安装Privoxy。您可以从Pri…...

AJAX(一)HTTP协议(请求响应报文),AJAX发送请求,请求问题处理

文章目录 一、AJAX二、HTTP协议1. 请求报文2. 响应报文 三、AJAX案例准备1. 安装node2. Express搭建服务器3. 安装nodemon实现自动重启 四、AJAX发送请求1. GET请求2. POST请求(1) 配置请求体(2) 配置请求头 3. 响应JSON数据的两种方式(1) 手动&#xff0c;JSON.parse()(2) 设置…...

Git进阶(十五):Git LFS 使用详解

文章目录 一、介绍二、Git LFS 使用步骤三、场景示例四、拓展阅读 一、介绍 Git LFS (Large File Storage) 是一个 Git 扩展&#xff0c;它使 Git 更适合处理大型文件&#xff0c;如音频、视频、图像或任何其他二进制大文件。Git LFS 替换仓库中的大文件为文本指针文件&#x…...

操作系统 | 学习笔记 | | 王道 | 5.1 I/O管理概述

5.1 I/O管理概述 5.1.1 I/O设备 注&#xff1a;块设备可以寻址&#xff0c;但是字符设备是不可寻址的 I/O设备是将数据输入到计算机中&#xff0c;或者可以接收计算机输出数据的外部设备&#xff0c;属于计算机中的硬件部件&#xff1b; 设备的分类 按使用特性分类&#xff…...

关于es的一个多集群、多索引切换的实现

首先是封装了一个类里定义了关于集群名称和集群节点&#xff1b;以及关于索引的名称和集群的名称做一个关联&#xff1b;将多个集群封装存储得到类中 /*** es集群类*/ Data public class EsClusterConfig implements Serializable {/*** 集群名称*/private String name;/*** 集…...

Linux系统编程(基础指令)上

1.Linux常见目录介绍 Linux目录为树形结构 /&#xff1a;根目录&#xff0c;一般根目录下只存放目录&#xff0c;在Linux下有且只有一个根目录。所有的东西都是从这里开始。当你在终端里输入“/home”&#xff0c;你其实是在告诉电脑&#xff0c;先从/&#xff08;根目录&…...

【STM32 Blue Pill编程】-定时器PWM模式

定时器PWM模式 文章目录 定时器PWM模式1、定时器PWM模式介绍2、硬件准备及接线3、模块配置4、代码实现在文中,我们将介绍如何使用 STM32 Blue Pill 定时器的PWM模式以及如何配置它们以生成具有不同占空比和频率的信号。 我们将使用 LED调光器示例来演示如何使用 STM32Cube IDE…...

数字英文验证码识别 API 对接说明

数字英文验证码识别 API 对接说明 本文将介绍一种 数字英文验证码识别 API 对接说明&#xff0c;它是基于深度学习技术&#xff0c;可用于识别变长英文数字验证码。输入验证码图像的内容&#xff0c;输出验证码结果。 接下来介绍下 数字英文验证码识别 API 的对接说明。 注册…...

稳了,搭建Docker国内源图文教程

大家好&#xff0c;之前分享了我的开源作品 Cloudflare Workers Proxy&#xff0c;它的作用是代理被屏蔽的地址&#xff0c;理论上支持代理任何被屏蔽的域名&#xff0c;使用方式也很简单&#xff0c;只需要设置环境变量 PROXY_HOSTNAME 为被屏蔽的域名&#xff0c;最后通过你的…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

C++ 基础特性深度解析

目录 引言 一、命名空间&#xff08;namespace&#xff09; C 中的命名空间​ 与 C 语言的对比​ 二、缺省参数​ C 中的缺省参数​ 与 C 语言的对比​ 三、引用&#xff08;reference&#xff09;​ C 中的引用​ 与 C 语言的对比​ 四、inline&#xff08;内联函数…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...