228 lines
7.3 KiB
Markdown
228 lines
7.3 KiB
Markdown
# xhs_video_crawler 工作移交文档
|
||
|
||
移交日期:2026-06-08
|
||
|
||
## 项目概述
|
||
|
||
本项目用于探索和验证小红书公开视频内容的采集和下载链路。当前实现采用人工登录浏览器 + 本地脚本附着调试端口的方式运行,不包含自动登录、验证码绕过或私有接口调用。
|
||
|
||
核心入口:
|
||
|
||
- `login_xhs.py`:启动带远程调试端口的 Chrome,并打开小红书页面供人工登录。
|
||
- `XHS.py`:附着到已登录 Chrome,发现笔记链接,解析视频地址,下载视频并写入元数据。
|
||
- `test_xhs.py`、`test_login_xhs.py`:单元测试。
|
||
- `docs/superpowers/`:需求和实现计划文档,记录了浏览器 feed 下载、长任务队列、搜索来源等设计背景。
|
||
|
||
## 当前能力
|
||
|
||
### 单次发现页下载
|
||
|
||
登录后可直接下载当前发现页或指定起始页的视频:
|
||
|
||
```bash
|
||
./.venv/bin/python XHS.py --max-videos 10
|
||
```
|
||
|
||
### 长任务队列下载
|
||
|
||
长任务使用 JSONL 队列文件保存状态,支持中断后继续:
|
||
|
||
```bash
|
||
./.venv/bin/python XHS.py \
|
||
--source video-channel \
|
||
--target-videos 500 \
|
||
--queue-file data/xhs_500_queue.jsonl \
|
||
--metadata-file data/xhs_500_metadata.jsonl \
|
||
--report-file data/xhs_500_report.json \
|
||
--output-dir video/xhs_500 \
|
||
--max-runtime 28800 \
|
||
--timeout 25 \
|
||
--retry-limit 2 \
|
||
--min-wait 2 \
|
||
--max-wait 6 \
|
||
--long-break-every 20
|
||
```
|
||
|
||
队列状态:
|
||
|
||
- `pending`:待处理。
|
||
- `downloaded`:已下载。
|
||
- `skipped_image`:无视频候选,通常是图文笔记或详情页没有暴露视频地址。
|
||
- `failed`:超过重试次数仍失败,例如响应过小、网络错误等。
|
||
|
||
### 搜索来源下载
|
||
|
||
支持关键词搜索来源:
|
||
|
||
```bash
|
||
./.venv/bin/python XHS.py \
|
||
--source search \
|
||
--keyword 猫咪 \
|
||
--target-videos 100 \
|
||
--queue-file data/search_cat_queue.jsonl
|
||
```
|
||
|
||
## 近期重要改动
|
||
|
||
本次移交提交中包含长任务稳定性补强:
|
||
|
||
- 下载改为 `requests.get(..., stream=True)` 分块写入,避免大文件一次性读入内存。
|
||
- 下载时先写入 `.part` 临时文件,校验通过后再替换为正式 `.mp4`;失败时清理 `.part`。
|
||
- 增加 `DEFAULT_MIN_VIDEO_BYTES = 200 * 1024`,默认拒绝过小视频响应,避免把异常响应保存为视频。
|
||
- 队列模式支持 `--min-video-bytes` 和 `--report-file`。
|
||
- 队列任务结束后生成运行报告 JSON,包含下载数量、队列状态、元数据行数、评论统计、目录大小、耗时等。
|
||
- 元数据中增加 `file_size_bytes`。
|
||
- 新增对应单元测试,覆盖流式下载、过小响应拒绝、CLI 参数透传、运行报告统计。
|
||
|
||
## 500 条长任务验证结果
|
||
|
||
2026-06-01 至 2026-06-02 跑过一次真实 500 条长任务验证。
|
||
|
||
命令使用 `video-channel` 来源,目标 `500` 条,输出到:
|
||
|
||
- 视频目录:`video/xhs_500`
|
||
- 队列文件:`data/xhs_500_queue.jsonl`
|
||
- 元数据文件:`data/xhs_500_metadata.jsonl`
|
||
- 运行报告:`data/xhs_500_report.json`
|
||
|
||
验证结果:
|
||
|
||
- 下载成功:500
|
||
- 本地 mp4 文件:500
|
||
- 元数据行数:500
|
||
- `.part` 临时文件残留:0
|
||
- 输出目录大小:约 4.5 GB
|
||
- 总耗时:19052.52 秒,约 5 小时 17 分钟
|
||
- 队列最终状态:
|
||
- `downloaded`: 500
|
||
- `skipped_image`: 147
|
||
- `failed`: 2
|
||
- `pending`: 50
|
||
|
||
两个 `failed` 都是 `视频响应过小`,被最小字节数保护逻辑拦截。`skipped_image` 主要来自视频频道队列里混入无视频候选的笔记。
|
||
|
||
结论:当前链路可以稳定跑 500 条级别长任务。主要瓶颈不是进程稳定性,而是视频频道来源筛选精度和页面内容密度。
|
||
|
||
## 运行环境
|
||
|
||
推荐环境:
|
||
|
||
```bash
|
||
python3 -m venv .venv
|
||
source .venv/bin/activate
|
||
pip install requests DrissionPage
|
||
```
|
||
|
||
启动浏览器:
|
||
|
||
```bash
|
||
./.venv/bin/python login_xhs.py --browser-port 9223
|
||
```
|
||
|
||
注意事项:
|
||
|
||
- Chrome 必须保持运行,脚本通过 `127.0.0.1:9223` 附着。
|
||
- 登录和验证码需要人工处理。
|
||
- 长任务期间不要让电脑睡眠、断网或关闭 Chrome。
|
||
- 如果任务中断,保留 `queue-file` 后重新执行相同命令即可继续。
|
||
|
||
## 数据和产物
|
||
|
||
以下目录在 `.gitignore` 中,正常不应提交:
|
||
|
||
- `.venv/`
|
||
- `.xhs-chrome-profile/`
|
||
- `data/`
|
||
- `video/`
|
||
- `data_queue_smoke/`
|
||
- `data_search_smoke/`
|
||
- `video_queue_smoke/`
|
||
- `video_search_smoke/`
|
||
- `video_human_test/`
|
||
|
||
原因:
|
||
|
||
- `.xhs-chrome-profile/` 可能包含本地浏览器登录态。
|
||
- `data/` 和 `video/` 是运行产物,体积大,且可能包含采集数据。
|
||
|
||
## 测试
|
||
|
||
提交前建议运行:
|
||
|
||
```bash
|
||
python3 -m unittest test_xhs.py test_login_xhs.py -v
|
||
```
|
||
|
||
当前测试覆盖重点:
|
||
|
||
- 可选运行依赖缺失时模块可导入。
|
||
- Chrome 调试端口检测。
|
||
- feed 和 HTML 中视频候选提取。
|
||
- 元数据、评论、输出文件名构造。
|
||
- 队列加载、保存、去重和状态流转。
|
||
- 搜索和视频频道来源构造。
|
||
- 流式下载和异常响应校验。
|
||
- 队列运行报告统计。
|
||
|
||
## 已知问题和风险
|
||
|
||
1. 视频频道来源筛选不够精确
|
||
|
||
队列里会混入图文或详情页无视频候选笔记,500 条验证中有 147 条 `skipped_image`。这不影响稳定性,但会降低有效下载效率。
|
||
|
||
2. 页面依赖小红书前端结构
|
||
|
||
当前依赖页面 DOM、内嵌状态和浏览器 feed 响应。如果小红书前端结构变化,解析器可能需要更新。
|
||
|
||
3. 不适合无人值守处理验证码
|
||
|
||
项目设计前提是人工登录和人工处理验证码,不做自动绕过。
|
||
|
||
4. 单进程串行下载速度有限
|
||
|
||
当前设计偏稳健,默认有人类化等待、详情页打开、评论加载和长停留。500 条真实验证耗时约 5 小时 17 分钟。
|
||
|
||
5. 运行产物没有进入 Git
|
||
|
||
真实验证产物保存在本地 `data/`、`video/`,默认不提交。如需归档,应走对象存储、网盘或其他专门的数据归档流程。
|
||
|
||
## 建议后续优化
|
||
|
||
1. 提高视频卡片筛选精度
|
||
|
||
优先优化 `collect_note_urls_from_page(..., video_only=True)` 的 DOM 判断,降低 `skipped_image` 比例。
|
||
|
||
2. 增加任务心跳
|
||
|
||
可周期性写 `heartbeat` 或增量报告,避免长任务中途只能从队列文件推断状态。
|
||
|
||
3. 增加中断报告
|
||
|
||
当前报告在正常结束时写入。后续可以在 `KeyboardInterrupt` 或异常退出时也写入当前队列摘要。
|
||
|
||
4. 将长任务参数固化成脚本
|
||
|
||
可以新增 `scripts/run_xhs_long_task.sh` 或类似入口,减少手动拼命令出错。
|
||
|
||
5. 降低评论采集开销
|
||
|
||
如果只关注视频下载稳定性,可设置 `--max-comments 0`,能明显提升吞吐。
|
||
|
||
6. 增加数据入库或对象存储
|
||
|
||
目前产物是本地 mp4 + JSONL。若后续要用于生产流程,应考虑上传对象存储并将元数据同步到数据库。
|
||
|
||
## 接手建议
|
||
|
||
接手时建议按以下顺序熟悉:
|
||
|
||
1. 阅读 `README.md`,跑通 1 到 3 条小规模下载。
|
||
2. 阅读 `XHS.py` 中 `run_queue_download`、`download_video`、`extract_video_candidates*`、`collect_note_urls*`。
|
||
3. 运行完整单测。
|
||
4. 用 `--target-videos 20` 跑一次队列模式,查看 queue、metadata、report 三类产物。
|
||
5. 再考虑改动来源筛选或任务报告能力。
|
||
|
||
## 合规边界
|
||
|
||
本项目仅用于技术学习、链路验证和授权范围内的数据处理。使用时应遵守平台服务条款、robots 协议和相关法律法规,不应绕过访问控制、验证码或平台风控,不应采集或传播未授权内容。
|