突破反爬困境: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的案例展示了实际应用。这一实现不仅将之前讨论的反爬虫理论付诸实践,还为开发者提供了一个灵活、易用的工具,帮助他们在复杂的反爬虫环境中更有效地进行数据采集工作。并成功地将复杂的反爬虫技术转化为可操作的开发实践,为读者搭建了理论与实践之间的桥梁。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/76631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++数据排序( 附源码 )

一.冒泡排序 原理:自左向右依次遍历,若相邻两数顺序错误,则交换两数. 这样,每一轮结束后,最大/最小的数就会到最后. Code: #include <iostream> #include <cstdio> using namespace std; const int N1e51; int n,a[N],in; void PrintArray(int a[],int n){for…

I2C 读写 AT24C02

根据AT24C02的 Datasheet 可知AT24C02有2K bit&#xff0c;即256B&#xff0c;分为32页,每页8个字节&#xff0c;结合数据手册和原理图可以得知&#xff0c;板载AT24C02的读地址为0xA2&#xff0c;写地址为0xA3&#xff1a; #define AT24C02_ADDR_WRITE 0xA2 #define AT24C02_…

K8S学习之基础七十四:部署在线书店bookinfo

部署在线书店bookinfo 在线书店-bookinfo 该应用由四个单独的微服务构成&#xff0c;这个应用模仿在线书店的一个分类&#xff0c;显示一本书的信息&#xff0c;页面上会显示一本书的描述&#xff0c;书籍的细节&#xff08;ISBN、页数等&#xff09;&#xff0c;以及关于这本…

Linux 查找文本中控制字符所在的行

参考资料 ASCIIコード表 目录 一. 业务背景二. 遇到的问题三. 分析3.1 url编码的前置知识3.2 出现控制字符的transactionid分析3.3 16进制分析 四. 从文本中查找控制字符所在的行五. 控制字符一览 一. 业务背景 ⏹在项目中&#xff0c;业务请求对应着下URL http://www.test.…

python将pdf文件转为图片,如果pdf文件包含多页,将转化的多个图片通过垂直或者水平合并成一张图片

要将PDF文件转换为图片&#xff0c;并将多页PDF垂直合并成一张图片&#xff0c;可以使用PyMuPDF&#xff08;也称为fitz&#xff09;库来读取PDF文件&#xff0c;并使用Pillow库来处理和合并图片。以下是一个示例代码&#xff0c;展示了如何实现这个功能&#xff1a; 首先&…

HarmonyOS 基础组件和基础布局的介绍

1. HarmonyOS 基础组件 1.1 Text 文本组件 Text(this.message)//文本内容.width(200).height(50).margin({ top: 20, left: 20 }).fontSize(30)//字体大小.maxLines(1)// 最大行数.textOverflow({ overflow: TextOverflow.Ellipsis })// 超出显示....fontColor(Color.Black).…

FrameWork基础案例解析(四)

文章目录 单独拉取framework开机与开机动画横屏Android.mk语法单独编译SDKmake 忽略warning单独修改和编译Camera2单独编译Launcher3Android Studio 导入、修改、编译Settings导入 Android Studio 导入、修改、编译Launcher3android 开机默认进入指定Launcher植入自己的apk到系…

基于vscode(GDB)调试ros2节点

一、环境准备 必备vscode插件 1&#xff09;Docker Docker - Visual Studio Marketplace 2&#xff09;Dev Containers Dev Containers - Visual Studio Marketplace 3&#xff09;GDB GDB Debug - Visual Studio Marketplace 二、进去docker镜像 1&#xff09;docker安…

基于springboot的考研成绩查询系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 这些年随着Internet的迅速发展&#xff0c;我们国家和世界都已经进入了互联网大数据时代&#xff0c;计算机网络已经成为了整个社会以及经济发展的巨大动能&#xff0c;考研成绩查询管理事务现在已经成为社会关注的重要内容&#xff0c;因此运用互联网技术来提高考研成绩…

C++:算术运算符

程序员Amin &#x1f648;作者简介&#xff1a;练习时长两年半&#xff0c;全栈up主 &#x1f649;个人主页&#xff1a;程序员Amin &#x1f64a; P   S : 点赞是免费的&#xff0c;却可以让写博客的作者开心好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全…

