番茄线上章节回读
什么时候用
- 在番茄编辑器里手改过某章,要把它同步回本地(本地没有那一版)。
- 怀疑线上和本地不一致,想核对。
- 本地原文丢了,但线上还发着。
硬事实(先读,别重复踩)
- 作者后台没有可读正文的接口。实测 404:
/api/author/chapter/chapter_detail/v1、get_article/v1、edit_article/v1、
article_detail/v0/、chapter_content/v1、preview_content/v1。
别再去撞这些端点。 - 可读的只有公开读者页:
https://fanqienovel.com/reader/<item_id>。
返回的 SSR HTML 里"content":"<p>…</p>…"就是全文,且不需要登录态。 - 约 55% 的汉字被换成私用区码位(U+E000–U+F8FF),靠动态 woff 字体还原,直接抓下来是乱码。
- 码位表在同一本书内稳定:同一章隔几分钟连抓两次,178 个唯一码位有 176 个重合。
——所以只要找到一章「线上字数 == 本地字数」的,逐段等长按位置建表,就能百分百还原,
再把这张表套用到别的章。
取 item_id / 字数
import tomato_publish as tp, json # E:/Workbuddy/tomato_publish.py
cookie, csrf = tp.load_creds()
cli = tp.TomatoClient(cookie, csrf)
B = '<book_id>' # 例:7688317746366385177
vol = tp.list_volumes(cli, B)['volume_list'][0]['volume_id']
ch = tp.list_chapters(cli, B, vol) # 注意:键是 item_list,不是 chapter_list
for c in ch['item_list']:
print(c['index'], c['item_id'], c['title'], c['word_number'])
word_number 等于「正文字符数(不含换行)」,拿它和本地各版本比,就能定位哪一章线上/本地完全一致。
三步走
PY="E:/WorkBuddyConfig/binaries/python/versions/3.13.12/python.exe"
S="E:/WorkBuddyConfig/skills/tomato-chapter-fetch/scripts/tomato_fetch_chapter.py"
# 1) 抓取(先抓「线上字数==本地字数」的那章当基准)
$PY $S fetch --item <基准章item_id> --out raw_base.txt
# 2) 建表(喂本地同文文件,可以多喂几份变体提高覆盖)
$PY $S buildmap --raw raw_base.txt --local 第03章.txt --map pua_map.json
# 3) 抓目标章 + 解码
$PY $S fetch --item <目标章item_id> --out raw_target.txt
$PY $S decode --raw raw_target.txt --map pua_map.json --out clean.txt
建表质量自检(必做)
buildmap会打印来源分布:出现9(逐段等长)越多越可信;只有1(锚点对齐)的码位要人工复核。- 回解校验:用表把基准章解码,应逐字等于本地文件。
python [decode(p, m) for p in raw_base] == local_paras # 必须为 True - 解码后若仍有 PUA 残留,按上下文填空(通常只剩个位数),
然后断言not any(is_pua(c) for c in out)。
常见坑
- 抓 reader 页必须带
User-Agent,否则拿不到 SSR 数据。 - 提取
content要手工扫 JSON 字符串(处理\\转义),别用正则硬切;
再把u003C/u003E/u002F/u0026还原成< > / &。 - 锚点对齐依赖「线上与本地文字高度重合」。若线上那章本地根本没有对应版本,
覆盖率会掉、分歧码位变多——这时优先找别的章做基准章。 - 解码完 不要 直接覆盖本地正式文件:先备份到
_archive/,
再落盘,并另存一份*_番茄线上版.txt留痕。
落盘后
- 跑一遍八项硬指标 + 18 维检测,把「线上版 vs 本地版」的指标差报给用户。
- 线上版常常更短更紧:AI 检测分可能更低(更不像 AI),但句长均值、引号对密度可能越界。
是否要为了达标再改,交给用户决定——改了就不再等于线上版。