告别复杂解析!用Python requests + re 轻松搞定Scrape Center SSR1电影网站爬虫
·
轻量级爬虫实战:用Python标准库抓取Scrape Center电影数据
每次看到那些复杂的爬虫框架配置就头疼?其实对于结构规整的静态网页,用Python自带的requests和re模块就能快速搞定数据抓取。今天我们就以Scrape Center的SSR1电影网站为例,教你如何用不到100行代码实现一个轻量级但功能完备的爬虫。
1. 为什么选择requests+re组合
在Python爬虫领域,Scrapy和BeautifulSoup确实功能强大,但它们的学习曲线和项目配置成本往往让初学者望而却步。相比之下,requests+re组合有以下优势:
- 零依赖 :仅需Python标准库,无需安装额外包
- 学习成本低 :requests的API设计极其简单直观
- 执行效率高 :正则表达式处理静态页面速度飞快
- 调试方便 :可以逐步测试每个正则匹配环节
提示:这种方案最适合结构固定、不需要处理JavaScript渲染的静态网页。对于动态加载的现代网站,可能需要考虑Selenium等工具。
2. 环境准备与基础配置
开始前,确保你的Python环境已经就绪。我们只需要最基本的库:
import re
import time
import requests
from requests.exceptions import RequestException
虽然可以添加fake_useragent来伪装浏览器,但为了保持极简,我们先用固定User-Agent:
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
3. 网页结构分析与正则设计
打开Scrape Center SSR1的任意页面(如 https://ssr1.scrape.center/page/1 ),查看源代码会发现电影信息都包裹在 <div class="el-col-md-4"> 的容器中。每个电影包含:
- 封面图片URL(img标签的src属性)
- 电影名称(h2标签内文本)
- 分类标签(多个button下的span文本)
- 详细信息(国家、时长、上映时间等)
- 评分(score类下的p标签文本)
对应的正则表达式可以这样设计:
PATTERN = re.compile(
r'<div.*?el-col-md-4.*?'
r'src="(.*?)".*?' # 图片URL
r'<h2.*?>(.*?)</h2>.*?' # 电影名称
r'button.*?<span>(.*?)</span>.*?' # 分类标签1
r'button.*?<span>(.*?)</span>.*?' # 分类标签2
r'button.*?<span>(.*?)</span>.*?' # 分类标签3
r'info.*?<span.*?>(.*?)</span>.*?' # 国家
r'<span.*?>(.*?)</span>.*?' # 类型
r'<span.*?>(.*?)</span>.*?' # 时长
r'info.*?<span.*?>(.*?)</span>.*?' # 上映时间
r'score.*?>(.*?)</p>', # 评分
re.S)
4. 核心功能实现
4.1 页面获取函数
def fetch_page(url):
try:
resp = requests.get(url, headers=HEADERS, timeout=10)
resp.encoding = resp.apparent_encoding
return resp.text if resp.status_code == 200 else None
except RequestException as e:
print(f"请求失败: {e}")
return None
4.2 数据解析函数
def parse_movies(html):
items = re.findall(PATTERN, html)
movies = []
for item in items:
movie = {
'cover': item[0],
'title': item[1],
'categories': list(set(item[2:5])), # 去重
'country': item[5],
'duration': item[7],
'release': item[8],
'score': item[9].strip()
}
movies.append(movie)
return movies
4.3 数据存储函数
虽然原始示例使用了Excel存储,但JSON格式更适合这种结构化数据:
import json
def save_to_json(data, filename='movies.json'):
with open(filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
5. 完整爬虫实现与优化
将所有组件组合起来,并添加一些优化措施:
def scrape_ssr1(max_page=10):
base_url = "https://ssr1.scrape.center/page/{}"
all_movies = []
for page in range(1, max_page + 1):
url = base_url.format(page)
html = fetch_page(url)
if not html:
continue
movies = parse_movies(html)
all_movies.extend(movies)
print(f"已抓取第{page}页,共{len(movies)}部电影")
time.sleep(1) # 礼貌性延迟
save_to_json(all_movies)
print(f"全部完成,共抓取{len(all_movies)}部电影数据")
6. 正则表达式调试技巧
编写复杂的正则表达式时,可以分步验证:
- 逐步构建 :先匹配大框架,再逐步添加细节
- 在线测试 :使用regex101.com等工具实时调试
- 可视化工具 :如Debuggex帮助理解模式结构
- 单元测试 :对样本HTML片段进行针对性测试
遇到匹配问题时,可以:
- 检查
re.S标志是否正确使用(处理换行) - 确认贪婪
.*?和非贪婪.*的区别 - 使用
re.DEBUG标志查看解析过程
7. 扩展与进阶
虽然这个爬虫已经很实用,但还可以进一步优化:
- 异常处理 :增加重试机制应对网络波动
- 并发请求 :使用
concurrent.futures提升速度 - 增量爬取 :记录已抓取URL避免重复
- 数据清洗 :对抓取结果进行规范化处理
# 带重试机制的请求函数示例
def fetch_with_retry(url, retries=3):
for i in range(retries):
try:
return fetch_page(url)
except Exception as e:
if i == retries - 1:
raise
time.sleep(2 ** i) # 指数退避
在实际项目中,我发现正则表达式虽然强大,但对于特别复杂的HTML结构,维护成本会显著上升。这时候可以考虑用 lxml 这样的轻量级解析库作为补充,它比BeautifulSoup更快,又比纯正则更易维护。
更多推荐

所有评论(0)