1. 爬虫基础与工具选型
Python作为爬虫领域的首选语言,其优势在于丰富的生态库和简洁的语法结构。Requests库以人性化的API设计著称,相比原生urllib减少了约70%的代码量。BeautifulSoup4(BS4)则是HTML解析利器,支持多种解析器,其中lxml解析器的速度比标准库的html.parser快8-10倍。
重要提示:实际项目中务必遵守robots.txt协议,设置合理的请求间隔(建议≥2秒),避免对目标服务器造成负担
我常用的开发环境配置:
- Python 3.8+(兼容性最佳版本)
- Requests 2.26+(支持HTTP/2)
- BeautifulSoup4 4.10+(新版本修复了部分标签解析问题)
- 可选但推荐:lxml解析器(需单独安装)
bash复制pip install requests beautifulsoup4 lxml
2. 核心组件深度解析
2.1 Requests实战技巧
请求头定制是突破基础反爬的关键。这里分享一个真实可用的headers模板:
python复制headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Referer': 'https://www.google.com/',
'DNT': '1'
}
异常处理必须考虑的三种情况:
- 连接超时(timeout=10)
- HTTP错误状态码(resp.raise_for_status())
- SSL证书验证(verify=False/True)
2.2 BeautifulSoup高阶用法
解析器性能对比(测试10MB HTML文件):
| 解析器 | 解析时间 | 内存占用 | 兼容性 |
|---|---|---|---|
| lxml | 1.2s | 85MB | 最好 |
| html.parser | 3.8s | 120MB | 内置 |
| html5lib | 8.5s | 210MB | 最差 |
CSS选择器与find_all的复合使用示例:
python复制soup.select('div.article')[0].find_all('a', class_='external')
3. 完整爬虫项目实战
以爬取豆瓣电影Top250为例,分步骤拆解:
3.1 页面分析阶段
使用Chrome开发者工具(F12)观察:
- 数据存储在class="info"的div中
- 分页通过?start=参数控制
- 评分在class="rating_num"的span标签
3.2 代码实现
python复制import requests
from bs4 import BeautifulSoup
import time
def scrape_douban():
base_url = "https://movie.douban.com/top250"
headers = {'User-Agent': 'Mozilla/5.0'}
for page in range(0, 250, 25):
url = f"{base_url}?start={page}"
resp = requests.get(url, headers=headers)
soup = BeautifulSoup(resp.text, 'lxml')
for item in soup.select('.item'):
title = item.select('.title')[0].text
rating = item.select('.rating_num')[0].text
print(f"{title}: {rating}")
time.sleep(3) # 遵守爬虫礼仪
3.3 数据存储优化
三种存储方式对比:
- CSV文件(适合新手)
python复制import csv
with open('movies.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['标题', '评分'])
- SQLite数据库(结构化存储)
python复制import sqlite3
conn = sqlite3.connect('movies.db')
c = conn.cursor()
c.execute('CREATE TABLE IF NOT EXISTS movies (title TEXT, rating REAL)')
- JSON文件(便于传输)
python复制import json
data = [{'title': title, 'rating': rating}]
with open('movies.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False)
4. 反爬应对策略实录
4.1 常见反爬手段破解
- User-Agent检测:使用fake_useragent库动态生成
python复制from fake_useragent import UserAgent
ua = UserAgent()
headers = {'User-Agent': ua.random}
- IP封锁:使用免费代理池(需自行验证)
python复制proxies = {
'http': 'http://123.123.123.123:8080',
'https': 'https://123.123.123.123:8080'
}
- 验证码识别:使用Tesseract-OCR(准确率约60%)
python复制import pytesseract
from PIL import Image
captcha_text = pytesseract.image_to_string(Image.open('captcha.jpg'))
4.2 法律合规要点
- 严格遵守网站robots.txt规定
- 单域名请求频率≤30次/分钟
- 禁止爬取用户隐私数据
- 商业用途需获得授权
5. 性能优化技巧
5.1 并发处理方案
比较三种并发方式:
| 方式 | 优点 | 缺点 |
|---|---|---|
| 多线程 | 实现简单 | GIL限制 |
| 多进程 | 真正并行 | 内存消耗大 |
| 异步IO | 高效 | 代码复杂度高 |
推荐aiohttp异步方案:
python复制import aiohttp
import asyncio
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.text()
5.2 缓存机制实现
使用requests-cache库实现自动缓存:
python复制import requests_cache
requests_cache.install_cache(
'demo_cache',
expire_after=3600, # 1小时缓存
allowable_methods=['GET']
)
6. 项目扩展方向
- 增量爬虫:记录已爬取URL
python复制import hashlib
url_hash = hashlib.md5(url.encode()).hexdigest()
- 分布式爬虫:使用Scrapy-Redis
- 数据可视化:Pyecharts生成图表
- 自动化部署:Docker容器化
调试技巧:在开发阶段使用mitmproxy抓包工具,可以实时查看请求响应内容,快速定位解析错误
我在实际项目中总结的黄金法则:
- 先小规模测试解析逻辑(单页面)
- 添加完善的日志记录
- 永远假设HTML结构会变
- 重要数据必须本地备份