4.1 KiB
4.1 KiB
通知按 last-id 增量获取与全量翻页
用户确认的语义
“ID 前”指接口列表中排在该条之前的新消息:从最新开始获取,遇到指定 ID 就停止,不包含该条,也不包含同页更旧的数据。不是获取比该 ID 更早的历史,也不按 ID 的数值大小比较。
当前命令
# 不指定边界:自动翻页至接口 has_more=0
python3 src/get_notifications.py
# 获取从最新到该通知之前的消息,排除边界通知
python3 src/get_notifications.py --last-id 7658481661130654757
# 另存文件
python3 src/get_notifications.py --last-id 7658481661130654757 --output /tmp/notifications-new.json
移除 --pages(及原先可缩写的 --page)、--unread、--mark-readed;同时撤下手动 --max-time 起点,确保始终从最新开始。命令仅保留 --last-id 和 --output。关闭 argparse 参数缩写。last-id 要求非空 ASCII 数字字符串,按字符串精确匹配,避免 64 位 ID 精度丢失。
无新的依赖,Python、browser-harness、CDP 与手动登录环境要求不变。空白环境安装见 2026-09-05-23-15-current-user-notifications.md。该文件以及其他早期文档的旧 CLI 参数已被本说明替代。
实现细节
collect_notifications(uid, last_id=None)从 max_time=0 顺序翻页,页间隔 0.5 秒,返回合并记录、raw_pages、是否找到 last-id。- 每页 count=10,响应可能是短页或空页;只依赖 has_more、有效且向历史推进的 max_time 判断是否继续。
- 命中边界立即结束当前页处理,不请求下一页;保留边界前所有已读/未读状态。
- 按通知 ID 去重,保留第一次出现的数据及接口顺序。抖音号、主页链接继续保存。
- last-id 未找到时,采集到接口末页,保存全部并在 stderr 提醒;不会把没找到伪装成命中。
- 用户归属、接口格式、分页状态异常时停止,不自动登录、不重试,也不覆盖上次成功文件。
- 所有采集成功后一次性原子保存。全量会使用与数据规模相应的内存;当前实测几十条不需要落盘流式处理。
- 请求固定 is_mark_read=0;正式抓取脚本不再提供任何标记已读功能。独立实验脚本仍保留,属于历史验证工具而非正式采集流程。
输出
src/notifications.json 默认被本次结果替换;不会自动追加上次运行的数据。
- notifications:实际目标范围内的摘要列表。
- count:去重后的目标通知数量。
- last_id:传入边界,未指定则 null。
- last_id_found:是否命中边界;未指定时为 false。
- stop_reason:last_id 或 exhausted。
- pages_fetched:实际请求页数。
- has_more/max_time:最后一页的服务端分页状态;命中边界时 has_more 仍可能为 1。
- raw_pages:完整原始响应,最后一页可能包含边界及更旧的通知;使用目标列表应读取 notifications,而非 raw_pages。
不再输出 unread_only 和 mark_read_status。这里的“全部”仅指当前互动通知接口 notice_group=960 可提供的所有数据,不包括私信或服务端不再提供的历史记录。
验证记录
2026-09-05 23:59:
python3 src/test_notifications.py通过:覆盖全量翻页、短页/空页、去重、首条/跨页/末条边界、ID 不存在、顺序不等于 ID 数值、无效游标、跨账号数据、请求中断保留旧文件、废弃参数拒绝、用户摘要字段和只读请求。python3 src/test_verify_notification_mark_read.py通过;仅 mock,不执行远端标记。python3 src/get_notifications.py --help验证仅显示 last-id 和 output。- 真实账号全量获取:26 页、72 条,has_more=0、stop_reason=exhausted,已更新
src/notifications.json。 - 真实跨页边界:last-id=7658481661130654757,2 页获取 12 条后停止,last_id_found=true、stop_reason=last_id。结果保存
/tmp/douyin-last-id-check.json;与上述全量结果的前 12 条 ID 精确一致,边界未被包含。
本次未打开通知面板、未标记已读、未执行点赞/关注/评论等写操作。结果含个人互动信息,仅保存在本地。