让 AI 写抓取脚本,跑之前该卡住哪几步:robots、频率与用途的边界
数据截至 2026-07,各产品的额度与报错口径以官方最新说明为准。
你的抓取脚本出事,八成不是代码写错了,而是三个判断从头到尾没人做:这个站点你有没有资格抓、按什么节奏抓才不给对方添麻烦、抓回来的数据打算用在哪里。 大多数人复盘时会归到技术上——库选错了、请求头没配全、并发开太大,然后开始调参数、加重试、换出口。调完当时是通了,过两周同样的问题换个形态又回来,因为真正失守的那一层根本没动过。
先划清范围:本篇只谈两类场景,一是公开可访问且站点明确允许抓取的数据,二是你自己拥有或已获书面授权的站点的自动化。任何绕过访问控制、伪造身份、破解校验、越权读取的做法都不在讨论之列,也不该让 AI 去写——AI 生成这类代码毫无心理负担,责任却全落在按回车的人身上。
站内 AI 工具的数据安全风险 讲的是你把代码和数据交给 AI 之后的泄露面,给自动化任务设计最小权限 讲的是任务本身能碰到哪些资源、怎么收口;本篇夹在这两者中间,只解决一件事:脚本正式跑起来之前和刚跑起来那几天,哪几个判断必须由人落到纸面上,以及出了症状怎么分因。
一、先把场景归类:AI 能替你做到哪一步
抓取这件事在工程上可以拆成六段:确认数据来源与授权、设计请求节奏、写请求与解析代码、做存储与去重、做异常处理与告警、决定数据的下游用途。AI 在其中的表现是极不均匀的。
第三段到第五段,AI 干得很好。给它一段样例 HTML 或一份接口响应,它能写出解析、分页、重试、退避、断点续跑的完整骨架,还能顺手加上超时和结构校验。这部分你要做的只是审代码:超时有没有设、重试次数有没有上限、失败是不是被 except 吞掉了。
第一段、第二段、第六段,AI 基本帮不上忙,而且会给你一种「它已经考虑过了」的错觉。它不知道这个域名归谁、你和对方有没有协议、这份数据将来会不会进你的对外产品。它更不知道你所在行业对个人信息的具体要求。你让它写抓取脚本,它默认你已经有权抓——这是它的合理假设,不是你的免责声明。
一个具体表现:你说「帮我写个脚本抓某某网站的商品列表」,多数模型会直接给出一份可运行的代码,不会先问你 robots.txt 怎么写的、有没有官方开放接口、这些数据你要拿来做什么。不是模型不负责,是这个判断本来就不该由它做。所以工作流应该反过来——人先把边界定死,再让 AI 在边界内写实现。
二、开跑前必须由人定的四件事
1. 这是谁的站,你的身份是什么
分三种,处理方式完全不同。
自有站点或已授权系统:你可以做几乎任何自动化,但仍要给脚本单独的账号和最小权限,不要复用管理员凭证。这类场景反而最容易出内部事故,因为「反正是自己的」。
第三方站点、有官方开放接口:优先走接口。接口有明确的调用契约、限流说明和字段稳定性承诺,页面抓取一样都没有。为省注册流程去抓页面,是拿长期维护成本换一次性的方便。
第三方站点、只有页面:这时候 robots.txt 是你必须看的第一份文件。
curl -s https://example.com/robots.txt
它是站点方对自动化访问表达意愿的公开渠道。里面 Disallow 的路径,含义就是「别抓这里」;Crawl-delay 如果写了,就是对方给出的节奏建议——这一条属于事实标准之外的扩展字段,各家抓取端支持程度不一,但既然对方写了,就按它来。技术上 robots.txt 拦不住任何人,正因为拦不住,遵不遵守才是判断而不是能力问题。除 robots.txt 外,站点的服务条款、页面底部的使用声明同样要读一眼——这两处经常比 robots.txt 更严格。
2. 数据本身能不能碰
把要抓的字段列出来,逐个问一句:这里面有没有可以定位到具体自然人的信息。姓名、手机号、邮箱、身份证件号、精确位置、设备标识、账号昵称加头像的组合,都属于要额外谨慎的那一类。「页面上公开可见」不等于「你可以收集、存储、再加工」——公开展示和批量汇聚是两件事,汇聚之后的风险量级完全不同。
结论很朴素:能不抓的字段就别抓。少一个字段,少一整条合规链路和一份存储风险。
3. 频率怎么定
不要用「多快能跑完」定频率,要用「对方感不感觉得到」定。思路是估算目标站点的正常访问量级,让你的请求量在它面前小到可以忽略:单线程起步,串行为主,请求之间留固定间隔。各站点的限流规则不同且会调整,具体阈值以对方公开说明或实际反馈为准;工程上你能控制的只有并发数、请求间隔、退避策略这三件事。
import time, random
for url in urls:
fetch(url)
time.sleep(1.5 + random.random()) # 固定基线 + 抖动,避免整点齐刷
抖动不是为了隐藏什么,是为了避免多个任务在同一秒撞在一起。
4. 抓来干嘛
这一条最容易被跳过,也最容易在半年后爆炸。同一份数据,自己做一次性分析、内部长期入库、对外产品展示、拿去训练模型,四种用途的边界完全不一样,脚本却长得一模一样。所以用途要在动手前写进任务说明,并落到存储上:给数据打上来源域名、抓取时间、用途标签、保留期限四个字段。半年后有人问「这批数据哪来的、能不能用在新功能里」,你能三分钟内答上来,而不是翻代码猜。
三、跑起来之后:现象判别表
脚本上线头几天必然会遇到各种响应异常。别一上来就加重试、换出口——先分因。
| 现象 | 大概率成因 | 怎么验证 | 处置动作 |
|---|---|---|---|
| 首次请求就 403,浏览器打开正常 | 站点对非交互式访问关闭了该路径 | 先请求站点首页看是不是也 403:只有该路径 403,多半是路径级限制;整站 403 则更像来源或地区维度的拒绝。再查 robots.txt 是否 Disallow 该路径、该页是否本来就需要登录 | 视为不允许抓。改走官方接口或申请授权,不做任何规避 |
| 前几百条正常,之后集中 429 | 请求节奏超过对方限流 | 把并发降到 1、间隔拉长,复跑同一批:能跑通即确认是节奏问题;单线程慢速仍 429,说明触发的是日/时窗口总量或账号维度的限制,降频救不回来 | 降频加指数退避;调整后仍复现就停手 |
| 连接层报 ETIMEDOUT / ECONNRESET | 网络出口问题,或对方主动断连 | 换网络环境单条复跑;看是否只在并发升高时出现 | 限制并发、设超时与重试上限,先区分网络故障和被限速 |
| 401 且本来有登录态 | 会话过期,或凭证只对交互式会话有效 | 重新取一次凭证后单条复跑:通了就是过期,按刷新逻辑处理;仍 401 说明该凭证在非交互式调用里本来就不生效 | 凭证自动化只做在自有或授权系统上,第三方站点不模拟登录 |
| 抓到页面但正文是空的 | 内容由前端渲染,原始 HTML 里没有 | 对比 curl 拿到的 HTML 与浏览器里的 DOM | 先找官方数据接口、导出功能或 RSS;都没有就重新评估这条路值不值得走 |
| TLS 证书链校验失败 | 出口有中间代理,用的是自签证书 | 用 curl -v 请求该域名,看握手日志里打印的证书签发者是不是你公司网关的 CA;再换一个网络环境单条复跑,不报错就基本坐实是中间代理 | 把企业根证书装进信任库,不要用关闭校验的方式绕过 |
| 某天起字段全空、解析全崩 | 对方页面结构或接口返回结构变了 | 存一份当天的原始响应,和历史样本逐字段对比 | 加结构校验和告警,见 接口返回结构变了怎么办 |
这张表的用法是从上往下扫,先定性再动手。403 和 429 是两类完全不同的信号:429 是「你太快了,慢点」,可以调;403 往往是「这里不对外」,那就不是调参数的事。把 403 当成技术障碍去攻,是这类项目走向失控的起点。
另外提醒一句关于重试:任何自动重试都必须配合幂等设计,否则一次网络抖动会让你重复写入几百条脏数据。这块的坑单独讲过,见 重试与幂等怎么一起做。
四、什么情况下别再折腾
工程师的惯性是「再试一个方案」。抓取这件事上,有几个信号出现就该停,继续投入只会把成本和风险一起放大。
止损信号一:你开始研究怎么让请求看起来不像脚本。 这是一条清晰的分界线。跨过去之后,你解决的问题从「工程」变成了「对抗」,而对抗是没有终点的——对方改一次,你改一次,永远在维护一堆随时会碎的东西。更要紧的是,对方已经用行为明确表达了不欢迎。
止损信号二:目标数据里出现了你说不清用途的个人信息。 停下来,把字段清单和用途拿给能拍板的人看。这一步花半小时,比事后清库省事得多。
止损信号三:同一个页面结构一个月里崩了三次以上。 这说明对方在频繁改版,你的解析永远追不上。此时该换路:找官方接口、找数据服务商、或者改用采样加人工核对的方式,不要再堆解析规则。
回滚点怎么留。 第一次上线就把脚本按开关设计:一个环境变量控制启停,一个控制频率倍率。
export CRAWL_ENABLED=false # 一键停跑
export CRAWL_RATE_FACTOR=0.2 # 出问题先降到两成速度
出问题时先把开关关掉再排查,不要一边跑一边改。同时保留「只跑一条」的模式,任何验证都从单条开始,别拿全量跑验证。
换条路的判断依据。 问自己一个问题:如果这个站点明天彻底封掉自动访问,这件事还成不成立?如果答案是「整个功能就废了」,说明你把产品的地基建在别人家的地板上,该考虑的是换数据来源,而不是加固脚本。
五、避坑清单
只看 robots.txt,不看服务条款。 会踩是因为 robots.txt 好查、条款要读一大段。避法是把「robots.txt 截图 + 条款相关段落摘录」一起存进项目文档,作为立项材料的一部分。两者冲突时按严格的那份执行。
把 403 当技术问题攻。 会踩是因为工程师的本能是「一定有办法」。避法是提前立规则:403 直接进人工评估队列,脚本层面不做任何自动化应对,代码里也不留那种「换个方式再试」的分支。
并发从大往小调。 很多人上来就开高并发,出问题再往下降——这时候对方那边的记录已经留下了。避法是反过来:单线程起步,稳跑一天再考虑加,每次只加一档。
重试没有上限。 会踩是因为 AI 生成的重试循环经常只写退避不写次数上限,看代码时容易忽略。避法是审代码只盯三处:最大重试次数、总超时、失败后的落库动作。
日志把原始响应整个打出来。 会踩是因为调试时确实需要看原文,然后就忘了删。这会把对方页面上的个人信息完整复制到你的日志系统里,还常常是权限最松的那个系统。避法是日志只记状态码、耗时、URL 哈希和解析后的字段数;需要留原文就单独落到受控存储并设保留期,参考 日志里的敏感信息怎么处理。
定时任务无人值守跑几个月。 会踩是因为脚本一旦稳定就没人再看,直到对方改版或者法务找上门。避法是给每个抓取任务设复核日期,到期强制人工确认一次:来源还在不在、条款有没有改、数据还用不用。
存储不打来源标签。 会踩是因为建表时觉得多余。避法是建表就带 source_domain、fetched_at、purpose、retain_until 四列,没有这四列的抓取表不许上线。
让 AI 一次性写完全套。 会踩是因为一句话出一个完整脚本的体验太好。避法是拆开:边界你定,解析和存储让它写,异常处理你逐条审。
顺带一句工具选择:部分海外模型服务对中国大陆存在区域限制,官方不支持直连使用,市面上虽有第三方中转,但稳定性与数据流向都不受你控制,涉及数据处理的脚本不建议依赖这类链路。
收尾:上线前的自检清单
抓取脚本的技术难度这些年一直在降,AI 让它降得更快。真正没变的是判断:数据是谁的、你以什么身份取、取回来用在哪。这三件事写清楚了,脚本本身是十分钟的活;写不清楚,后面所有的重试、退避、代理配置都只是在推迟问题。
上线前对着走一遍:
- robots.txt 和服务条款都读过,相关段落已存档;
- 优先级排过:官方接口 > 官方导出 > 页面抓取,前两条确认没有才走第三条;
- 字段清单过了一遍,能不抓的个人信息已经删掉;
- 并发从 1 起步,请求间隔带抖动,重试有次数上限和总超时;
- 停跑开关和降速开关都是环境变量,改一行就能生效;
- 存储表带来源域名、抓取时间、用途、保留期限四个字段;
- 日志里没有原始响应,没有明文个人信息;
- 任务有下次人工复核的日期,写在文档里而不是记在某个人脑子里。
八条都能过,这个脚本可以跑。有一条过不了,先补那一条,别急着上量。