Commit Graph

22 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
c7e6c9fdc0 feat(ks): 支持分享短链 /f/<token> 形式的视频输入
快手分享短链 https://www.kuaishou.com/f/X9Idt15MQb9L2cv 路径里是 share_token
而不是视频 ID,它只做 302 跳转,真实地址在 Location 里。原先的解析器只认
/short-video/<id> 和纯 ID,遇到短链会抛 ValueError 被 continue 掉——只有一行
ERROR 日志,看起来像"爬了但没数据"。

- help.py: 新增 /f/<token> 分支,返回 url_type="short"(token 不是视频 ID,
  必须跟随重定向),并补上第三种形式的文档
- client.py: 新增 resolve_short_url,GET 时 follow_redirects=False,读
  301/302/303/307/308 的 Location
- core.py: url_type == "short" 时先解析短链再解析一次,失败则跳过该条
- 新增 tests/test_kuaishou_url_parse.py(6 条,不发网络请求)

验证:两条真实短链分别解析到 3xyziwesje8e9jg / 3xbbkdxtxqm8sae,详情均成功;
带 query 的标准视频页不会被误判成短链。
2026-09-18 17:23:20 +08:00
程序员阿江(Relakkes)
1e1ae64cb4 fix(ks): 视频不可用时 photo 为 null 导致整轮爬取崩溃
快手对已删除/私密/不存在的视频,返回的 visionVideoDetail 里 photo/author 是
null——key 存在、值是 null。而 detail.get("photo", {}) 只在 key 缺失时给默认值,
key 存在且为 null 时拿到的仍是 None,紧接着的 photo.get(...) 抛 AttributeError。
该异常不在 get_video_info_task 的 except 列表里(只 catch DataFetchError /
KeyError),会穿过 asyncio.gather 直接把整轮爬取带崩。

- core.py: 用 (x or {}) 兜住 null;photo 为空时打 WARNING 并跳过该视频,
  不再返回半残的 detail 让下游存空记录、再去下载媒体
- 新增 tests/test_kuaishou_unavailable_video.py(不发网络请求)

验证:photo=null / photo 缺失 / visionVideoDetail 缺失 均返回 None;
真实 cookie 端到端确认不可用视频被跳过、正常视频照常返回详情。
2026-09-18 17:18:01 +08:00
程序员阿江(Relakkes)
cf513e70a1 fix(dy): 补上 detail 接口的 uifid/verifyFp 风控参数
抖音 detail 接口的 Argus 风控要求 uifid / verifyFp / fp 三个参数,缺一则直接
403:响应体为 "Blocked by ArgusSecurityPlugin Uifid Not Found",补上 uifid 但
verifyFp 不对时换成 "... Signature Not Found"。原实现只传 aweme_id,于是
get_aweme_detail 全线失败,详情和媒体都拿不到。

- 三个参数取自浏览器 cookie:uifid 用 UIFID(缺失时退到 UIFID_TEMP),
  verifyFp/fp 用 s_v_web_id。必须用 cookie 里的 s_v_web_id——实测 uifid 搭配
  自生成的 verifyFp 会被判 Signature Not Found,两者需要同源
- 新增 tests/test_douyin_aweme_detail_params.py(不发网络请求)

验证:抓包比对真实浏览器发出的 detail 请求,参数逐项一致;真实爬取中详情与
74MB 视频均下载成功。
2026-09-18 17:00:11 +08:00
程序员阿江(Relakkes)
eec25bb0a0 fix(xhs): 适配上游 EF* 分档,修复视频只下到封面
小红书把 DASH 分档名从按编码命名(h264/h265/av1)改成了按内部档位命名
(EF4/EF5/EF6/EF7),同时 video.consumer 里的 origin_video_key 也没了。
extract_video_urls 写死 stream["h264"],两条路都取不到地址,于是静默返回
空列表:笔记照常入库,但 video_url 为空、媒体只下到封面,全程不报错。

- media.py: 遍历 stream 下所有列表型分档,不再写死分档名;同一分档内含多个
  分辨率(720P→4K),按 (height, avg_bitrate) 降序,最高档作主地址,其余作为
  备用地址交给下载器回退;origin_video_key 分支保留
