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 的标准视频页不会被误判成短链。
This commit is contained in:
程序员阿江(Relakkes)
2026-09-18 17:23:20 +08:00
parent 1e1ae64cb4
commit c7e6c9fdc0
4 changed files with 132 additions and 0 deletions
+18
View File
@@ -204,6 +204,24 @@ class KuaishouCrawler(AbstractCrawler):
for video_url in config.KS_SPECIFIED_ID_LIST:
try:
video_info = parse_video_info_from_url(video_url)
# 分享短链(/f/xxx)要先跟随 302 重定向,才能拿到 /short-video/<id>
if video_info.url_type == "short":
utils.logger.info(
f"[KuaishouCrawler.get_specified_videos] Resolving short link: {video_url}"
)
resolved_url = await self.ks_client.resolve_short_url(video_url)
if resolved_url:
video_info = parse_video_info_from_url(resolved_url)
utils.logger.info(
f"[KuaishouCrawler.get_specified_videos] Short link resolved to video ID: {video_info.video_id}"
)
else:
utils.logger.error(
f"[KuaishouCrawler.get_specified_videos] Failed to resolve short link: {video_url}"
)
continue
video_ids.append(video_info.video_id)
utils.logger.info(f"Parsed video ID: {video_info.video_id} from {video_url}")
except ValueError as e: