爬虫写多了,一定会遇到反爬。这篇文章总结最常见的 5 种反爬手段和对应的解决方案。
一、反爬手段全景
| 反爬方式 | 特征 | 难度 |
|---|---|---|
| User-Agent 检测 | 请求头不含浏览器标识 | ⭐ |
| IP 频率限制 | 同一 IP 短时间大量请求被封 | ⭐⭐ |
| Cookie/Session 校验 | 不带 Cookie 直接返回 403 | ⭐⭐ |
| 请求头完整性校验 | Referer、Origin 等不完整被拦截 | ⭐⭐⭐ |
| 验证码 | 图形验证码、滑块验证码 | ⭐⭐⭐⭐ |
二、User-Agent 伪装
最简单的反爬,也是最容易被忽略的。
import requests
# 错误:没有设置请求头
resp = requests.get(url)
# 网站一看来的是 python-requests,直接封
# 正确:伪装成浏览器
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"Chrome/120.0.0.0 Safari/537.36"
}
resp = requests.get(url, headers=headers)
建议准备一个 User-Agent 池,随机切换:
import random
USER_AGENTS = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/120.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ... Safari/605.1.15",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Firefox/121.0",
"Mozilla/5.0 (X11; Linux x86_64) ... Chrome/119.0.0.0 Safari/537.36",
]
def get_headers():
return {"User-Agent": random.choice(USER_AGENTS)}
三、IP 代理池
同一 IP 短时间内大量请求,网站会直接封 IP。
# 使用代理
proxies = {
"http": "http://127.0.0.1:7890", # 本地代理
"https": "http://127.0.0.1:7890"
}
resp = requests.get(url, proxies=proxies)
# 随机切换代理
proxy_list = [
"http://代理1:端口",
"http://代理2:端口",
"http://代理3:端口",
]
proxy = random.choice(proxy_list)
resp = requests.get(url, proxies={"http": proxy, "https": proxy})
免费代理获取
def get_free_proxies():
"""从免费代理网站获取代理(示例:快代理)"""
url = "https://www.kuaidaili.com/free/inha/1/"
headers = {"User-Agent": "Mozilla/5.0 ..."}
resp = requests.get(url, headers=headers)
resp.encoding = "utf-8"
tree = etree.HTML(resp.text)
proxies = []
for row in tree.xpath('//table/tbody/tr'):
ip = row.xpath('./td[1]/text()')[0]
port = row.xpath('./td[2]/text()')[0]
proxies.append(f"{ip}:{port}")
return proxies
请求频率控制
比代理更重要的是一一控制请求速度:
import time
# 每次请求间隔 1~3 秒
for page in range(10):
resp = requests.get(url)
time.sleep(random.uniform(1, 3)) # 关键
四、Cookie 处理
有些网站必须带 Cookie 才能访问:
# 方法1:直接从浏览器复制 Cookie
cookies = {
"sessionid": "abc123...",
"csrf_token": "def456..."
}
resp = requests.get(url, cookies=cookies)
# 方法2:先用 requests.Session 保持会话
session = requests.Session()
session.get(login_url) # 先访问登录页获取 Cookie
session.post(login_url, data=login_data) # 登录
resp = session.get(target_url) # 带着 Cookie 访问目标页
五、请求头完整性
一些反爬严格的网站会检查请求头的完整性:
headers = {
"User-Agent": "Mozilla/5.0 ...",
"Referer": "https://www.example.com", # 从哪跳转来的
"Origin": "https://www.example.com", # 来源站占
"Accept-Language": "zh-CN,zh;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
}
# 先用浏览器开发者工具 F12 → Network → 任意请求
# 把 Request Headers 完整复制过来
六、应对验证码
验证码是反爬的终极大招,常见应对方案:
# 方案1:打码平台(推荐)
# 使用 超级鹰、打码兔 等平台自动识别
import hashlib
def recognize_captcha(image_file):
"""调用打码平台 API 识别验证码"""
# 各平台有 SDK,按文档调用即可
return "识别结果"
# 方案2:Selenium 手动介入
# 当出现验证码时暂停,等手动处理
input("请手动完成验证码,完成后按 Enter...")
七、完整实战:带反爬策略的爬虫模板
import requests
import random
import time
from lxml import etree
class AntiSpiderCrawler:
"""带反爬策略的爬虫模板"""
def __init__(self):
self.session = requests.Session()
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
"Accept-Language": "zh-CN,zh;q=0.9",
})
self.proxies = None
def set_proxy(self, proxy):
self.proxies = {"http": proxy, "https": proxy}
def request(self, url, retry=3):
"""带重试机制的请求"""
for i in range(retry):
try:
resp = self.session.get(url, proxies=self.proxies, timeout=10)
if resp.status_code == 200:
return resp
elif resp.status_code == 403:
print(f"被反爬拦截,切换代理重试...")
time.sleep(2)
else:
print(f"状态码: {resp.status_code}")
except Exception as e:
print(f"请求失败: {e}")
time.sleep(random.uniform(1, 3))
return None
# 使用
crawler = AntiSpiderCrawler()
resp = crawler.request("https://example.com/data")
if resp:
tree = etree.HTML(resp.text)
# 提取数据...
总结
反爬与反反爬是一个持续对抗的过程。核心原则:
- 模拟真人 — User-Agent、请求间隔、行为模式
- 降低频率 — 控制请求速度比任何技术都重要
- 分散 IP — 被封了就换代理
- 完整请求头 — 越像浏览器越安全
如果对你有帮助,欢迎点赞、评论、关注【张老师技术栈】,持续分享 Java/Python/爬虫 实战干货。

1781

被折叠的 条评论
为什么被折叠?



