网络爬虫与反爬基础
从零写一个礼貌、稳定、可扩展的爬虫:请求、解析、限速、UA 池与常见反爬应对思路。
项目简介
爬虫的核心不是“爬得快”,而是 稳定、礼貌、合规。本页给出最小可用的采集框架:限速与重试、随机 UA、robots.txt 检查、常见反爬(验证码 / 频率限制)应对思路。
代码示例:基础采集框架
py
import time
import random
import requests
from bs4 import BeautifulSoup
UA_POOL = [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Safari/605.1.15",
]
def fetch(url: str, retries: int = 3):
for i in range(retries):
headers = {"User-Agent": random.choice(UA_POOL)}
try:
r = requests.get(url, headers=headers, timeout=8)
if r.status_code == 200:
return r.text
if r.status_code == 429:
time.sleep(10 + i * 5) # 被限速,退避重试
except requests.RequestException:
pass
time.sleep(1 + random.random() * 2)
return None
def parse_links(html: str):
soup = BeautifulSoup(html, "html.parser")
return [a.get("href") for a in soup.find_all("a") if a.get("href")]
if __name__ == "__main__":
html = fetch("https://example.com")
if html:
print(parse_links(html)[:10])代码示例:限速队列
py
import threading
import time
class RateLimiter:
def __init__(self, max_qps: float = 1.0):
self.gap = 1.0 / max_qps
self.lock = threading.Lock()
self.last = 0.0
def wait(self):
with self.lock:
now = time.time()
delta = self.gap - (now - self.last)
if delta > 0:
time.sleep(delta)
self.last = time.time()
limiter = RateLimiter(max_qps=1) # 每秒最多 1 个请求
# 在 fetch() 前调用 limiter.wait() 即可全局限速反爬应对基础
- 频率限制 / 429:降低 QPS、指数退避重试、分布式抓取。
- 请求头校验:伪造完整浏览器头(UA、Referer、Accept-Language)。
- JS 动态渲染:改用 Playwright / Selenium 渲染后采集。
- 验证码:优先走官方 API 或授权数据源,避免破解对抗。
- 合规红线:遵守 robots.txt、不抓个人隐私、不过度并发、尊重版权。
操作步骤
pip install requests beautifulsoup4后运行基础采集框架。- 把限速器接入
fetch(),形成礼貌抓取节奏。 - 遇到动态页面再引入 Playwright;先判断是否触发反爬,再决定策略。
来源参考
GitHub 关键词:python-spider-starter、requests-retry-ua、rate-limiter-py(链接可替换为实际仓库地址)。