跳转到内容

LLM 结构化提取(网页转 JSON)

LLM 结构化提取(网页转 JSON)

概述

LLM 结构化提取是将网页的非结构化 HTML 内容转换为结构化 JSON 数据的技术。传统爬虫依赖 XPath/CSS 选择器提取数据,对页面结构变化敏感且难以处理语义信息。LLM 结构化提取通过自然语言 Schema 定义目标数据结构,利用 LLM 的理解能力从 HTML 中提取匹配数据,对页面结构变化具有鲁棒性。

核心流程

1. HTML 清理

直接将原始 HTML 送入 LLM 会导致:

  • Token 浪费:HTML 包含大量与提取无关的标签(<script><style>、导航栏、页脚等)
  • 上下文窗口溢出:大型页面的 HTML 可能超出 LLM 的上下文限制
  • 干扰信息:广告、Cookie 弹窗等噪音影响提取准确性

清理策略:

  • 移除 <script><style><nav><footer> 等非内容元素
  • 提取主内容区域(main content area detection)
  • 保留语义结构(标题层级、列表、表格)

2. Schema 定义

使用 Pydantic / Zod / JSON Schema 定义目标数据结构:

# Pydantic 示例
class Founder(BaseModel):
name: str = Field(description="创始人全名")
role: str = Field(description="职位/角色")
class CompanyInfo(BaseModel):
founders: list[Founder] = Field(description="创始人列表")
pricing_plans: list[str] = Field(description="定价方案")

Schema 中的 description 字段至关重要 —— 它是 LLM 理解每个字段语义的关键提示。

3. Prompt 组装

典型的结构化提取 Prompt 结构:

系统提示:
你是一个数据提取助手。从给定的 HTML 中提取数据,匹配以下 JSON Schema。
如果某个字段不存在,返回 null 而非猜测。
用户提示:
HTML 内容:
{cleaned_html}
JSON Schema:
{schema_definition}

4. LLM 调用与输出验证

关键决策点:

  • JSON 解析失败:LLM 返回的不是合法 JSON,需要重试
  • Schema 校验失败:JSON 合法但不匹配目标 Schema(缺少必填字段、类型不匹配等)
  • 重试策略:通常 2-3 次重试,超过则返回错误

常见陷阱与对策

1. LLM 幻觉(Hallucination)

LLM 可能编造 HTML 中不存在的数据。

对策

  • 在系统提示中明确指令:“如果字段不存在,返回 null,不要猜测”
  • 使用 strict 模式(OpenAI 的 structured outputs 支持)
  • 对提取结果进行后验证(如检查 URL 是否真实存在)

2. Token 成本过高

大型页面的 HTML 可能消耗大量 Token。

对策

  • HTML 清理减少 60-80% 的 Token 用量
  • 先提取精简的 DOM 树(只保留数据相关元素)
  • 使用较小的模型处理简单 Schema

3. Schema 设计不当

过于宽泛的 Schema 导致提取结果不可用;过于严格的 Schema 导致频繁校验失败。

对策

  • 每个字段必须有清晰的 description
  • 使用 Optional / 可空类型处理不一定存在的字段
  • 避免在 Schema 中嵌套过深的结构

4. 多语言页面

页面内容可能混合多种语言,LLM 可能错误翻译或混淆。

对策

  • 在系统提示中指定目标语言
  • 使用 LLM 的原生语言处理能力

设计优势

优势说明
语义理解不只是结构匹配,还能理解内容的语义关系
容错性页面结构变化时,只要语义不变,提取结果仍正确
零模板不需要为每个目标网站编写专用提取规则
自适应同一 Schema 可用于不同网站

替代方案对比

方案优点缺点
XPath/CSS 选择器精确、零成本、可预测页面结构变化即失效,需维护大量规则
正则表达式灵活、轻量脆弱、难以维护、不适合复杂结构
LLM 结构化提取语义理解、容错、零模板成本高、延迟大、可能幻觉
混合方案先用规则提取简单字段,LLM 处理复杂语义复杂度增加,但成本和延迟可控

补充:对话场景下的 LLM 记忆提取

LLM 结构化提取不仅适用于网页→JSON 场景,也广泛应用于对话→记忆的提取。两者的关键差异:

维度网页提取对话提取
输入静态 HTML多轮对话消息(role + content)
目标预定义 Schema 的 JSON开放式的自然语言事实列表
去重不需要(每次独立提取)需要(跨会话去重、语义去重)
角色分离不需要需要区分用户/助手消息的提取来源

对话提取的挑战

  1. “First Topic Dominance” 问题:LLM 倾向于提取第一个主要话题,忽略后续话题。当对话覆盖多个主题时,需要提示词中明确要求”扫描整段对话的每一个话题”。
  2. 回显去重:助手消息经常重复用户已说的内容(“我帮你设置了每日检查,时间是 7:30 AM”),需要从助手消息中跳过已覆盖的信息。
  3. 时间锚定:对话中的相对时间引用(“昨天”、“上周”、“下个月”)必须基于**观察日期(Observation Date)而非当前日期(Current Date)**转换为绝对日期,否则数月后检索时时间信息失效。
  4. 多说话者场景:当对话中的”assistant”角色实际代表另一个人(如 “Maria: 我刚养了一只猫”),需要提取其个人事实,而非跳过所有 assistant 消息。

ADD-Only 提示词设计原则

ADD-Only 策略下的提取提示词(如 ADDITIVE_EXTRACTION_PROMPT)包含以下关键设计:

  • 角色定义:“你是 Memory Extractor——精确、证据绑定的处理器”
  • 提取范围:明确从用户消息和助手消息中分别提取什么
  • 质量约束:15-80 字、自包含、时间锚定、数值精确
  • 完整性约束:禁止泛化具体信息(“Ferrari 488 GTB” ≠ “跑车”)
  • 完整性检查清单:“输出前,逐条扫描对话中的每个话题,确认是否已提取”
  • Few-Shot 示例:覆盖多话题提取、助手推荐、空结果、去重、实体链接等场景

版本标注

本文档基于通用 LLM 提取模式编写,参考了 OpenAI Function Calling 和 JSON Schema 生成等相关技术文档。