数据类 Skill 系列走到第六篇。前几篇从清洗写到分析再写到挖掘,但所有人都默认了一件事:数据已经在了。现实中根本不是——数据采集才是这条流水线的源头,也是失败率最高、最需要工程化的一环。网站改版、接口限流、反爬升级、字段变更,任何一个波动都会让整条下游流水线断粮。这篇讲透数据采集 Skill 怎么设计:它的边界、它的三大技术命门,以及它和下游清洗 Skill 之间那条不能越过的线。
一、先定位:数据采集在流水线的位置
把整个数据流水线画出来,采集在最上游:
数据采集 → 数据清洗 → 数据分析 / 数据挖掘 → 报告 / 决策 ▲ └─ 采集的产出是"原始数据",不是"干净数据"采集 Skill 的第一设计原则:它只负责"把数据拿到手",不负责"把数据变干净"。轻量处理(去 HTML 标签、转编码)可以做,但深度清洗(去重、口径统一、异常处理)必须留给清洗 Skill。为什么?因为采集和清洗的关注点完全不同——采集关注"能不能拿到、全不全",清洗关注"干不干净、对不对"。两者耦合,改一处动全身。
二、数据采集的四种形态
先分清要采什么,因为不同形态的 Skill 设计差异巨大:
| 形态 | 数据来源 | 特点 | 典型工具 |
|---|---|---|---|
| 网页抓取 | 静态/动态网页 | 结构易变、有反爬 | 请求库 + 解析库 |
| API 调用 | 官方/第三方接口 | 稳定但有配额、需鉴权 | HTTP 客户端 |
| 数据库同步 | 业务库 / 数仓 | 稳定但权限敏感 | 连接器、ETL |
| 文件导入 | CSV、Excel、日志 | 最简单 | 读取库 |
设计建议:一个采集 Skill 聚焦一种来源。"万能采集器"在现实中不存在——网页采集和 API 采集的失败模式、重试策略、合规要求完全不同。先做最痛的那一种。
三、定义输入输出契约
采集 Skill 的边界定义,重点在"采什么、采到什么样算完成":
输入: - 目标定义(URL 列表 / 接口参数 / 数据表范围) - 采集配置(频率、字段清单、页数限制、时间范围) 输出: - 原始数据文件(统一格式,含采集时间戳) - 采集日志(成功/失败/重试记录,缺失清单) - 数据完整性报告(应采 X 条,实采 Y 条,缺 Z 条) 边界: - 只做采集与轻量提取,不深度清洗 - 遵守目标方的 robots、授权与频率要求 - 不采集个人敏感信息(除非有明确合法依据)注意输出里的"缺失清单"——这是采集 Skill 和手工爬虫最大的区别。手工爬虫"抓到多少算多少",采集 Skill 必须知道自己缺了多少、缺在哪。下游清洗和分析才能判断这批数据的可信度。
四、核心流程:采集不是"发请求",是一套工程
步骤 1:目标解析(规则) → 解析 URL 列表 / 接口定义,生成任务队列 步骤 2:调度与限流(规则,关键) → 控制请求频率(QPS 上限)、并发数、时间窗口 步骤 3:请求与重试(规则,关键) → 发送请求;失败按指数退避重试(如 3 次:2s/4s/8s) → 区分可重试错误(超时、5xx)与不可重试错误(404、鉴权失败) 步骤 4:解析与轻量提取(规则) → 从响应中提取目标字段;HTML 用选择器,JSON 用路径 → 只做格式转换,不做语义清洗 步骤 5:完整性核对(规则) → 对照任务队列核对实采数量,生成缺失清单 步骤 6:存储与日志(规则) → 写入统一格式(CSV/JSON/数据库),附带采集时间戳这个流程的精华在步骤 2 和 3:采集 Skill 的工程质量不在"能抓到",而在"被抓挂之后能自己恢复"。重试策略、限流策略、断点续采,才是它和一次性爬虫脚本的分水岭。
五、三大技术命门
1. 稳定性:断点续采是底线
采集是个长任务,跑到第 3000 条断了,不能从头再来。Skill 必须内置:
- 任务队列持久化:已完成的记录标记,进程重启后从断点继续 - 增量采集:记录上次采集位置,下次只采新增 - 失败重试:可重试错误自动重试,不可重试错误入"待人工"清单设计原则:任何一次采集都要"可中断、可恢复、可续采"。这是采集 Skill 与手工脚本最本质的工程化差距。
2. 健壮性:目标会变,Skill 不能一碰就碎
网站改版是常态,字段名说改就改。Skill 要:
- 解析规则与代码分离:选择器/字段映射做成配置,改版时只改配置 - 结构变化检测:解析结果为空/异常时,先怀疑"结构变了"而不是"没数据" - 异常采样存档:解析失败的响应体存下来,供排查设计原则:把"解析规则"当作需要维护的配置资产,而不是写在代码里的死字符串。否则每次网站改版,你的 Skill 都要"重写"。
3. 合规性:采集的底线不能碰
这部分没有灰色地带,必须写进 Skill 的硬约束:
合规清单(硬性检查,不满足即拒绝执行): □ 目标是否有公开 API?有则优先用 API,而非抓网页 □ robots.txt 是否允许?不允许的目标不进任务队列 □ 请求频率是否合理?(模拟真实用户节奏,禁止高频轰炸) □ 是否涉及个人信息?涉及则需要合法依据,否则不采 □ 是否受版权/授权保护?未授权的内容不进采集范围为什么写进 Skill 而不是靠人自觉?因为采集是自动化的——一条代码跑 10 万次,每次都在替你"做决定"。把合规做成执行前的硬检查(不通过直接拒绝运行),而不是写进注释让人记住。
六、和下游清洗 Skill 的衔接线
这是数据流水线协作的关键设计——采集 Skill 的产出就是清洗 Skill 的输入,两者之间的契约必须固定:
采集输出 → 清洗输入的约定: - 格式:统一为表格文件 + 字段说明 - 每条记录带采集时间戳(清洗时可用于去重) - 缺失清单随数据一起传递(清洗可据此决定缺失策略) - 轻量处理只到"可读取",深度清洗全部留给清洗 Skill一条铁律:采集 Skill 不做任何"有损处理"。不去重、不删字段、不合并——宁可把原始数据多给下游,也不能在自己这层丢信息。因为采集层的任何"自作聪明",都会变成下游无法追查的数据损失。
七、一个采集 Skill 骨架
defrun_collection(targets,config):queue=build_task_queue(targets,config)# 1. 目标解析results,missing=[],[]fortaskinqueue:ifnotcheck_rate_limit(config):# 2. 限流wait(config["interval"])resp=request_with_retry(task,config)# 3. 请求+重试ifrespisNone:missing.append(task);continuerecord=extract_fields(resp,config)# 4. 解析(配置驱动)ifis_empty(record)andsuspicious(resp):# 结构变化检测archive_raw_response(resp)# 存档待排查results.append(record)mark_done(task)# 断点持久化integrity=build_integrity_report(len(results),len(missing))save(results,config["output_path"])save_log(integrity)returnconfig["output_path"],integrity骨架里内置了三个采集 Skill 必备件:限流、重试、断点记录——缺任何一个,它都退化成"一次性爬虫脚本"。
八、最容易踩的坑
- 采集和清洗耦合:采集时顺手做深度清洗,下游改不动、源头丢数据。
- 没有断点续采:跑一半挂了,全部重来,长任务永远跑不完。
- 重试策略一刀切:把 404 和超时同等对待,无效重试浪费配额。
- 解析规则写死在代码里:网站一改版,整个 Skill 瘫痪。
- 不核对完整性:采了 80% 就当成功交付,下游全然不知缺了 20%。
- 无视合规:高频抓取、绕过授权——不只是道德问题,是法律风险。
- 不存原始响应:解析出错时没有存档,排查只能靠猜。
- 频率设置过激进:短时间大量请求,被限流封禁,反而拿不到数据。
九、一句话总结
数据采集 Skill 的本质,是把"抓数据"从一次性的手艺活,变成"可中断、可恢复、可续采、合规且自知缺漏"的工程。它的成败不取决于"能不能抓到第一条数据",而取决于"第 10000 条数据抓完时,你是否知道自己抓全了没有、缺了什么、还守住了底线"。
至此,这个系列已经完整覆盖了数据流水线的三环:采集(拿到)→ 清洗(变净)→ 分析/挖掘(用起来)。每篇都在讲同一件事:把隐性经验固化成可复现、可追溯、有验收标准的能力——这正是 Skill 的本质。