- 测试 fixture 换成真实响应结构,旧的 h264 结构另存一份确保兼容性不被改坏

验证:真实响应下旧实现取到 0 条、新实现 5 条;真实下载得到 4K 视频
(54079413 字节 / hevc 3840x2160 / 281.87s),旧结构与图文笔记行为不变。
2026-09-18 16:10:18 +08:00
程序员阿江(Relakkes)
c03ab60aac fix(bili): 登录态判定改为校验 cookie 有效性,避免静默降级到 480P
check_login_state 原先只判断 SESSDATA 是否存在。过期会话的 SESSDATA 会一直
留在浏览器里,于是 pong 报"账号未登录"后进入的登录流程会被立刻判成成功:
既不等待扫码,又把这份死 cookie 灌给 API client。

后果是隐蔽的:详情和评论两个接口不要求登录,照常爬到;而 playurl 依据
Cookie 决定清晰度,未登录状态会静默封顶在 480P,不报任何错。

- login.py: 抽出 is_login_cookie_refreshed(),要求 SESSDATA 被扫码换发成新值
  才算登录成功;进入登录流程前记录旧值,残留死 cookie 时输出告警
- core.py: 登录流程结束后补一次 pong 校验,仍失败则明确报错退出,
  不再带着未登录状态跑完全程
- 新增 tests/test_bilibili_login_state.py 覆盖上述分支
2026-09-18 15:48:06 +08:00
程序员阿江(Relakkes)
0ca7b29cf0 feat(media): 重构媒体下载,支持 xhs/dy/ks/bili/wb 五平台
旧实现只覆盖 4 个平台,且把整个文件读进内存、无重试与完整性校验,
代码按平台复制粘贴了 4 份。本次用统一下载器替换:

- 新增 media_downloader/:流式写入、Range 续传、指数退避重试、大小校验、
  路径穿越防护;B 站 DASH 音视频分轨下载后交由 ffmpeg 无损合流
- 新增 media_platform/<平台>/media.py:从平台原始响应提取媒体地址,
  与下载器解耦;快手首次接入下载能力
- 开关:config.ENABLE_GET_MEDIA 与 --get_media,并打通 API/WebUI;
  同时修正旧配置项 ENABLE_GET_MEIDAS 的拼写
- 落盘按帖子聚合:{SAVE_DATA_PATH 或 data}/{platform}/media/{内容ID}/
- B 站装好 ffmpeg 时走 DASH 最高画质,否则降级 mp4 直链(产物 video-durl.mp4,
  避免低清文件阻塞后续的高清路径)
- 删除 4 个 *_store_media.py、AbstractStoreImage/Video 及各 client 的媒体 GET 方法

媒体下载失败只记录日志,不中断爬取主流程。
2026-09-17 22:54:22 +08:00
程序员阿江(Relakkes)
d594c20c13 fix(xhs,bilibili): 修复访问受限异常击穿与评论采集边界问题
xhs: PR #958 把 IPBlockError / PlatformAccessError 加入 request() 的
retry_if_not_exception_type 后,tenacity 会直接重抛原异常而不再包装成
RetryError,core 层的 except 分支接不住,单条笔记被限流会让整批
asyncio.gather 抛出,同批已抓取但未入库的数据全部丢失。

- get_note_detail_async_task / get_creators_and_notes 捕获访问受限异常,
  记录明确日志后跳过当前条目,恢复原有的"跳过并继续"语义
- 移除 request() 中已不可达的 IP_ERROR_CODE 分支

bilibili: 修复 get_video_all_comments 的两处翻页边界问题

- is_first_page 改为独立标志,接口返回 next=0 且 is_end=False 时
  不再把后续页误判为首页而重复注入置顶评论
- result 无条件累加,否则开启楼中楼抓取时循环守卫永不推进,
  max_count 完全失效并可能死循环;截断提前到抓取楼中楼之前,
  避免为已被丢弃的评论抓子评论
