突破反爬困境:SDK开发,浏览器模块(七)

声明
本文所讨论的内容及技术均纯属学术交流与技术研究目的,旨在探讨和总结互联网数据流动、前后端技术架构及安全防御中的技术演进。文中提及的各类技术手段和策略均仅供技术人员在合法与合规的前提下进行研究、学习与防御测试之用。
作者不支持亦不鼓励任何未经授权的工程应用或违法行为,所有内容均不构成任何非法操作的技术指导或建议。请各位读者根据所在平台的相关规定及法律法规谨慎使用和解读本文内容。
引言
在过去的六篇文章中,我们以“庖丁解牛”的方式拆解了反爬虫攻防的核心逻辑,从协议分析、行为特征检测到动态渲染对抗,逐步构建了一套完整的反爬虫技术设计框架。
从这一篇开始,一切将截然不同,我们将以代码说话。
设计是技术的骨架,而开发才是赋予其血肉与灵魂的过程。本文将带领读者正式跨越理论与实践的边界,进入实战开发阶段。我们将亲手实现一个轻量指纹浏览器SDK,并深度集成浏览器自动化工具(如Puppeteer、Playwright)。
接下来的内容将默认读者已掌握Python/JavaScript基础及HTTP协议核心知识。
接口设计
在设计SDK接口时,我反复澄清要给到最终使用者的是什么?更多功能?还是更简单易用?在这里,我选择了更加倾向于易用性。毕竟我们的程序,是要解决问题,降低复杂度,而非制造问题。因此我们在设计浏览器模块接口时,只关注以下几个动作:
- 创建一个浏览器实例
- 关闭浏览器实例,并回收相关资源
- 查看当前正在运行中的浏览器实例
这些行为,已经完全可以满足一个爬虫在执行过程中所需进行的全部动作了。因为在浏览器实例创建完毕之并与爬虫框架完成CDP连接之后,后续的就都是爬虫系统的行为了。
接口文档
由于我们是指纹浏览器,因此我们先把指纹模型的设计放在最开始
指纹数据
{"screen": {"width": 800, // 宽度"height": 600 // 高度},// 屏幕分辨率 非必填"timezone": "Asia/Hong_Kong",// 时区,非必填"userAgent": "Mozilla/5.0 (Windows NT 10.0; WOW64) Chrome/86.0.4240.198", // UA信息 非必填"platform": "Win32",// 平台信息 非必填"userAgentData": {"productName": "Google Chrome", //浏览器品牌名 Google Chrome / Microsoft Edge / Chromium / Brave"productVersion": "110.0.5481.78", // 浏览器版本号"isMobile": false, // 是否为手机版 "platform": "Windows", // 运行平台 Windows/Mac OS X/Linux/iOS/Android"platformVersion": "15.0.0", // 运行平台版本号 Windows 举例 Win11:15.0.0 /Win10: 10.0.0"architecture": "x86", // 编译架构 arm/x86"bitness": "64", //运行平台 位数 32/64"model": "", //品牌型号,仅限手机版情况下有值"wow64": false // 99 以下 undefined,99 以上 false(仅win有判断,其他系统统一false)},// UAData信息 非必填 但UA发生变化时必填,同时会校验此信息合法性"deviceMemory?": 8, // 设备内存 非必填"hardwareConcurrency?": 4, // 硬件并发数 非必填"languages": ["en-US",], // 页面语言 非必填"locale": "en-US", // UI语言 非必填},"font": {"unicode": true, //是否禁用Emoji表情,true|false"fonts": ["Arial","Arial Black","Arial Narrow","Calibri","Cambria","Cambria Math","Comic Sans MS"],// 字体列表}, // 字体信息 非必填"audio": {"seed": "xxxxx"},// 音频指纹噪声 非必填"canvas": {"seed": "xxxxx"},// Canvas指纹噪声 非必填"webgl": { "seed": "xxxxx", // 噪声 非必填"meta":{"vendor": "Google Inc.", // 提供商"renderer": "ANGLE (NVIDIA GeForce GT 730)" // 渲染器} //元数据 非必填},// WebGL配置 非必填"geolocation": {"latitude": 44.0,"longitude": 55.0},// 定位信息 非必填"bluetooth": { "enabled": false // 是否启用蓝牙,true or false},// 蓝牙状态 非必填"speech": [// 至少有一项的is_default为true !// 否则朗读者列表强制转化为空,显示为blocked{"name": "Microsoft Swara - Hindi (India)", // 朗诵者名称,字符串"lang": "hi-IN", // 朗诵者语言,字符串"isDefault": true // 是否为默认语音,true or false},{"name": "Microsoft Sylvie - French (Canada)","lang": "fr-CA","isDefault": false}]// 朗读者列表 非必填} 以上是我们指纹部分支持的全部配置,通过这些指纹的排列组合,我们已经可以很好的确定浏览器实例的指纹唯一性了,下面我们来继续完善其他操作的文档。
新建浏览器实例
API
| 路径 | 请求方式 |
| /browsers | POST |
Request
{"userDataDir":"", // 数据缓存路径 必填"proxy":{"protocol":"http",// 协议 支持http,https,socks 必填"host":"39.123.33.154",// 代理主机 支持 IPv4 IPv6 以及域名 必填"port":10234,// 代理端口 必填"username":"",// 用户名 非必填"password":"",// 密码 非必填},//代理 非必填"args":[],// 浏览器附加的命令行参数,非必填 会过滤掉 --proxy-server --remote-debugging-port"metadata":{},//用户存储的元数据,非必填"fingerprint":{},// 指纹数据,非必填 无指纹数据时则不会对指纹进行模拟。
} Response
{"id":"xxxx-xxxx-xxxx-xxxx-xxxx", // 浏览器实例ID"proxyUrl":"http://127.0.0.1:11111",// 浏览器使用的本地转发后的代理链接"args":[],// 浏览器附加的参数"metadata":{},// 用户缓存的元数据"automation":{"driverPath":"",// 浏览器匹配的WebDriver路径"remoteDebuggingPort":32023,// 远程调试端口"cdpUrl":"http://127.0.0.1:32023",// CDP连接路径"cdpWsUrl":"ws://localhost:32023/devtools/page/DAB7FB6187B554E10B0BD18821265734",// CDP Websocket连接路径},// 自动化相关信息"createdTime":""// 创建时间
} 关闭浏览器实例
API
| 路径 | 请求方式 |
| /browsers/{browserId} | DELETE |
Response
{"id":"xxxx-xxxx-xxxx-xxxx-xxxx", // 浏览器实例ID"proxyUrl":"http://127.0.0.1:11111",// 浏览器使用的本地转发后的代理链接"args":[],// 浏览器附加的参数"metadata":{},// 用户缓存的元数据"automation":{"driverPath":"",// 浏览器匹配的WebDriver路径"remoteDebuggingPort":32023,// 远程调试端口"cdpUrl":"http://127.0.0.1:32023",// CDP连接路径"cdpWsUrl":"ws://localhost:32023/devtools/page/DAB7FB6187B554E10B0BD18821265734",// CDP Websocket连接路径},// 自动化相关信息"createdTime":""// 创建时间
} 关闭全部浏览器实例
API
| 路径 | 请求方式 |
| /browsers | DELETE |
Response
{"id":"xxxx-xxxx-xxxx-xxxx-xxxx", // 浏览器实例ID"proxyUrl":"http://127.0.0.1:11111",// 浏览器使用的本地转发后的代理链接"args":[],// 浏览器附加的参数"metadata":{},// 用户缓存的元数据"automation":{"driverPath":"",// 浏览器匹配的WebDriver路径"remoteDebuggingPort":32023,// 远程调试端口"cdpUrl":"http://127.0.0.1:32023",// CDP连接路径"cdpWsUrl":"ws://localhost:32023/devtools/page/DAB7FB6187B554E10B0BD18821265734",// CDP Websocket连接路径},// 自动化相关信息"createdTime":""// 创建时间
} 查看当前所有正在运行的浏览器实例
API
| 路径 | 请求方式 |
| /browsers | GET |
Response
[{"id":"xxxx-xxxx-xxxx-xxxx-xxxx", // 浏览器实例ID"proxyUrl":"http://127.0.0.1:11111",// 浏览器使用的本地转发后的代理链接"args":[],// 浏览器附加的参数"metadata":{},// 用户缓存的元数据"automation":{"driverPath":"",// 浏览器匹配的WebDriver路径"remoteDebuggingPort":32023,// 远程调试端口"cdpUrl":"http://127.0.0.1:32023",// CDP连接路径"cdpWsUrl":"ws://localhost:32023/devtools/page/DAB7FB6187B554E10B0BD18821265734",// CDP Websocket连接路径},// 自动化相关信息"createdTime":""// 创建时间
}] 以上就是全部的接口设计文档了。
使用案例
下面我们以用户的角度,来使用我们的SDK,以下是一个基于Python与Playwright框架的简单例子。
import requests
from playwright.sync_api import sync_playwright# API信息
api_url = "http://localhost:3000/browsers" # 假设这是我们SDK服务的地址# 请求数据
request_data = {"userDataDir": "/path/to/user/data", # 请替换为实际的数据缓存路径"proxy": {"protocol": "http","host": "39.123.33.154","port": 10234,"username": "","password": ""},"args": [],"metadata": {"description":"一个演示用的实例"},"fingerprint": {"screen":{"width":800,"height":600},"userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36","userAgentData": {"productName": "Google Chrome", "productVersion": "133.0.6943.142", "isMobile": false, "platform": "Windows", "platformVersion": "15.0.0", "architecture": "x86", "bitness": "64", "model": "", "wow64": false}}
}# 发送POST请求创建浏览器实例
response = requests.post(api_url, json=request_data)# 检查响应状态码
if response.status_code == 200:response_data = response.json()print("浏览器实例创建成功:")print(response_data)# 获取CDP连接信息cdp_ws_url = response_data["automation"]["cdpWsUrl"]# 使用Playwright连接到浏览器实例with sync_playwright() as p:browser = p.chromium.connect_over_cdp(cdp_ws_url)# ... Todoelse:print(f"请求失败,状态码: {response.status_code},错误信息: {response.text}")
以上就是一个使用SDK的简单示例,我们在启动时,提供了一个基于Http协议的代理,以及提供了屏幕大小、UA的指纹模拟。并在启动完成之后,通过cdpWsUrl,将浏览器实例与Playwright进行连接,最终完成我们的爬虫操作。
总结
本文从理论到实践,详细介绍了一个轻量级指纹浏览器SDK的设计与实现。文章强调了易用性,将SDK功能聚焦于创建、关闭和查看浏览器实例三个核心操作。文中详细说明了指纹数据模型结构,包括屏幕分辨率、用户代理、平台信息等多个维度,确保浏览器实例的唯一性。
接口设计部分提供了完整的API文档,并通过一个Python和Playwright的案例展示了实际应用。这一实现不仅将之前讨论的反爬虫理论付诸实践,还为开发者提供了一个灵活、易用的工具,帮助他们在复杂的反爬虫环境中更有效地进行数据采集工作。并成功地将复杂的反爬虫技术转化为可操作的开发实践,为读者搭建了理论与实践之间的桥梁。
相关文章:
突破反爬困境:SDK开发,浏览器模块(七)
声明 本文所讨论的内容及技术均纯属学术交流与技术研究目的,旨在探讨和总结互联网数据流动、前后端技术架构及安全防御中的技术演进。文中提及的各类技术手段和策略均仅供技术人员在合法与合规的前提下进行研究、学习与防御测试之用。 作者不支持亦不鼓励任何未经授…...
rce操作
Linux命令长度突破限制 源码 <?php $param $_REQUEST[param];if ( strlen($param) < 8 ) {echo shell_exec($param); } echo执行函数,$_REQUEST可以接post、get、cookie传参 源码中对参数长度做了限制,小于8位,可以利用临时函数&…...
LabVIEW高效溢流阀测试系统
开发了一种基于LabVIEW软件和PLC硬件的溢流阀测试系统。通过集成神经网络优化的自适应PID控制器,该系统能自动进行压力稳定性、寿命以及动静态性能测试。该设计不仅提升了测试效率,还通过智能化控制提高了数据的精确性和操作的便捷性。 项目背景&…...
Spring Boot 中 JdbcTemplate 处理枚举类型转换 和 减少数据库连接的方法 的详细说明,包含代码示例和关键要点
以下是 Spring Boot 中 JdbcTemplate 处理枚举类型转换 和 减少数据库连接的方法 的详细说明,包含代码示例和关键要点: 一、JdbcTemplate 处理枚举类型转换 1. 场景说明 假设数据库存储的是枚举的 String 或 int 值,但 Java 实体类使用 enu…...
DataGear 5.3.0 制作支持导出表格数据的数据可视化看板
DataGear 内置表格图表底层采用的是DataTable表格组件,默认并未引入导出数据的JS支持库,如果有导出表格数据需求,则可以在看板中引入导出相关JS支持库,制作具有导出CSV、Excel、PDF功能的表格数据看板。 在新发布的5.3.0版本中&a…...
Web网页内嵌 Adobe Pdf Reader 谷歌Chrome在线预览编辑PDF文档
随着数字化办公的普及,PDF文档已成为信息处理的核心载体,虽然桌面端有很多软件可以实现预览编辑PDF文档,而在线在线预览编辑PDF也日益成为一个难题。 作为网页内嵌本地程序的佼佼者——猿大师中间件,之前发布的猿大师办公助手&am…...
歌词json
绽放(4:17) {"lyrics": [{time: 00:00, text: 作词:郑润泽},{time: 00:01, text: 作曲:郑润泽},{time: 00:02, text: 编曲:赵建飞},{time: 00:03, text: 制作人:李淘/赵建飞},{time: 00:09, tex…...
CNG汽车加气站操作工备考真题及答案解析【判断题】
1、燃气经营许可证按照燃气经营规模和类别实行分级审批。(√) 解析:不同规模和类别的燃气经营,其许可证审批级别不同,以确保经营活动的规范和安全。 2、依照《安全生产法》的规定,安全生产监督检查人员对检…...
Sentinel[超详细讲解]-1
定义一系列 规则 👺,对资源进行 保护 👺, 如果违反的了规则,则抛出异常,看是否有fallback兜底处理,如果没有则直接返回异常信息😎 1. 快速入门 1.1 引入 Sentinel 依赖 <depend…...
CUDA专题8—CUDA L2缓存完全指南:从持久化策略到性能优化实战
1. 设备内存L2缓存访问管理 当CUDA内核反复访问全局内存中的某个数据区域时,此类数据访问可视为持久化(persisting)访问。反之,若数据仅被访问一次,则可视为流式(streaming)访问。 从CUDA 11.0开始,计算能力8.0及以上的设备能够调控L2缓存中数据的持久性,从而可能实现更…...
如何让 SQL2API 进化为 Text2API:自然语言生成 API 的深度解析?
在过去的十年里,技术的进步日新月异,尤其是在自动化、人工智能与自然语言处理(NLP)方面。 随着“低代码”平台的崛起,开发者和非技术人员能够更轻松地构建强大而复杂的应用程序。然而,尽管技术门槛降低了&…...
OCCT(2)Windows平台编译OCCT
文章目录 一、Windows平台编译OCCT1、准备环境2、下载源码3、下载第三方库4、使用 CMake 配置5、编译OCCT源码6、运行示例 一、Windows平台编译OCCT 1、准备环境 安装工具: Visual Studio(推荐 VS2019/2022,选择 C 桌面开发 组件࿰…...
【蓝桥杯—单片机】通信总线专项 | 真题整理、解析与拓展 (更新ing...)
通信总线专项 前言SPI第十五届省赛题 UART/RS485/RS232UARTRS485RS232第十三届省赛题小结和拓展:传输方式的分类第十三届省赛 其他相关考点网络传输速率第十五届省赛题第十二届省赛题 前言 在本文中我会把 蓝桥杯单片机赛道 历年真题 中涉及到通信总线的题目整理出…...
【Golang】泛型与类型约束
文章目录 一、环境二、没有泛型的Go三、泛型的优点四、理解泛型(一)定义(二)调用(三)类型约束(Type Constraint)1)接口与约束2)结构体类型约束3)类…...
Uni-app页面信息与元素影响解析
获取窗口信息uni.getWindowInfo {pixelRatio: 3safeArea:{bottom: 778height: 731left: 0right: 375top: 47width: 375}safeAreaInsets: {top: 47, left: 0, right: 0, bottom: 34},screenHeight: 812,screenTop: 0,screenWidth: 375,statusBarHeight: 47,windowBottom: 0,win…...
CentOS(最小化)安装之后,快速搭建Docker环境
本文以VMware虚拟机中安装最小化centos完成后开始。 1. 检查网络 打开网卡/启用网卡 执行命令ip a查看当前的网络连接是否正常: 如果得到的结果和我一样,有ens网卡但是没有ip地址,说明网卡未打开 手动启用: nmcli device sta…...
【身份证证件OCR识别】批量OCR识别身份证照片复印件图片里的文字信息保存表格或改名字,基于QT和腾讯云api_ocr的实现方式
项目背景 在许多业务场景中,需要处理大量身份证照片复印件,手动输入其中的文字信息效率低下且容易出错。利用 OCR(光学字符识别)技术可以自动识别身份证图片中的文字信息,结合 QT 构建图形用户界面,方便用户操作,同时使用腾讯 OCR API 能够保证较高的识别准确率。 界面…...
IP属地和发作品的地址不一样吗
在当今这个数字化时代,互联网已经成为人们日常生活不可或缺的一部分。随着各大社交平台功能的不断完善,一个新功能——IP属地显示,逐渐走进大众视野。这一功能在微博、抖音、快手等各大平台上得到广泛应用,旨在帮助公众识别虚假信…...
Redis - 概述
目录 编辑 一、什么是redis 二、redis能做什么(有什么特点)? 三、redis有什么优势 四、Redis与其他key-value存储有什么不同 五、Redis命令 六、Redis数据结构 1、基础数据结构 2、高级数据结构 一、什么是redis 1、redis&#x…...
vue3 根据城市名称计算城市之间的距离
<template><div class"distance-calculator"><h1>城市距离计算器</h1><!-- 城市输入框 --><div class"input-group"><inputv-model"city1"placeholder"请输入第一个城市"keyup.enter"cal…...
html 列表循环滚动,动态初始化字段数据
html <div class"layui-row"><div class"layui-col-md4"><div class"boxall"><div class"alltitle">超时菜品排行</div><div class"marquee-container"><div class"scroll-…...
QT基础:安装与简介
QT初级 1、简介1.1 安装1.2 设置1.3 在VS中配置Qt1.3 帮助文档 2、Qt项目2.1 创建项目2.1 项目文件2.2 Qt中的窗口类窗口显示 2.3 坐标体系2.4 内存回收 1、简介 QT是一个跨平台的C应用程序开发框架。几乎支持所有的平台, 可用于桌面程序开发以及嵌入式开发。 Qt是标准 C 的扩…...
41、当你在 index.html 中引用了一个公共文件(比如 common.js),修改这个文件后,用户访问页面时仍然看到旧内容,因为浏览器缓存了旧版本
由于浏览器缓存导致公共文件无法更新。当用户修改了公共文件(如 JavaScript 或 CSS),但 index.html 中引用的文件名没有变化,浏览器会认为文件没有更新,继续使用缓存的旧版本。因此,需要通过某种方式让浏览…...
WEB安全-HTTPS
1 需求 结合Wireshark抓包实战,图文详解TCP三次握手及四次挥手原理(附下载) 结合Wireshark抓包分析,沉浸式体验HTTP请求的一次完整交互过程 https://mp.weixin.qq.com/s/f3LmUEtjIuLjkyjxJj7ebA 一文彻底了解DNS协议工作原理&…...
【宇宙回响】从Canvas到MySQL:飞机大战的全栈交响曲【附演示视频与源码】
🌟 这是星际大战系列的第三篇,感谢一路以来支持和关注这个项目的每一位朋友! 💡 文章力求严谨,但难免有疏漏之处,欢迎各位朋友指出,让我们一起在交流中进步。 🎁 项目代码、文档和相关资源都可以免费获取,希望能帮助到更多对游戏开发感兴趣的朋友。 💌 如果您有任…...
Linux内核内存管理 ARM32页表映射流程和案例分享
ARM32架构使用两级页表结构将虚拟地址转换为物理地址,以下为详细流程及案例分析: ARM32页表映射流程 1.获取页目录基地址 MMU通过TTBR(Translation Table Base Register)寄存器获取当前进程的一级页表(L1页表&#x…...
git push origin masterremote: [session-bd46a49f] The token username invalid
参考:如何把项目上传到Gitee(保姆级教程)_gitee上传项目-CSDN博客 1 新建仓库 username可以是登录账号的邮箱地址也可以是用户名 password可以是登录账号的密码也可以是私人令牌 2 创建分支 3 初始化 dev是你新建的分支 创建并切换分支 git init g…...
基于MCU实现的电机转速精确控制方案:软件设计与实现
本文将详细介绍一篇基于微控制器(MCU)的电机转速精确控制的软件方案。通过采样PWM信号控制和ADC采样技术,结合PID闭环控制算法,实现了电机转速的高效、稳定调节。以下是软件方案流程图,下文将对其进行展开讲解。 原图太…...
suse15 sp1使用华为云软件源yum源zypper源
登录suse15终端, cd /etc/zypp/repos.d/进入目录后执行以下命令: zypper ar -fcg https://mirrors.huaweicloud.com/opensuse/distribution/leap/15.1/repo/oss HuaWeiCloud:15.1:OSS zypper ar -fcg https://mirrors.huaweicloud.com/opensuse/distribu…...
amd64 架构机器如何拉取arm64的镜像
在 AMD 架构(通常是 x86_64 架构)的机器上拉取 ARM 架构的镜像 拉取指定架构的镜像 例如,要拉取 ARM64 架构的 nginx 镜像,可以使用以下命令: docker pull --platform linux/arm64 nginx...
