Merge pull request 'fix(zhihu): remove noscript tags to prevent duplicate images' (#15) from fix/ci-deploy-reset into main
Deploy kb-skills / deploy (push) Successful in 2s
Deploy kb-skills / deploy (push) Successful in 2s
Reviewed-on: http://192.168.1.22:8418/starmen1265/kb-skills/pulls/15
This commit was merged in pull request #15.
This commit is contained in:
@@ -2,21 +2,29 @@
|
||||
status: awaiting_human_verify
|
||||
trigger: "知乎文章处理时图片链接丢失"
|
||||
created: 2026-03-15T00:00:00Z
|
||||
updated: 2026-03-15T00:03:00Z
|
||||
updated: 2026-03-16T00:00:02Z
|
||||
---
|
||||
|
||||
## Current Focus
|
||||
|
||||
hypothesis: ROOT CAUSE CONFIRMED - 知乎懒加载图片的 src 属性是 SVG 占位符,真实 URL 在 data-actualsrc 属性中
|
||||
test: 已验证 markdownify 只读取 src 属性,得到无效的 SVG 占位符
|
||||
expecting: 修改 markdown_converter.py 处理知乎懒加载图片
|
||||
next_action: 修复 markdown_converter.py,提取真实图片 URL
|
||||
hypothesis: 图片重复是因为知乎 HTML 包含 <noscript> 标签 - 已确认并修复
|
||||
test: 已添加 test_noscript_images_not_duplicated 测试
|
||||
expecting: 用户验证实际知乎链接处理
|
||||
next_action: 等待用户验证
|
||||
|
||||
## Resolution
|
||||
|
||||
root_cause: 知乎使用图片懒加载机制,`<img>` 标签的 `src` 属性包含 SVG 占位符(`data:image/svg+xml;...`),真实图片 URL 存储在 `data-actualsrc` 属性中。`markdownify` 库默认只读取 `src` 属性,导致转换后的 Markdown 包含无效的 SVG 占位符而不是真实图片链接。
|
||||
fix: 修改 `markdown_converter.py`,使用 BeautifulSoup 在转换前预处理 HTML,将 `data-actualsrc` 或 `data-original` 属性的值替换到 `src` 属性中
|
||||
verification: 单元测试全部通过(25/25),包括新的懒加载图片处理测试
|
||||
root_cause: |
|
||||
问题1 (已修复): 知乎使用图片懒加载机制,`<img>` 标签的 `src` 属性包含 SVG 占位符(`data:image/svg+xml;...`),真实图片 URL 存储在 `data-actualsrc` 属性中。
|
||||
|
||||
问题2 (本次修复): 知乎 HTML 结构包含 `<noscript>` 标签作为备用,里面有相同的真实图片 URL。修复懒加载后,外层 img 和 noscript 内的 img 都有真实 URL,导致图片重复出现两次。
|
||||
|
||||
fix: |
|
||||
修改 `markdown_converter.py` 的 `_fix_lazy_load_images` 方法:
|
||||
1. 在处理 img 标签之前,先移除所有 `<noscript>` 标签
|
||||
2. 这样只保留懒加载的主图片,避免重复
|
||||
|
||||
verification: 单元测试全部通过(13/13),包括新的 noscript 重复测试
|
||||
files_changed: [kb-zhihu-metadata/markdown_converter.py, tests/test_zhihu_metadata/test_markdown_converter.py]
|
||||
|
||||
## Symptoms
|
||||
@@ -58,6 +66,11 @@ started: 第一次出现,可能是功能从未正确实现
|
||||
found: 确认转换结果包含 `data:image/svg+xml` 占位符而不是真实图片 URL
|
||||
implication: ROOT CAUSE CONFIRMED - 需要预处理 HTML 提取真实图片 URL
|
||||
|
||||
- timestamp: 2026-03-16T00:00:00Z
|
||||
checked: 知乎 HTML 结构中的 noscript 标签
|
||||
found: 知乎图片 HTML 结构为 `<figure><img data-actualsrc=...><noscript><img src=...></noscript></figure>`,noscript 内包含备用图片
|
||||
implication: ROOT CAUSE CONFIRMED (问题2) - 修复懒加载后,两个 img 都有真实 URL,导致重复
|
||||
|
||||
## Resolution (问题2: 原文丢失)
|
||||
|
||||
root_cause: 知乎回答 (answer) 和专栏 (zhuanlan) 的原文没有被追加到分析报告中。代码只在 `content_type == "article"` 时设置和追加原文,但知乎回答的类型是 `"answer"`
|
||||
|
||||
@@ -38,6 +38,9 @@ class MarkdownConverter:
|
||||
将 data-actualsrc 或 data-original 属性的值替换到 src 属性中,
|
||||
以便 markdownify 能够正确提取真实图片 URL。
|
||||
|
||||
同时移除 <noscript> 标签,因为知乎等平台在 noscript 中包含备用图片,
|
||||
会导致修复后图片重复出现。
|
||||
|
||||
Args:
|
||||
html: 输入的 HTML 字符串
|
||||
|
||||
@@ -46,6 +49,10 @@ class MarkdownConverter:
|
||||
"""
|
||||
soup = BeautifulSoup(html, 'html.parser')
|
||||
|
||||
# 先移除 noscript 标签,避免图片重复
|
||||
for noscript in soup.find_all('noscript'):
|
||||
noscript.decompose()
|
||||
|
||||
for img in soup.find_all('img'):
|
||||
src = img.get('src', '')
|
||||
|
||||
|
||||
@@ -105,6 +105,30 @@ class TestMarkdownConverterImages:
|
||||
assert "https://pic.zhimg.com/fig.jpg" in result
|
||||
assert "Image caption" in result
|
||||
|
||||
def test_noscript_images_not_duplicated(self):
|
||||
"""Test that images inside noscript tags don't cause duplicates
|
||||
|
||||
Zhihu HTML structure includes noscript fallback images:
|
||||
<figure><img data-actualsrc=...><noscript><img src=...></noscript></figure>
|
||||
|
||||
After fixing lazy-load, both imgs would have real URLs, causing duplicates.
|
||||
The fix removes noscript tags before processing.
|
||||
"""
|
||||
html = '''
|
||||
<figure>
|
||||
<img src="data:image/svg+xml;..." data-actualsrc="https://pic.zhimg.com/test.jpg">
|
||||
<noscript>
|
||||
<img src="https://pic.zhimg.com/test.jpg">
|
||||
</noscript>
|
||||
</figure>
|
||||
'''
|
||||
converter = MarkdownConverter()
|
||||
result = converter.convert(html)
|
||||
|
||||
# Should appear exactly once, not twice
|
||||
assert result.count("zhimg.com") == 1
|
||||
assert "https://pic.zhimg.com/test.jpg" in result
|
||||
|
||||
def test_empty_src_with_data_actualsrc(self):
|
||||
"""Test handling of empty src with data-actualsrc"""
|
||||
html = '<img src="" data-actualsrc="https://example.com/fallback.jpg">'
|
||||
|
||||
Reference in New Issue
Block a user