2026-08-11 18:10:16 +08:00
程序员阿江-Relakkes
3c25521bbb Merge pull request #958 from ottercoconut/agent/fix-xhs-raw-response-errors
fix(xhs): 在返回原始 HTML 前识别访问限制
2026-08-11 18:00:22 +08:00
ottercoconut
508abc504f 补全小红书响应与重试回归测试 2026-08-11 17:52:54 +08:00
ottercoconut
6937b12738 修复小红书原始响应错误分类与重复重试 2026-08-11 16:45:49 +08:00
muzimu
17c6d386b8 fix(bilibili): 修复缺失置顶评论 2026-08-08 18:01:26 +08:00
程序员阿江(Relakkes)
a06273ea6c fix: 将平台业务ID统一改为String并自动建表
- 抖音、B站、快手、微博的帖子/视频/评论ID从BigInteger改为String,
  避免PostgreSQL下字符串写入BIGINT报错及未来ID溢出风险
- B站dynamic_id改为String,修复API返回id_str被强转int导致的精度丢失
- 知乎提取器对content_id/question_id显式str()转换
- main.py启动数据库保存模式时自动建表,无需手动--init_db
- 同步更新相关老化测试
2026-07-01 23:03:43 +08:00
程序员阿江(Relakkes)
9f4f8bf768 refactor: 教学版移除全平台用户个人信息采集与持久化
- 用户 ID 转为匿名 creator_hash,昵称中间脱敏,IP/头像/主页/签名/性别不再采集
- 覆盖 xhs/weibo/bilibili/douyin/kuaishou/tieba/zhihu 7 个平台
- 删除 7 张 creator 档案 ORM 表,15 张内容/评论表新增 creator_hash 列
- B 站禁用粉丝/关注/联系人列表抓取
- 新增 tools/user_hash.py 与 4 个平台的 mock+SQLite 端到端测试

测试: pytest tests/test_no_user_info.py tests/test_weibo_no_user_info.py tests/test_douyin_no_user_info.py tests/test_kuaishou_no_user_info.py (21 passed)
2026-07-01 13:09:55 +08:00
程序员阿江(Relakkes)
c9a111be73 fix: 修复已有浏览器 CDP 连接 2026-06-18 17:22:38 +08:00
程序员阿江(Relakkes)
8e93438fe5 Keep PR 900 overrides bounded and opt-in
The PR adds API limit overrides and static proxy support, but the review found that the default proxy provider changed to an invalid static placeholder and the new API fields accepted unbounded values. This keeps the existing proxy default intact, makes static proxy explicit via config or CLI, validates API limit ranges, and adds focused regression coverage for both paths.

Constraint: PR branch must remain contributor-branch compatible and avoid adding dependencies

Rejected: Keep static as the default provider | breaks existing --enable_ip_proxy defaults with an invalid placeholder URL

Rejected: Accept arbitrary integer limits | lets API callers request negative or excessive crawl sizes

Confidence: high

Scope-risk: narrow

Directive: Do not change proxy provider defaults when adding new providers; new providers should be opt-in and covered by provider-specific tests

Tested: uv run pytest tests/test_api_limits.py tests/test_static_proxy_provider.py

Tested: uv run pytest tests

Tested: uv run pytest test/test_utils.py

Tested: uv run python -m compileall api cmd_arg config proxy tests

Tested: git diff --cached --check

Not-tested: Live crawler run against external platforms or real proxy vendor endpoints
2026-05-29 21:27:52 +08:00
钟保罗
ec432eb63e feat: 启动任务接口添加帖子/视频数量与评论数量覆盖支持 2026-05-19 20:57:07 +08:00
程序员阿江(Relakkes)
f328ee35b5 fix: restore Tieba crawling after PC page rewrite
Tieba search, detail, comments, creator, and forum-list pages now rely on the current signed PC JSON APIs instead of brittle HTML selectors. The CLI also maps Tieba detail and creator arguments into the platform-specific config so command-line runs exercise the intended mode.

