fix(monitor): 抖音「作品」模式的目标被当成博主去查,白废一条本来能用的路
Deploy VitePress site to Pages / build (push) Canceled after 0s
Deploy VitePress site to Pages / Deploy (push) Canceled after 0s

两种模式的**目标是不同的东西**,原来的 fetcher 却一条路走到底:

* 「作品」模式(粘贴作品链接)—— 目标本身就是作品 id,直接取详情即可。**这个接口没被
  那道真校验挡,今天就能用。**
* 「博主」模式 —— 目标是主页 sec_uid,要先拉作品列表;那个接口被挡,退化成刷新已知作品。

原来两种都去调 author_videos(它要的是博主 sec_uid),于是「作品」模式的监控拿作品号当
sec_uid 去查,必然失败 —— 而且失败原因说得很难懂(接口回你「未登录/不是浏览器」)。
结果就是:**新建「作品」模式的抖音监控永远抓不到东西**,而那本来是现有条件下唯一能用的。

现在按 mode 分岔。测试 +2:作品模式必须走 detail 且**不得**去调列表接口(走错了会
直接抛断言);一件作品坏掉不连累其他作品。

顺带记一条排查结论:博主主页的 HTML 里**没有**作品列表(RENDER_DATA 解出来只有
{isLogin, statusCode, isSpider}),所以「走页面 HTML 免接口」那条路也是死的。
This commit is contained in:
2026-10-10 17:30:28 +08:00
parent 95b1be2c2e
commit 9f70cd0924
2 changed files with 97 additions and 17 deletions
+53
View File
@@ -132,6 +132,59 @@ class TestHappyPath:
assert result["notes"] == 1
class TestNoteMode:
@pytest.mark.asyncio
async def test_a_work_target_is_fetched_by_detail_not_by_creator_list(
self, monkeypatch, tmp_path
):
"""作品模式的目标**本身就是作品 id**,不能拿它当博主的 sec_uid 去查列表。
走错了会必然失败,而且失败原因很难看懂(接口说你没登录/不是浏览器)——
「粘贴作品链接的监控」今天本来是能用的,别让它因为这一处走错而废掉。
"""
async def must_not_be_called(*args, **kwargs):
raise AssertionError("作品模式不该去拉博主的作品列表")
async def fake_detail(aweme_id, *, cookie=""):
return _video(aweme_id)
monkeypatch.setattr(douyin_api, "author_videos", must_not_be_called)
monkeypatch.setattr(douyin_api, "video_detail", fake_detail)
result = await _collect(
tmp_path,
mode="note",
want_comments=False,
targets=[_Target("111"), _Target("222")],
)
assert result["notes"] == 2
assert result["errors"] == []
notes = _read(list((tmp_path / "douyin" / "jsonl").glob("*_contents_*.jsonl"))[0])
assert [n["aweme_id"] for n in notes] == ["111", "222"]
@pytest.mark.asyncio
async def test_a_broken_work_does_not_lose_the_others(self, monkeypatch, tmp_path):
async def flaky(aweme_id, *, cookie=""):
if aweme_id == "222":
raise douyin_api.DouyinApiError("作品已被删除")
return _video(aweme_id)
monkeypatch.setattr(douyin_api, "video_detail", flaky)
result = await _collect(
tmp_path,
mode="note",
want_comments=False,
targets=[_Target("111"), _Target("222")],
)
assert result["notes"] == 1
assert any("222" in error for error in result["errors"])
class TestDegradation:
"""作品列表被挡时的行为 —— 决定了这个功能今天有没有用。"""