PyQt6实例_A股日数据维护工具_使用

目录 前置&#xff1a; 下载预备更新的数据 使用工具更新 用工具下载未复权、前复权、权息数据 在PostgreSQL添加两个数据表 工具&视频 前置&#xff1a; 1 本系列将以 “PyQt6实例_A股日数据维护工具” 开头放置在“PyQt6实例”专栏 2 日数据可在“数据库”专栏&…

REST 方法

FUNCTION ZFM_INTERFACE_LOG. *"---------------------------------------------------------------------- *"*"本地接口&#xff1a; *" IMPORTING *" REFERENCE(IV_DSTART) TYPE EDI_UPDDAT *"---------------------------------------…

QT 中的元对象系统(五):QMetaObject::invokeMethod的使用和实现原理

目录 1.简介 2.原理概述 3.实现分析 3.1.通过方法名调用方法的实现分析 3.2.通过可调用对象调用方法的实现分析 4.使用场景 5.总结 1.简介 QMetaObject::invokeMethod 是 Qt 框架中的一个静态方法&#xff0c;用于在运行时调用对象的成员函数。这个方法提供了一种动态调…

Unity3D开发AI桌面精灵/宠物系列 【三】 语音识别 ASR 技术、语音转文本多平台 - 支持科大讯飞、百度等 C# 开发

Unity3D 交互式AI桌面宠物开发系列【三】ASR 语音识别 该系列主要介绍怎么制作AI桌面宠物的流程&#xff0c;我会从项目开始创建初期到最终可以和AI宠物进行交互为止&#xff0c;项目已经开发完成&#xff0c;我会仔细梳理一下流程&#xff0c;分步讲解。 这篇文章主要讲有关于…

Java 状态模式 详解

状态模式详解 一、状态模式概述 状态模式(State Pattern)是一种行为型设计模式&#xff0c;它允许一个对象在其内部状态改变时改变它的行为&#xff0c;使对象看起来似乎修改了它的类。 核心特点 状态封装&#xff1a;将每个状态的行为封装到独立的类中状态转换&#xff1a…

Nginx 配置 HTTPS 与 WSS 完整指南

Nginx 配置 HTTPS 与 WSS 完整指南 本教程将手把手教你如何为网站配置 HTTPS 加密访问&#xff0c;并通过反向代理实现安全的 WebSocket&#xff08;WSS&#xff09;通信。以 https://www.zhegepai.cn 域名为例&#xff0c;完整流程约需 30 分钟完成。 一、前置准备 1.1 域名…

双向链表的理解

背景 代码中经常会出现双向链表&#xff0c;对于双向链表的插入和删除有对应的API函数接口&#xff0c;但直观的图表更容易理解&#xff0c;所以本文会对rt-thread内核代码中提供的双向链表的一些API函数操作进行绘图&#xff0c;方便后续随时查看。 代码块 rt-thread中提供…

大文件上传源码,支持单个大文件与多个大文件

大文件上传源码&#xff0c;支持单个大文件与多个大文件 Ⅰ 思路Ⅱ 具体代码前端--单个大文件前端--多个大文件前端接口后端 Ⅰ 思路 具体思路请参考我之前的文章&#xff0c;这里分享的是上传流程与源码 https://blog.csdn.net/sugerfle/article/details/130829022 Ⅱ 具体代码…

Unity中的静态合批使用整理

静态批处理是一种绘制调用批处理方法&#xff0c;它组合不移动的网格以减少绘制调用。它将组合的网格转换为世界空间&#xff0c;并为它们构建一个共享顶点和索引缓冲区。然后&#xff0c;对于可见网格&#xff0c;Unity 会执行一系列简单的绘制调用&#xff0c;每个调用之间几…

【机器学习中的基本术语:特征、样本、训练集、测试集、监督/无监督学习】

机器学习基本术语详解 1. 特征&#xff08;Feature&#xff09; 定义&#xff1a;数据的属性或变量&#xff0c;用于描述样本的某个方面。作用&#xff1a;模型通过学习特征与目标之间的关系进行预测。示例&#xff1a; 预测房价时&#xff0c;特征可以是 面积、地段、房龄。…