3. 订阅机制入门
法规文本订阅不是“把网页加到收藏夹”那么简单。它要解决四个连续问题:从哪里取、多久取一次、每次取多少、取回来如何判断新旧。这四个问题分别对应订阅源配置、更新频率、增量抓取与去重策略。任何一环设计不当,都会导致漏采、重复入库、解析失败或存储成本失控。本节从工程视角拆解这套机制,并给出可直接落地的配置与判断逻辑。
一、核心原理:订阅是一条“状态化”的数据管道
订阅的本质,是把外部法规站点的“变化”转化为本地可识别的“事件”。它依赖三个关键状态:源状态(站点是否可达、结构是否变化)、抓取状态(上次抓取时间、游标、分页位置)、内容状态(正文指纹、标题、文号、生效日期)。只有把这三类状态持久化,增量与去重才有依据。
订阅源配置决定了管道的入口。一个法规订阅源通常包含:源名称、入口 URL、列表页规则、详情页规则、编码、请求头、限速、更新频率、增量标识字段。配置不是写死在代码里,而应外置为可版本管理的 YAML 或 JSON,便于审计与回滚。
source:
name: "国务院政策文件库"
entry: "https://www.gov.cn/zhengce/zuixin.htm"
list_selector: "ul.list li a"
detail_selector: "div.pages_content"
encoding: "utf-8"
headers:
User-Agent: "RegWatch/1.0 (+contact@example.com)"
rate_limit: "1 req / 3s"
frequency: "every 6h"
incremental_key: "publish_date"
dedup_key: ["title", "doc_number"]
二、更新频率:在时效性与站点压力之间取平衡
更新频率不是越密越好。频率过高会触发反爬、浪费带宽,并放大解析错误;频率过低则可能错过法规的征求意见窗口或生效节点。实践中可按“法规类型 + 发布规律”分层设置:
- 高频源:政策发布厅、征求意见稿栏目,建议 2~6 小时一次。
- 中频源:地方性法规、部门规章,建议 12~24 小时一次。
- 低频源:年度汇编、标准全文库,建议每日或每周一次。
- 事件驱动:对已订阅的详情页,可在生效日前 7 天提高检查频率。
频率配置还应支持“退避策略”:连续失败时自动拉长间隔,恢复后回归正常。这比固定轮询更稳健。
三、增量抓取:用游标与指纹减少无效请求
增量抓取的目标是“只取新增或变更的部分”。常见做法有三种:时间游标(记录上次最大发布时间)、分页游标(记录已抓页码或偏移量)、内容指纹(对标题+正文做哈希)。时间游标适合列表按时间倒序的站点;分页游标适合有稳定分页的栏目;内容指纹适合详情页可能被修订的场景。
一个可用的增量判断流程如下:先请求列表页,提取候选链接与发布时间;与本地游标比较,过滤掉早于游标且指纹未变的条目;对剩余条目请求详情页,计算正文指纹;若指纹已存在则跳过入库,否则写入并更新游标。整个过程应记录日志,便于复盘漏采原因。
def incremental_fetch(source, cursor):
items = parse_list(source.entry)
new_items = []
for it in items:
if it.publish_date <= cursor.last_publish:
continue
detail = fetch_detail(it.url)
fp = sha256(detail.title + detail.body)
if fp in cursor.fingerprints:
continue
new_items.append((it, detail, fp))
return new_items
四、去重策略:多键组合比单一标题更可靠
法规文本的重复来源很多:同一文件被多个栏目转载、标题略有差异、正文含附件、文号相同但版本不同。仅靠标题去重会误杀,仅靠 URL 去重会漏掉转载。推荐使用多键组合 + 指纹的分层去重:
| 去重层级 | 判断键 | 适用场景 | 风险 |
|---|---|---|---|
| URL 级 | 规范化 URL | 同一页面重复抓取 | 无法识别转载 |
| 文号级 | 发文机关 + 文号 | 正式文件唯一标识 | 部分文件无文号 |
| 标题级 | 标题归一化 | 快速初筛 | 标题相似但内容不同 |
| 指纹级 | 正文 SHA-256 | 识别修订与转载 | 附件变化需单独处理 |
五、案例场景:一次漏采与一次重复入库的复盘
场景一:漏采。某地方规章在周五 18:00 发布,订阅频率为每日 9:00。结果周一才抓到,错过了周末的征求意见截止提醒。复盘发现:频率未按栏目发布规律调整,且未对“征求意见”类源单独提频。改进:对征求意见栏目设置 4 小时频率,并增加“截止日期临近”告警。
场景二:重复入库。同一文件被“政策文件”和“政策解读”两个栏目转载,标题分别为“XX办法”和“XX办法(全文)”。仅按标题去重失败,导致两条记录。复盘发现:未使用文号与正文指纹组合。改进:以文号为主键,正文指纹为辅,标题仅作展示。
六、常见误区与检查清单
- 误区一:频率越高越好。高频会触发封禁,且增加解析噪声。
- 误区二:只存正文不存元数据。缺少发布时间、文号、来源,后续影响识别无法回溯。
- 误区三:去重只做一次。应在入库前、入库后、影响识别前分阶段校验。
- 误区四:忽略编码与附件。GBK 页面乱码、PDF 附件未解析,都会导致指纹失真。
落地时可用以下清单自检:源配置是否外置并可版本管理;频率是否按栏目分层;增量游标是否持久化;指纹是否覆盖标题与正文;去重是否多键组合;失败是否有退避与告警;日志是否记录候选数、新增数、跳过数。把这七项做扎实,订阅机制才算真正入门。