摘要
本文主要介绍爬虫学习所要掌握的基础知识,主要包括Web开发相关基础知识(Html、Css等)、Python相关基础知识、几个简单的Python库的使用等。还需要一些知识储备,比如:
- re 模块,python 正则基础;
- requests,用于获取网页内容,供后续处理;
- lxml,用于处理 Html文档中的 元素;
- 常用的爬虫策略与反爬策略;
re 模块
re 模块是python内置的模块,代码都在re.py
文件中,是Python用来进行正则处理的,提供了正则表达式的支持,用于字符串的模式匹配、搜索、替换等操作。 如果没有正则基础,在文件的头部有正则表达式最基本的说明,这个更通过网络搜索的结果是一样的,而且每个说明都有例子说明。
常用的正则使用示例
- 手机号判断
- 身份证判断
- 是否包含数字
常用函数
re.match(pattern, string)
从字符串开头匹配模式,如果匹配成功返回匹配对象,否则返回 None,示例如下:
python
import re
result = re.match(r'hello', 'hello world')
if result:
print(result.group()) # 输出: hello
re.search(pattern, string)
在整个字符串中搜索模式,返回第一个匹配的对象。
python
import re
result = re.search(r'world', 'hello world')
if result:
print(result.group()) # 输出: world
re.findall(pattern, string)
返回字符串中所有匹配的子串列表
python
import re
result = re.findall(r'\d+', 'abc123def456')
if result:
print(result.group()) # 输出:[123, 456]
re.finditer(pattern, string)
返回匹配对象的迭代器。
python
import re
result = re.finditer(r'\d+', 'abc123def456')
if result:
for match in result:
print(match.group())
# 输出
# 123
# 456
re.sub(pattern, repl, string)
替换字符串中匹配的子串。
python
import re
result = re.sub(r'\d+', 'NUMBER', 'abc123def456')
print(result)
# 输出:abcNUMBERdefNUMBER
re.split(pattern, string)
根据 pattern 来进行字符串的分割,返回的是列表。
python
import re
result = re.split(r's+', 'hello word python')
print(result)
编译正则表达式
re.compile(pattern, flag)
使用 re.compile() 预编译正则表达式,提高重复使用的性能。
python
import re
pattern = re.compile(r'\d+')
result = pattern.findall('abc123def456')
print(result)
常用正则匹配模式
模式 | 说明 |
---|---|
. | 匹配任意字符(除换行符) |
. | 匹配字符串开头 |
$ | 匹配字符串结尾 |
* | 匹配前面的字符0次或多次 |
+ | 匹配前面的字符1次或多次 |
? | 匹配前面的字符0次或多次 |
{n} | 匹配前面的字符n次 |
{n,} | 匹配前面的字符至少n次 |
{n,m} | 匹配前面的字符n到m次 |
[] | 字符类,匹配方括号内任意字符 |
[^] | 否定字符类 |
\d | 匹配数字,等价于[0-9] |
\D | 匹配非数字 |
\w | 匹配字母、数字或下划线 |
\W | 匹配非字母、数字或下划 |
\s | 匹配空白字符 |
\S | 匹配非空白字符 |
匹配对象方法
匹配 对象值得是调用 re.search(pattern, string)
后返回的Match对象,他有如下方法:
group()
- 返回匹配的字符串;groups()
- 返回所有分组的元组;group(n)
- 返回第n个分组;start()
- 返回匹配开始位置;end()
- 返回匹配结束位置;span()
- 返回匹配位置的元组(start, end);
标志参数
可以使用标志位来修改正则表达式的匹配行为,如:
python
# re.IGNORECASE 忽略大小写
result = re.search(r'hello', 'Hello World', re.IGNORECASE)
# re.MULTILINE 多行模式
# re.DOTALL 使.匹配包括换行符在内的所有字符
# re.VERBOSE 详细模式,允许写注释
捕获组(Capturing Groups)详解
捕获组是正则表达式中用圆括号 ()
包围的子表达式,用于从匹配的文本中提取特定部分。
1. 基本概念
在正则表达式中,当你使用圆括号将一部分模式包围起来时,这部分就成为了一个捕获组。捕获组会"捕获"(保存)匹配该部分的文本,以便后续使用。
2. 示例说明
以你的代码为例:
python
content = '''◎译 名 侏罗纪世界:重生/侏罗纪世界4◎片 名 Jurassic World: Rebirth/Jurassic World 4◎年 代 2025◎产 地 美国◎类 别 动作/科幻/惊悚/冒险◎语 言 英语◎字 幕 中英双字◎上映日期 2025-07-02(美国/中国大陆)◎IMDb评分 5.9/10 from 126698 users◎豆瓣评分 5.9/10 from 121885 users◎片 长 134分钟◎导 演 加里斯·爱德华斯 Gareth Edwards◎编 剧 大卫·凯普 David Koepp 迈克尔·克莱顿 Michael Crichton◎主 演 斯嘉丽·约翰逊 Scarlett Johansson 马赫沙拉·阿里 Mahershala Ali 乔纳森·贝利 Jonathan Bailey 鲁伯特·弗兰德 Rupert Friend 艾德·斯克林 Ed Skrein 曼努埃尔·加西亚-鲁尔福 Manuel Garcia-Rulfo 卢娜·布雷斯 Luna Blaise 奥德丽娜·米兰达 Audrina Miranda 大卫·伊亚科诺 David Iacono 贝希尔·西尔万 Bechir Sylvain 菲莉皮娜·维莱芝 Philippine Velge 妮娅姆·芬利 Niamh Finlay 亚当·洛克斯利 Adam Loxley 迪伦·比克尔 Dylan Bickel 朱利安·埃德加 Julian Edgar 乔尼·拉韦尔 Jonny Lavelle◎简 介 故事发生在《侏罗纪世界3》事件的五年后。危在旦夕的恐龙族群生存于孤岛之上,但是它们中却隐藏着能够带来人类医药奇迹的关键基因,为获取神秘基因,一支精英小队潜入恐龙禁地,然而等待他们的却是无法预知的危机和惊天阴谋......侏罗纪世界:重生.2025.BD.1080P.中英双字'''
translated_name = re.search(r'◎译\s*名\s*([^\r\n<◎]+)', content)
正则表达式分解:
◎译
- 匹配字面量"◎译"- \s* - 匹配零个或多个空白字符
名
- 匹配字面量"名"- \s* - 匹配零个或多个空白字符
([^\r\n<◎]+)
- 这是一个捕获组,匹配一个或多个非换行符、非"<"、非"◎"的字符
3. group() 方法的区别
csharp
# 假设匹配成功,对于文本 "◎译 名 侏罗纪世界:重生/侏罗纪世界4"
translated_name.group() 或 translated_name.group(0)
# 返回整个匹配的字符串:
# "◎译 名 侏罗纪世界:重生/侏罗纪世界4"
translated_name.group(1)
# 返回第一个捕获组的内容:
# "侏罗纪世界:重生/侏罗纪世界4"
4. 多个捕获组示例
python
import re
text = "姓名:张三,年龄:25"
pattern = r"姓名:(\w+),年龄:(\d+)"
match = re.search(pattern, text)
if match:
print(match.group(0)) # "姓名:张三,年龄:25" (整个匹配)
print(match.group(1)) # "张三" (第一个捕获组)
print(match.group(2)) # "25" (第二个捕获组)
print(match.groups()) # ("张三", "25") (所有捕获组的元组)
5. 非捕获组
如果只想分组但不捕获内容,可以使用 (?:...)
语法:
python
# 普通捕获组
pattern1 = r"(https?)://(\w+.com)"
# 非捕获组
pattern2 = r"(?:https?)://(\w+.com)"
text = "https://example.com"
match1 = re.search(pattern1, text)
match2 = re.search(pattern2, text)
# match1.groups() 返回 ("https", "example.com")
# match2.groups() 返回 ("example.com",)
requests
requests首先需要能拿到网页的内容,这需要用到 requests
库,安装requests库后,会自动安装[urllib3](urllib3 2.1.0 documentation)库
pip install requests
基础使用方法如下,其他方法看源码无非就是request
的调用
ini
import requests
response = requests.request()
以下是 Python requests
库的深度解析,作为基于 urllib3
的上层封装,它提供了更人性化的 HTTP 客户端接口:
核心特性
-
极简 API 设计
-
一行代码完成 GET/POST 等操作,无需手动处理 URL 编码、参数拼接
csharpimport requests r = requests.get('https://api.example.com/data', params={'key': 'value'})
-
-
自动内容解析
-
自动解码响应内容(
r.text
根据编码推断字符串,r.json()
直接解析 JSON)scssprint(r.json()['result']) # 直接获取结构化数据
-
-
会话持久化
-
使用
Session
对象保持 Cookies、头信息、连接池复用csharpwith requests.Session() as s: s.headers.update({'User-Agent': 'MyApp'}) s.get('https://example.com/login', auth=('user', 'pass')) r = s.post('https://example.com/api', data={'action': 'query'})
-
-
SSL 验证与证书控制
-
默认启用证书验证,支持自定义 CA 包或禁用验证(生产环境慎用)
csharprequests.get('https://example.com', verify='/path/to/cert.pem') # 自定义证书
-
基础用法示例
GET 请求
ini
# 带查询参数 & 自定义头
headers = {'Accept': 'application/json'}
params = {'page': 1, 'limit': 20}
r = requests.get('https://api.example.com/items',
params=params,
headers=headers)
print(f"状态码: {r.status_code}")
print(f"响应头: {r.headers['Content-Type']}")
POST 请求
ini
# 表单提交
data = {'username': 'admin', 'password': 'secret'}
r = requests.post('https://example.com/login', data=data)
# JSON 提交(自动设置 Content-Type)
payload = {'key': 'value'}
r = requests.post('https://example.com/api', json=payload)
# 文件上传(多部分编码)
files = {'file': open('report.pdf', 'rb')}
r = requests.post('https://upload.example.com', files=files)
高级功能
-
超时与重试
inifrom requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry session = requests.Session() retry = Retry(total=3, backoff_factor=0.3, status_forcelist=[500, 502]) adapter = HTTPAdapter(max_retries=retry) session.mount('http://', adapter) session.mount('https://', adapter) response = session.get('https://example.com', timeout=(3.05, 27)) # 连接/读取超时
-
流式处理大文件
pythonr = requests.get('https://example.com/large-file', stream=True) with open('download.zip', 'wb') as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk)
-
代理配置
rustproxies = { 'http': 'http://10.10.1.10:3128', 'https': 'http://user:pass@10.10.1.10:3128', } requests.get('http://example.com', proxies=proxies)
响应对象关键属性
属性/方法 | 说明 | 示例 |
---|---|---|
status_code |
HTTP 状态码 | 200 |
headers |
响应头字典 | r.headers['Content-Type'] |
text |
解码后的字符串响应体 | html = r.text |
content |
原始字节数据 | img_data = r.content |
json() |
解析 JSON 响应体 | data = r.json() |
raise_for_status() |
非 2xx 状态码时抛出异常 | r.raise_for_status() |
异常处理
python
try:
r = requests.get('https://example.com', timeout=5)
r.raise_for_status() # 自动检查 4xx/5xx 错误
except requests.exceptions.HTTPError as errh:
print("HTTP 错误:", errh)
except requests.exceptions.ConnectionError as errc:
print("连接错误:", errc)
except requests.exceptions.Timeout as errt:
print("超时:", errt)
except requests.exceptions.RequestException as err:
print("未知请求异常:", err)
最佳实践
- 始终使用会话对象 - 提升性能(连接池复用)
- 明确超时设置 - 避免阻塞(推荐
timeout=(3.05, 27)
) - 优先使用
json
参数 - 替代手动序列化 - 及时关闭响应 - 使用
with
语句或手动调用r.close()
与 urllib3 对比
特性 | requests | urllib3 |
---|---|---|
API 易用性 | ⭐⭐⭐⭐⭐ | ⭐⭐ |
连接池自动化 | 自动管理 | 需手动配置 PoolManager |
流式下载 | 支持 (stream=True ) |
原生支持 |
适用场景 | 快速开发、REST API 调用 | 底层协议控制、高性能场景 |
💡 选择建议 :日常开发首选 requests
,需要极致性能或底层控制时使用 urllib3
。二者可混合使用(requests
底层依赖 urllib3
)。
urllib3
urllib3 是 Python 中一个功能强大且用户友好的 HTTP 客户端库,专注于提供线程安全的连接池、文件上传、重试机制等高级功能。以下是关键特性详解:
核心特性
-
线程安全 & 连接池
-
自动管理连接复用,显著减少 TCP 三次握手开销
-
支持
HTTPConnectionPool
和HTTPSConnectionPool
管理不同主机的连接iniimport urllib3 http = urllib3.PoolManager(num_pools=5) # 控制连接池数量
-
-
重试机制
inifrom urllib3.util import Retry retries = Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502]) http = urllib3.PoolManager(retries=retries) # 自动重试失败请求
-
SSL/TLS 安全
-
默认启用证书验证,支持自定义 CA 证书
inihttp = urllib3.PoolManager(ca_certs='/path/to/certs.pem')
-
典型使用场景
-
GET 请求
luaresp = http.request('GET', 'https://api.example.com/data') print(resp.status, resp.data.decode('utf-8'))
-
POST 表单 & JSON
iniresp = http.request('POST', 'https://api.example.com/submit', fields={'name': 'Alice', 'age': 30}) # 表单提交 # 或发送 JSON import json resp = http.request('POST', 'https://api.example.com/submit', body=json.dumps({'data': 'test'}).encode('utf-8'), headers={'Content-Type': 'application/json'})
-
文件上传
csharpwith open('file.txt', 'rb') as f: resp = http.request('POST', 'https://upload.example.com', fields={'file': ('filename.txt', f.read())})
常见对象介绍
以下是 urllib3 库中核心类的详细说明,掌握这些类能更好地控制 HTTP 请求行为:
1. PoolManager
-
功能:全局入口类,管理所有 HTTP/HTTPS 连接池
-
关键作用:
- 自动创建和维护
HTTPConnectionPool
/HTTPSConnectionPool
- 控制最大连接池数量 (
num_pools
) - 处理跨主机的连接复用
- 自动创建和维护
-
典型用法:
inihttp = urllib3.PoolManager( num_pools=10, # 最大连接池数量 maxsize=5, # 每个池最大连接数 block=True # 连接不足时是否阻塞等待 )
2. HTTPConnectionPool
-
功能:管理特定主机的 HTTP 连接池
-
核心特性:
- 同一主机复用 TCP 连接(减少握手开销)
- 支持连接存活时间 (
maxsize
+block
参数)
-
手动使用示例:
inipool = urllib3.HTTPConnectionPool('example.com', maxsize=5) resp = pool.request('GET', '/api/data')
3. Retry
-
功能:定义请求失败时的重试策略
-
可配置参数:
iniRetry( total=3, # 最大总重试次数 connect=2, # 连接错误重试次数 read=2, # 读取超时重试次数 status_forcelist=[502], # 强制重试的 HTTP 状态码 backoff_factor=0.5 # 重试间隔算法因子 )
-
高级用法:
inifrom urllib3.util import Retry retry = Retry(raise_on_status=False) # 不抛出状态码异常
4. ProxyManager
-
功能:通过代理服务器发送请求
-
特性:
- 支持 HTTP/HTTPS/SOCKS 代理
- 自动处理代理认证
-
示例:
iniproxy = urllib3.ProxyManager( 'http://user:pass@proxy.example.com:8080/', num_pools=5 ) resp = proxy.request('GET', 'http://target-site.com')
5. Response
-
功能:封装 HTTP 响应数据
-
关键属性:
bashresp.status # 状态码 (200) resp.headers # 响应头 (CaseInsensitiveDict) resp.data # 原始字节数据 resp.reason # 状态说明 ('OK')
-
最佳实践:
pythonwith http.request('GET', url, preload_content=False) as resp: for chunk in resp.stream(1024): # 流式读取大响应 process(chunk)
6. 异常类
类名 | 触发场景 | 处理建议 |
---|---|---|
HTTPError |
HTTP 状态码异常 (4xx/5xx) | 检查 resp.status |
MaxRetryError |
超过最大重试次数 | 检查网络或调整 Retry 配置 |
TimeoutError |
连接/读取超时 | 优化 timeout 参数 |
SSLError |
SSL 证书验证失败 | 检查证书路径或禁用验证 |
类协作流程
掌握这些类的用法,可以更精细地控制连接管理、错误处理等底层细节,适合需要高性能 HTTP 客户端的场景。
高级配置
ini
# 超时控制(连接/读取)
http.request(..., timeout=urllib3.Timeout(connect=2.0, read=10.0))
# 代理设置
http = urllib3.ProxyManager('http://proxy.example.com:8080/')
# 自定义头信息
headers = {'User-Agent': 'MyApp/1.0'}
http.request(..., headers=headers)
异常处理
python
try:
resp = http.request(...)
except urllib3.exceptions.HTTPError as e:
print("HTTP 错误:", e)
except urllib3.exceptions.MaxRetryError:
print("超过最大重试次数")
性能优化建议
- 连接复用 - 始终通过
PoolManager
实例发起请求 - 超时设置 - 避免因网络问题阻塞进程
- 限制连接池大小 - 防止占用过多系统资源
- 及时释放响应体 - 使用
resp.release_conn()
或上下文管理器
与标准库对比
特性 | urllib3 | 标准库 urllib |
---|---|---|
连接池管理 | ✅ 自动复用 | ❌ 无 |
重试机制 | ✅ 可定制策略 | ❌ 需手动实现 |
SSL 验证 | ✅ 默认开启 | ❌ 需复杂配置 |
💡 适用场景 :需精细控制 HTTP 行为时选择 urllib3,快速开发可考虑 requests
(基于 urllib3 的上层封装)
lxml
lxml是一个功能丰富并易于使用的用来处理xml或HTML文件的库。作为高效处理 XML/HTML 文档的利器,其底层基于 C 语言库 libxml2/libxslt,兼具高性能与丰富功能:
核心特性
- 闪电解析速度:比纯 Python 解析库快 5-20 倍
- XPath 1.0/2.0 支持:精准定位文档节点
- HTML 容错处理:自动修复残缺标签(类似浏览器行为)
- 内存友好:支持增量解析大文件
安装与基础用法
bash
pip install lxml # 安装
解析 XML
ini
from lxml import etree
xml = """
<bookstore>
<book category="web">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<year>2003</year>
<price>40.00</price>
</book>
</bookstore>
"""
root = etree.fromstring(xml) # 解析字符串
print(root.tag) # 输出根节点标签名: bookstore
# 或解析文件
tree = etree.parse('data.xml')
root = tree.getroot()
核心模块详解
1. ElementTree API
-
节点操作
ini# 遍历子节点 for child in root: print(child.tag, child.attrib) # 获取第一个 book 节点 first_book = root.find('book') # 获取所有 price 节点 prices = root.findall('.//price') # 修改节点内容 first_book.find('price').text = "49.99"
-
构建 XML
iniroot = etree.Element("root") child = etree.SubElement(root, "child") child.set("id", "123") child.text = "文本内容" print(etree.tostring(root, pretty_print=True).decode())
2. XPath 数据提取
ini
# 选择所有价格超过 30 的书籍标题
titles = root.xpath('//book[price>30]/title/text()')
# 带命名空间的 XPath(常见于 XML 文档)
ns = {'ns': 'http://example.com/ns'}
elements = root.xpath('//ns:element', namespaces=ns)
# 获取属性值
langs = root.xpath('//title/@lang')
3. HTML 解析模块
ini
from lxml.html import fromstring
broken_html = "<div><p>未闭合标签"
doc = fromstring(broken_html) # 自动修复结构
# CSS 选择器
links = doc.cssselect('a.external')
for link in links:
print(link.get('href'), link.text_content())
# 表单操作(自动化测试常用)
form = doc.forms[0]
form.fields = {'user': 'admin', 'pass': 'secret'}
submit_url = form.action # 获取表单提交地址
性能优化技巧
-
增量解析大文件
inicontext = etree.iterparse('large.xml', events=('end',), tag='item') for event, elem in context: process(elem) elem.clear() # 及时清理已处理节点
-
预编译 XPath
inifind_title = etree.XPath('//title/text()') titles = find_title(root) # 复用编译后的表达式
-
禁用无用功能
iniparser = etree.XMLParser(remove_blank_text=True, recover=True) # 忽略空白/错误恢复 tree = etree.parse('data.xml', parser)
常见问题处理
编码问题
ini
# 强制指定输入输出编码
parser = etree.XMLParser(encoding='gbk')
tree = etree.parse('gbk_data.xml', parser=parser)
output = etree.tostring(tree, encoding='utf-8')
处理 CDATA
ini
# 创建 CDATA 节点
cdata = etree.CDATA('<不可转义的内容>')
elem.append(cdata)
错误捕获
python
from lxml.etree import XMLSyntaxError
try:
etree.parse('invalid.xml')
except XMLSyntaxError as e:
print(f"解析错误: {e.message} (行 {e.position[0]})")
与 BeautifulSoup 对比
特性 | lxml | BeautifulSoup |
---|---|---|
解析速度 | ⭐⭐⭐⭐⭐ (C 扩展) | ⭐⭐ (纯 Python) |
HTML 容错 | 自动修复 | 依赖解析器 (如 html5lib) |
XPath 支持 | 原生支持 | 需第三方库 (lxml 驱动) |
内存占用 | 低 (SAX 模式) | 较高 (DOM 树) |
学习曲线 | 中等 | 简单 |
典型应用场景
- 爬虫数据提取:XPath + HTML 解析快速抽取结构化数据
- XML 配置文件处理:验证/修改符合 Schema 的配置文件
- Web 模板引擎:结合 XSLT 转换生成动态页面
- 大数据处理:流式解析 GB 级 XML 文件
扩展功能
ini
# XSLT 转换(需 xslt 文件)
transform = etree.XSLT(etree.parse('style.xsl'))
result = transform(tree)
print(str(result))
# Schema 验证
schema = etree.XMLSchema(file='schema.xsd')
if schema.validate(tree):
print("文档有效")
💡 最佳实践 :优先使用 XPath 而非逐层遍历,结合 lxml.html
处理网页抓取,对性能敏感场景启用解析器优化参数。
常用的爬虫策略和反爬策略
以下是爬虫策略与反爬策略的深度解析及攻防实战指南,结合技术实现与合规建议:
一、常用爬虫策略(攻击方)
1. 基础请求优化
-
请求头伪装
csharpheaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Referer': 'https://www.example.com/', 'Accept-Language': 'zh-CN,zh;q=0.9' } requests.get(url, headers=headers)
-
Cookie 管理
使用
requests.Session()
自动保持会话,或手动更新 cookies
2. 动态内容处理
-
Headless 浏览器
使用 Selenium/Puppeteer 渲染 JavaScript:
scssfrom selenium.webdriver import ChromeOptions options = ChromeOptions() options.add_argument('--headless') # 无头模式 driver = webdriver.Chrome(options=options) driver.get(url) print(driver.page_source)
-
API 逆向工程
通过浏览器开发者工具分析 XHR/Fetch 请求,直接调用数据接口
3. 分布式架构
-
IP 代理池
集成付费/免费代理服务,实现 IP 轮换:
rustproxies = { 'http': 'http://10.10.1.10:3128', 'https': 'http://user:pass@10.10.1.10:3128' } requests.get(url, proxies=proxies)
-
消息队列调度
使用 Redis/RabbitMQ 分配任务,实现多节点协同抓取
4. 反反爬绕过技术
- 验证码破解
商用方案:接入打码平台(如超级鹰)
自研方案:CNN 训练识别简单验证码 - TLS 指纹伪装
使用curl_cffi
等库模拟浏览器 TLS 指纹
5. 数据清洗与存储
- 去重策略
Bloom Filter 过滤已抓取 URL
数据指纹比对(MD5 等) - 异构数据存储
结构化数据存 MySQL/PostgreSQL
非结构化数据存 MongoDB/MinIO
二、主流反爬策略(防御方)
1. 基础特征检测
-
流量特征阻断
- 短时间高频访问(如 >100 次/分钟)
- 非常规 User-Agent 格式
- 缺失 Referer/Accept-Language 头
-
防御代码示例(Node.js):
kotlinif(req.headers['user-agent'].includes('Python-urllib')) { return res.status(403).send('Bot detected!'); }
2. 高级行为分析
- 鼠标轨迹检测
通过 JavaScript 监控用户操作模式 - 页面停留时间
正常用户访问间隔 >3 秒,爬虫往往连续请求 - Honeypot 陷阱
隐藏不可见链接(CSS:display:none
),捕获点击者
3. 动态防护体系
-
加密参数
使用前端生成
_token
、sign
等加密校验参数ini# 爬虫需逆向生成算法 token = hashlib.md5(f"{timestamp}secret_key".encode()).hexdigest()
-
API 限速
令牌桶算法控制接口调用频次:
pythonfrom flask_limiter import Limiter limiter = Limiter(key_func=get_remote_address) @app.route("/api", methods=["GET"]) @limiter.limit("10/minute") # 限速
4. 深度学习对抗
- 用户行为建模
收集点击流数据,训练 LSTM 模型识别机器行为 - 动态挑战响应
随机触发验证码(滑块、点选等)
三、攻防成本对比表
策略 | 爬虫方成本 | 防御方成本 | 突破难度 |
---|---|---|---|
User-Agent 检测 | 低 | 低 | ⭐ |
IP 代理池 | 中 | 中 | ⭐⭐ |
验证码识别 | 高 | 高 | ⭐⭐⭐⭐ |
TLS 指纹验证 | 高 | 高 | ⭐⭐⭐⭐ |
行为模式分析 | 极高 | 极高 | ⭐⭐⭐⭐⭐ |
四、合规建议
-
遵守 robots.txt
pythonfrom urllib.robotparser import RobotFileParser rp = RobotFileParser() rp.set_url('https://example.com/robots.txt') rp.read() if rp.can_fetch('MyBot', url): # 执行抓取
-
控制请求频率
添加随机延迟(2-10 秒)
luaimport random, time time.sleep(random.uniform(1, 3))
-
数据使用授权
优先使用官方 API(如 Twitter API、Facebook Graph API)
五、未来趋势
- AI 驱动攻防:GAN 生成对抗网络制造拟人流量
- 区块链溯源:爬虫行为上链存证
- 边缘计算防护:Cloudflare Workers 等边缘节点实时拦截
掌握这些策略需要持续关注最新反爬技术演进,建议定期研究:
- 浏览器 DevTools 协议更新
- WebAssembly 反混淆技术
- Web 标准(如 Privacy Sandbox)的影响