Constraint: Tieba PC pages no longer expose stable HTML structures for search, creator, and forum-list extraction
Constraint: Current PC APIs require browser cookies, tbs, and the web client signing convention
Rejected: Keep expanding HTML selectors | search and creator pages returned large documents with empty parsed results after the redesign
Confidence: high
Scope-risk: moderate
Directive: Do not replace these API paths with page HTML parsing without re-verifying the current Tieba network requests
Tested: uv run pytest tests/test_tieba_client_pagination.py tests/test_cmd_arg_tieba.py tests/test_tieba_extractor.py -q
Tested: uv run python -m py_compile cmd_arg/arg.py media_platform/tieba/help.py media_platform/tieba/client.py media_platform/tieba/core.py tests/test_cmd_arg_tieba.py tests/test_tieba_client_pagination.py tests/test_tieba_extractor.py
Tested: uv run main.py --platform tieba --type search --keywords 编程兼职 --get_comment false
Tested: uv run main.py --platform tieba --type detail --specified_id 9835114923 --get_comment true --max_comments_count_singlenotes 3
Tested: uv run main.py --platform tieba --type creator --creator_id https://tieba.baidu.com/home/main?id=tb.1.6ad0cd4a.7ZcjVYWa7UpHttCld2OppA --get_comment false
Not-tested: Second-level Tieba comment API migration; this path still uses the existing /p/comment HTML parser
Not-tested: Full pytest suite has one pre-existing unrelated XHS Excel store assertion failure
2026-04-30 18:20:46 +08:00
程序员阿江(Relakkes)
0282e626c9 feat: 新增 JSONL 存储格式支持,默认存储格式改为 jsonl
JSONL(JSON Lines)每行一个 JSON 对象,采用 append 模式写入,
无需读取已有数据,大数据量下性能远优于 JSON 格式。

- 新增 AsyncFileWriter.write_to_jsonl() 核心方法
- 7 个平台新增 JsonlStoreImplement 类并注册到工厂
- 配置默认值从 json 改为 jsonl,CLI/API 枚举同步更新
- db_session.py 守卫条件加入 jsonl,避免误触 ValueError
- 词云生成支持读取 JSONL 文件,优先 jsonl 回退 json
- 原有 json 选项完全保留,向后兼容
- 更新相关文档和测试
2026-03-03 23:31:07 +08:00
程序员阿江(Relakkes)
157ddfb21b i18n: translate all Chinese comments, docstrings, and logger messages to English
Comprehensive translation of Chinese text to English across the entire codebase:

- api/: FastAPI server documentation and logger messages
- cache/: Cache abstraction layer comments and docstrings
- database/: Database models and MongoDB store documentation
- media_platform/: All platform crawlers (Bilibili, Douyin, Kuaishou, Tieba, Weibo, Xiaohongshu, Zhihu)
- model/: Data model documentation
- proxy/: Proxy pool and provider documentation
- store/: Data storage layer comments
- tools/: Utility functions and browser automation
- test/: Test file documentation

Preserved: Chinese disclaimer header (lines 10-18) for legal compliance

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 23:27:19 +08:00
程序员阿江(Relakkes)
6e858c1a00 feat: excel store with other platform 2025-11-28 15:12:36 +08:00
hsparks.codes
324f09cf9f fix: Update tests to handle openpyxl color format and ContextVar
- Fix header color assertion to check only RGB values (not alpha channel)
- Remove ContextVar mock as it cannot be patched in Python 3.11+
- All 17 tests now passing successfully
2025-11-28 05:04:00 +01:00
hsparks.codes
46ef86ddef feat: Add Excel export functionality and unit tests
Features:
- Excel export with formatted multi-sheet workbooks (Contents, Comments, Creators)
- Professional styling: blue headers, auto-width columns, borders, text wrapping
- Smart export: empty sheets automatically removed
- Support for all platforms (xhs, dy, ks, bili, wb, tieba, zhihu)

Testing:
- Added pytest framework with asyncio support
- Unit tests for Excel store functionality
- Unit tests for store factory pattern
- Shared fixtures for test data
- Test coverage for edge cases

Documentation:
- Comprehensive Excel export guide (docs/excel_export_guide.md)
- Updated README.md and README_en.md with Excel examples
- Updated config comments to include excel option

Dependencies:
- Added openpyxl>=3.1.2 for Excel support
- Added pytest>=7.4.0 and pytest-asyncio>=0.21.0 for testing

This contribution adds immediate value for users who need data analysis
capabilities and establishes a testing foundation for future development.
2025-11-28 04:44:12 +01:00