首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从URL构造到字段提取的正则优化 —— 豆瓣影评的实践记录

从URL构造到字段提取的正则优化 —— 豆瓣影评的实践记录

原创
作者头像
jackcode
发布2025-08-28 11:43:30
发布2025-08-28 11:43:30
2170
举报
文章被收录于专栏:爬虫资料爬虫资料

一、起点:一次“看似简单”的小任务

去年,我在做一个小实验:想抓取几部经典电影的豆瓣影评,看看不同年份观众的评价差异。刚开始觉得没什么难度,不就是循环翻页、解析HTML吗?

结果一上手,才发现里面暗藏玄机。

  • 链接结构各式各样 豆瓣影评的入口并不统一。既有批量翻页的地址:
代码语言:plain
复制
https://movie.douban.com/subject/1292052/reviews?start=0

也有单独一篇影评的地址:

代码语言:plain
复制
https://movie.douban.com/review/1234567/

表面相似,实则需要不同的解析方式。

  • 页面字段也不老实 评论的时间格式并不固定,有时是完整的日期加时间,有时就剩个年月日。作者昵称的定位也多变,有时在 <a> 标签里,有时却嵌在别的节点中。最初写的字符串截取法,几乎每次都要改。

那几天,我的脚本几乎是“跑一次,改一次”。


二、摸索:问题到底卡在哪里

我后来重新梳理:真正困扰的核心是两个点。

  • URL 怎么分辨:翻页 URL 和单条 URL 的模式不一样,如果不做区分,逻辑根本跑不通。
  • 字段怎么抽取:评论时间和作者信息没有统一格式,写死的解析规则肯定不稳。

于是我开始往正则表达式的方向想:能不能写一套更“宽容”的模式,把这些变动都涵盖进去?


三、转机:用正则抽象出“通用规则”

经过几番尝试,慢慢找到了一些规律。

  • 翻页 URL:reviews?start=(\d+)
  • 单条影评 URL:review/(\d+)/
  • 评论时间:
代码语言:plain
复制
(\d{4}[-/]\d{1,2}[-/]\d{1,2}(?:\s+\d{1,2}:\d{2}:\d{2})?)

既能匹配“2023-08-27”,也能识别“2023-08-27 12:30:00”。

  • 作者昵称:
代码语言:plain
复制
<a href="/people/[^"]+/">([^<]+)</a>

一旦抽象成这些模式,后续就很顺畅了:URL 能自动识别类型,评论时间和作者也能统一提取。


四、代码实践:带代理的豆瓣采集

下面是简化版的示例代码,加入了爬虫代理配置,提高采集成功率:

代码语言:python
复制
import re
import requests

# 代理设置(亿牛云示例)
proxy_host = "proxy.16yun.cn"
proxy_port = "31000"
proxy_user = "16YUN"
proxy_pass = "16IP"

proxies = {
    "http": f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}",
    "https": f"http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}"
}

# 示例:豆瓣影评第一页
url = "https://movie.douban.com/subject/1292052/reviews?start=0"
resp = requests.get(url, proxies=proxies, timeout=10)
html = resp.text

# 解析翻页参数
page_pattern = re.compile(r"reviews\?start=(\d+)")
page = page_pattern.search(url)
if page:
    print("当前页码:", page.group(1))

# 提取影评 ID
review_pattern = re.compile(r"https://movie.douban.com/review/(\d+)/")
review_ids = review_pattern.findall(html)
print("影评ID示例:", review_ids[:5])

# 提取评论时间
time_pattern = re.compile(r"(\d{4}[-/]\d{1,2}[-/]\d{1,2}(?:\s+\d{1,2}:\d{2}:\d{2})?)")
times = time_pattern.findall(html)
print("评论时间:", times[:5])

# 提取作者昵称
author_pattern = re.compile(r'<a href="/people/[^"]+/">([^<]+)</a>')
authors = author_pattern.findall(html)
print("作者示例:", authors[:5])

五、回头看:最大的收获

这次经历让我有些感触:

  • 别依赖写死逻辑,哪怕今天能跑通,明天页面改动就全废。
  • 正则不是万能钥匙,但能兜底,尤其是在字段格式多变时。
  • 代理要跟上,特别是像豆瓣这种会有限流的网站。

过去我写爬虫时,总是先考虑“跑通”,很少想“如果格式变了怎么办”。这次之后,我更习惯去总结模式,再去写代码。

一句话总结:采集豆瓣影评的过程,其实是一堂“模式化思维”的课。链接和字段表面上杂乱无章,但只要把变化抽象成规则,就能让代码更稳、更耐用。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 图片
    • 一、起点:一次“看似简单”的小任务
    • 二、摸索:问题到底卡在哪里
    • 三、转机:用正则抽象出“通用规则”
    • 四、代码实践:带代理的豆瓣采集
    • 五、回头看:最大的收获
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档