用户发来 https://mp.weixin.qq.com/s/ZEOsi4R4JcmZ_mhS6qpcww,存进库的正文只有 67 个字符 ("原文链接 + 一个句号")。复盘发现公众号换了渲染方式:新版页面把整篇塞进 window.cgiDataNew 这个 JS 对象由前端渲染,页面里根本没有 id="js_content"; 三种 UA 拿到的字节数完全一样,也不是 UA 的问题。 - 从 JS 字符串字面量里读正文(content_noencode / desc),按 \xNN、\uNNNN 反转义, 话题标签是双重转义过的 HTML,先 unescape 再走 DOM。 - 配图字段排在文字之后,所以前后各找 2500 字符合图;剩下没用过的 mmbiz 图按 12 张上限补在末尾(图文型文章靠就近配对会漏)。 - 解析顺序:旧 DOM → 新版 JS 数据 → 通用抽取,一层层退。 实测两篇:2373 字符 + 12 张图、2772 字符 + 13 张图,作者也都取到了。 同时补上用户提的两件: - 知识能删了:DELETE /knowledge/{id}?confirm=true,软删 + 真删检索切片, 只有作者或 owner/admin 能删;列表卡片(悬停出现)和阅读页动作行各一个入口。 删完详情也回 7001,否则收藏的链接还能打开一篇已删除的知识。 - 分类下面有标签清单了:GET /knowledge/tags 按标签数"有多少条知识用了它", 侧栏渲染成 #标签 + 条数,点一下筛选、再点取消。
This commit is contained in:
+26
-2
@@ -513,7 +513,30 @@ Web 端未读数由 `AppShell` 每 30 秒轮询一次;在通知页标已读后
|
||||
|
||||
### 5.2 `GET /knowledge/{item_id}`
|
||||
|
||||
详情,附最近 50 条 `activities`。不存在或跨租户统一 `7001`。
|
||||
详情,附最近 50 条 `activities`。不存在、跨租户、**已经删掉**的统一 `7001`
|
||||
(删除是软删,但对读的人来说就是"没了",否则收藏的链接还会打开一篇已删除的知识)。
|
||||
|
||||
### 5.2.1 `GET /knowledge/tags` — 侧栏那串标签
|
||||
|
||||
```
|
||||
GET /knowledge/tags?status=published&status=in_review
|
||||
```
|
||||
|
||||
```json
|
||||
{"items": [{"name": "发布", "count": 12}, {"name": "回滚", "count": 3}]}
|
||||
```
|
||||
|
||||
- `count` 是**有多少条知识用了它**(`count(distinct item_id)`),不是引用次数。
|
||||
- 只统计未删除的知识;带了 `status` 就只数这些状态,和列表的 tab 对得上。
|
||||
- 按条数从多到少排,同数按名字。标签是分类之外的第二根轴:分类回答"属于哪一块",标签回答"跟什么有关"。
|
||||
|
||||
### 5.2.2 `DELETE /knowledge/{item_id}?confirm=true` — 删除
|
||||
|
||||
- 必须显式带 `confirm=true`,否则 `1002`「删除不能撤销,带 confirm=true 再来一次」(防手滑)。
|
||||
- 只有**作者本人**或 `owner`/`admin` 能删,否则 `3004`。
|
||||
- 软删:`item.deleted_at` 落时间戳,列表、详情、检索、标签统计里都不再出现;
|
||||
**检索切片真删**(`chunk` 表),否则"删掉的知识还能被搜出来"比删不掉更吓人。
|
||||
- 重复删不回错误,回 `message: "已经删过了"`,让重试的客户端不必区分。
|
||||
|
||||
### 5.3 `POST /knowledge` — 手记或指定来源
|
||||
|
||||
@@ -758,7 +781,8 @@ Query:
|
||||
|---|---|
|
||||
| 判断 | `extract_url()`:去掉首尾标点后只剩一个链接;带了别的话("看下 https://… 这个")仍按任务处理 |
|
||||
| 抓取 | `httpx` 取页面(25 秒超时、8 MB 上限),`trafilatura` 抽正文;标题取 `og:title`/`<h1>`/`<title>` |
|
||||
| 公众号 | `mp.weixin.qq.com` 单独走 DOM:标题 `#activity-name`、作者 `#js_name`、正文 `#js_content`,图片取 `data-src`(通用抽取器会把公众号的图丢光) |
|
||||
| 公众号(旧页) | `mp.weixin.qq.com` 且页面有 `#js_content`:标题 `#activity-name`、作者 `#js_name`、正文 `#js_content`,图片取 `data-src`(通用抽取器会把公众号的图丢光) |
|
||||
| 公众号(新版页) | 没有 `#js_content` 时(`appmsg_type = '9'` / `'10002'`)整篇在 `window.cgiDataNew` 里:从 `content_noencode` / `desc` 的 JS 字符串字面量读正文,按 `\xNN`、`\uNNNN` 反转义,话题标签先 `html.unescape` 再走 DOM;配图字段(`cdn_url`/`img_url`/`pic_url`)排在文字之后,前后各找 2500 字符合图;作者兜底取 `nick_name` |
|
||||
| 清洗 | 导航/页脚按行边界裁掉(`_trim_chrome`);`trafilatura` 结果太短(<120 字)就退到容器打分兜底 |
|
||||
| 配图 | 正文里的外链图下载进我们自己的存储,最多 12 张、单张 8 MB,正文改写成 `/attachments/{id}/raw?签名`——公众号一换图,外链就是一排红叉 |
|
||||
| 落库 | 知识草稿(`status="draft"`,`doc_type="note"`),正文首行是 `> 原文:<url>` |
|
||||
|
||||
Reference in New Issue
Block a user