用 CDP 抓 HAR 把网页流程变成脚本:一次接口逆向的完整记录
为什么要抓包
页面点得再多,也只是在自己机器上重复劳动。真正能复用的是协议:请求怎么发、参数怎么带、状态怎么判。抓一次 HAR,把它固化成客户端,之后跑一次脚本就是一次点击。
一、用 CDP 抓,而不是用浏览器插件
Chrome DevTools Protocol 的好处是不依赖扩展、能在服务器上跑。核心三步:
- WebSocket 连上
ws://127.0.0.1:9222/devtools/page/<id> - 发
Network.enable,然后监听Network.requestWillBeSent和Network.responseReceived - 对每个完成的请求发
Network.getResponseBody,把响应体补回条目
最后按 HAR 1.2 的结构落盘,浏览器的 Network 面板能直接打开,团队的其他人也能用同一份数据复盘。
二、三个实际踩到的坑
坑一:事件会静默丢失。 处理消息的逻辑只要抛一次异常,后面的 requestWillBeSent 全部漏掉,最后拿到 0 条记录。用 try/except 包住单条处理,别让一条脏数据带走整个采集器。
坑二:响应体不会自动回来。 Network.getResponseBody 是带 id 的调用,返回值和你主动发的请求混在同一个 WebSocket 里。必须维护 id 到 requestId 的映射,否则 93 条请求全都没有 body,等于白抓。
坑三:base64。 二进制响应会带 base64Encoded: true,不解码就是一串乱码进 HAR,之后按 JSON 解析必然失败。
三、从 HAR 到协议
抓完先做减法:把 js/css/图片/map 全过滤掉,剩下的才是接口。然后按 host + path 分组,你会看到接口其实就分两类:
- 公共接口:任务列表、活动信息,路径里有
servlet - 用户接口:积分、签到,路径里多一层
/user/
这两类的域名相同、前缀不同,写错就是一个 404,而且错误码还长得像内部错误,很容易误判成"接口挂了"。
再看请求头。用户级接口往往要求 CSRF。这类 token 有两种形态:一种是 cookie 直接当请求头用;另一种是前端 JS 在运行时注入,cookie 里根本找不到。后者只能从实时请求里收割,抓一次请求头存下来,过期了再抓。
参数命名也要看原始报文。同样的字段,驼峰和下划线在服务端可能是两套解析,传错了不报"字段名错误",而是报"必填项为空",白白多排查半小时。
四、cookie 要按域名精确取
一次性导出所有 cookie 看着省事,实际会踩重名覆盖:同名 cookie 在不同子域各有一份,字典一合并就剩最后一个,登录态随机失效。
正确做法是给 Network.getCookies 传目标 URL,让浏览器按它自己的规则算出发给这个域的那一份,再去重、落盘、权限设成 600。
五、先读后写,保持幂等
写完读接口再动写接口。签到这类操作天然幂等,重复调用只会返回"今天已经签过",正好拿来验证整条链路是否打通。真正危险的是那些没有幂等保护的提交,跑之前先看有没有"已完成"状态可以查。
结语
抓包的价值不在那一份 HAR,而在把"人点页面"变成"程序发请求"这一步。一次逆向,后面每天都是零成本。
- 点赞
- 收藏
- 关注作者
评论(0)