diff --git a/kb-zhihu-metadata/markdown_converter.py b/kb-zhihu-metadata/markdown_converter.py
index c0f912d..81faa54 100644
--- a/kb-zhihu-metadata/markdown_converter.py
+++ b/kb-zhihu-metadata/markdown_converter.py
@@ -1,7 +1,14 @@
+import re
+from bs4 import BeautifulSoup
from markdownify import MarkdownConverter as _MarkdownConverter
class MarkdownConverter:
- """HTML 转 Markdown 转换器,保留完整格式"""
+ """HTML 转 Markdown 转换器,保留完整格式
+
+ 处理知乎等平台的图片懒加载机制:
+ - 知乎图片的 src 属性可能是 SVG 占位符 (data:image/svg+xml;...)
+ - 真实图片 URL 存储在 data-actualsrc 或 data-original 属性中
+ """
def __init__(self):
self.converter = _MarkdownConverter(
@@ -13,5 +20,44 @@ class MarkdownConverter:
)
def convert(self, html: str) -> str:
- """转换 HTML 为 Markdown"""
+ """转换 HTML 为 Markdown
+
+ Args:
+ html: 输入的 HTML 字符串
+
+ Returns:
+ 转换后的 Markdown 字符串
+ """
+ # 预处理:处理懒加载图片
+ html = self._fix_lazy_load_images(html)
return self.converter.convert(html)
+
+ def _fix_lazy_load_images(self, html: str) -> str:
+ """修复懒加载图片的 src 属性
+
+ 将 data-actualsrc 或 data-original 属性的值替换到 src 属性中,
+ 以便 markdownify 能够正确提取真实图片 URL。
+
+ Args:
+ html: 输入的 HTML 字符串
+
+ Returns:
+ 处理后的 HTML 字符串
+ """
+ soup = BeautifulSoup(html, 'html.parser')
+
+ for img in soup.find_all('img'):
+ src = img.get('src', '')
+
+ # 如果 src 不是占位符,保持原样
+ if not src or not src.startswith('data:'):
+ continue
+
+ # 尝试获取真实图片 URL
+ # 优先 data-actualsrc,其次 data-original
+ real_src = img.get('data-actualsrc') or img.get('data-original')
+
+ if real_src:
+ img['src'] = real_src
+
+ return str(soup)
diff --git a/tests/test_zhihu_metadata/test_markdown_converter.py b/tests/test_zhihu_metadata/test_markdown_converter.py
new file mode 100644
index 0000000..525d315
--- /dev/null
+++ b/tests/test_zhihu_metadata/test_markdown_converter.py
@@ -0,0 +1,148 @@
+"""Tests for MarkdownConverter in kb_zhihu_metadata
+
+Tests cover:
+- Normal image conversion
+- Zhihu lazy loading image handling (data-actualsrc)
+- Alternative lazy loading (data-original)
+- Mixed content with images
+"""
+
+import pytest
+import sys
+from pathlib import Path
+
+# Add kb_zhihu_metadata to path
+zhihu_metadata_path = Path(__file__).parent.parent.parent / "kb-zhihu-metadata"
+if str(zhihu_metadata_path) not in sys.path:
+ sys.path.insert(0, str(zhihu_metadata_path))
+
+from markdown_converter import MarkdownConverter
+
+
+class TestMarkdownConverterImages:
+ """Tests for image handling in MarkdownConverter"""
+
+ def test_normal_image_conversion(self):
+ """Test that normal images are converted correctly"""
+ html = '
'
+ converter = MarkdownConverter()
+ result = converter.convert(html)
+ assert "" in result
+
+ def test_zhihu_lazy_load_image_with_data_actualsrc(self):
+ """Test that Zhihu lazy loading images use data-actualsrc"""
+ html = '''


'
+ converter = MarkdownConverter()
+ result = converter.convert(html)
+ assert "https://example.com/normal.jpg" in result
+
+ def test_mixed_content_with_images(self):
+ """Test conversion of mixed content with text and images"""
+ html = '''
+
First paragraph.
+
+ Second paragraph.
+
+
+
'
+ converter = MarkdownConverter()
+ result = converter.convert(html)
+ # Empty src is not a data: URI, so it should stay as is
+ assert "https://example.com/fallback.jpg" not in result
+
+
+class TestMarkdownConverterBasicConversion:
+ """Tests for basic HTML to Markdown conversion"""
+
+ def test_paragraphs(self):
+ """Test paragraph conversion"""
+ html = "First
Second
" + converter = MarkdownConverter() + result = converter.convert(html) + assert "First" in result + assert "Second" in result + + def test_headings(self): + """Test heading conversion""" + html = "def hello():\n print('hello')"
+ converter = MarkdownConverter()
+ result = converter.convert(html)
+ assert "```" in result or "def hello():" in result