GitHub周趋势2026W25 | Headroom 压缩 95% Token、NVIDIA 开源 AI Agent 安全扫描器、…
2026-07-28
2026-07-29 0
目标:给出一个网页 URL,最终得到正文 Markdown,其中不再包含侧边栏/广告/导航。
技术选型:
Doubao-Seed-Evolving 通过一次对话生成了代码初版;经过提炼的关键实现和踩坑内容,将在下文展开。
这是我输入提示词后AI给的回答:
以下为核心结构节选:
import requestsfrom bs4 import BeautifulSoupfrom readability import Documentimport markdownify as mdDEFAULT_UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ..."def fetch_url(url, timeout=15, verify_ssl=True):if not url.startswith(("http://", "https://")):url = "https://" + urlheaders = {"User-Agent": DEFAULT_UA}resp = requests.get(url, headers=headers, timeout=timeout, verify=verify_ssl)resp.raise_for_status()return resp.textdef extract_markdown(html, page_url=""):soup = BeautifulSoup(html, "lxml")for tag in soup.find_all(["script", "style", "nav", "aside", "footer"]):tag.decompose()doc = Document(str(soup), url=page_url)content_html = doc.summary()return md(content_html, heading_style="ATX", convert=["table", "pre"])
注意:第一版有个坑——markdownify 不能同传 convert 和 strip,否则运行时直接报错。预清理已处理 script/style,所以删掉 strip 即可。这个修复也是模型在看到报错后给出的。
测试对象涵盖 3 个不同类型的网页,结果在此按实际情况记录:
| 网站类型 | 结果 | 现象 |
|---|---|---|
| SSR 技术博客 | ✅ | 完整保留代码块、语言标注和表格 |
| 公众号 | ⚠️ | 标题显示 [no-title],正文则为 OK |
| 头条(CSR) | ❌ | 正文没有内容,仅出现 # [no-title] |
测试的三个网页中,一个直接成功,一个缺失标题,另一个完全只剩空壳。第一版并没有框架预设中那么糟糕,但实际问题更有意思,因为不同网站分别暴露了不同短板。
og:title 不在 readability-lxml 的 Document.summary() 读取范围内,它只提取 。解析 bug 会被微信文章的标题格式触发,结果便是 [no-title]。
修复:语义化标题提取应作为一层处理,置于 extract_markdown 之前。
def extract_title(soup, doc):og = soup.find("meta", property="og:title")if og and og.get("content"):return og["content"].strip()tw = soup.find("meta", attrs={"name": "twitter:title"})if tw and tw.get("content"):return tw["content"].strip()h1 = soup.find("h1")if h1 and h1.get_text(strip=True):return h1.get_text(strip=True)return doc.short_title()
头条这类站点正文由 JS 异步加载,requests 拿到的只是 修复:通过 --render 参数启用 Playwright 无头浏览器,完成渲染等待后再开始提取。 另:微信/头条图片是懒加载,真实地址在 data-src,需补一段把 data-src 回填到 src,否则全文裂图。 静态站不需要额外依赖,动态站加 --render。from playwright.sync_api import sync_playwrightdef fetch_rendered(url):with sync_playwright() as p:browser = p.chromium.launch(headless=True)page = browser.new_page()page.goto(url, wait_until="networkidle")html = page.content()browser.close()return html六、最终使用方法
python extract_article.py https://juejin.cn/post/xxx -o article.mdpython extract_article.py https://www.toutiao.com/xxx --render -o toutiao.md