数据截至 (上游 commit 7e801521428e)
结构化抽取:schema / 正则 / LLM
本章讲清
aprocess_html的第三步(可选):怎么从页面里抽出结构化数据(不是正文 Markdown,而是{name, price, ...}这种)。结果进result.extracted_content(JSON 字符串)。
1. 这一章解决什么
有时你要的不是「正文」,而是字段:商品名+价格、文章标题+作者+日期、页面里所有邮箱。这就是「结构化抽取」。
Crawl4AI 三条路,都继承 ExtractionStrategy(extraction_strategy.py:86),核心方法 run(url, sections):
| 策略 | 怎么抽 | 要钱? | 何时用 |
|---|---|---|---|
JsonCssExtractionStrategy / XPath / Lxml | 你给 CSS/XPath schema | 免费 | 结构稳定的列表/详情页 |
RegexExtractionStrategy | 内置/自定义正则 | 免费 | 邮箱/电话/URL/日期等通用模式 |
LLMExtractionStrategy | 自然语言指令或 Pydantic schema | 要钱 | 版面多变、语义抽取 |
输入格式很关键:每个策略有 input_format(extraction_strategy.py:91)——schema 类强制用 html(:2012),LLM 默认用 markdown,正则默认 fit_html。aprocess_html 按这个选喂哪份内容(async_webcrawler.py:902-919)。
2. CSS/XPath schema 抽取(免费、最常用)
2.1 直觉
如果一个列表页有 50 个商品卡,每张卡结构一样——那就告诉 Crawl4AI:「每张卡的容器是 .product(baseSelector),卡里 .title 是名字、.price 是价格(fields)」。它就遍历所有卡、按字段抽。纯 CSS/XPath 选择器,不用模型,极快。
2.2 schema 长什么样
示意,非源码:
schema = {
"baseSelector": ".product", # 每个商品卡的容器
"fields": [
{"name": "title", "selector": ".title", "type": "text"},
{"name": "price", "selector": ".price", "type": "text"},
{"name": "link", "selector": "a", "type": "attribute", "attribute": "href"},
],
}
2.3 怎么遍历
抽象基类 JsonElementExtractionStrategy.extract(extraction_strategy.py:1088):
# extraction_strategy.py:1109-1131(精简)
base_elements = self._get_base_elements(parsed_html, self.schema["baseSelector"])
for element in base_elements: # 每个卡片
item = {}
field_data = self._extract_item(element, self.schema["fields"]) # 按字段抽
item.update(field_data)
if item:
results.append(item)
字段类型很丰富(_extract_field,:1148):text / attribute / html / nested(嵌套对象)/ list / nested_list(列表里套对象)。还支持 computed 字段(用表达式或函数从已抽字段算出新值)。
具体解析器有三种实现,差别在底层引擎:JsonCssExtractionStrategy(BeautifulSoup,:1989)、JsonLxmlExtractionStrategy(lxml,更快,:2051)、JsonXPathExtractionStrategy(XPath,:2449)。
2.4 schema 自动生成(省你手写)
手写 schema 烦?generate_schema(extraction_strategy.py:1692)/ agenerate_schema(:1764)用一次 LLM 调用,从一个样例页面自动生成 schema。生成一次后存下来,之后的抽取全是纯 Python、零 LLM 成本——「用一次 LLM 换长期免费抽取」。
3. 正则抽取(通用模式)
RegexExtractionStrategy(extraction_strategy.py:2558)针对通用模式:邮箱、电话、URL、IP、日期、货币、信用卡……内置 21 种(DEFAULT_PATTERNS,:2636-2664),用 IntFlag 位标志让你 bit-OR 组合(:2578-2606):
from crawl4ai import RegexExtractionStrategy as R
# 同时抽邮箱和 URL
strat = R(R.Email | R.Url)
# 结果每 条:{url, label, value, span:[start,end]}
纯 Python、零调用。也能传 custom 自定义模式。同样 generate_schema() 能用 LLM 帮你生成正则(:2572 注释:只有 generate_schema 碰 LLM,抽取本身纯 Python)。
4. LLM 抽取(语义、灵活、要钱)
版面多变、或要「语义级」抽取(比如「把每条评论的情感和要点抽出来」)时用 LLMExtractionStrategy(extraction_strategy.py:533)。两种模式:
- 指令模式:给一句
instruction(自然语言),用PROMPT_EXTRACT_BLOCKS_WITH_INSTRUCTION。 - schema 模式:给 Pydantic schema,让模型按结构填。
4.1 分块 + 并行
长页面要先分块(chunking),避免超 LLM 上下文。run(extraction_strategy.py:786)先 _merge 按 token 阈值合并/切段(带 overlap_rate 重叠,防止边界切断信息),再处理:
# extraction_strategy.py:804-827(精简)
if provider 是 groq:
for section: extract(...); time.sleep(0.5) # 限速,顺序跑
else:
with ThreadPoolExecutor(max_workers=4): # 并行调 4 路
futures = [submit(extract, ix, section) for ...]
有 arun(:972)走异步并发,主线优先用它(async_webcrawler.py:931-937)。这就是把「大页面 → 多块 → 并行喂模型 → 合并」做成了流水线。chunking 策略本身在 chunking_strategy.py(RegexChunking 等)。
5. 怎么选
要抽通用模式(邮箱/电话/URL/日期)?
└─ 是 → RegexExtractionStrategy(零成本)
结构稳定、选择器写得出?
└─ 是 → JsonCss/Lxml/XPath schema(零成本;可用 generate_schema 自动生成)
版面多变 / 要语义理解?
└─ 是 → LLMExtractionStrategy(要钱,分块并行)
6. 巧妙之处
- 「一次 LLM 生成 schema,之后永久免费抽取」(
generate_schema)——把 LLM 用在「学规则」而非「每次抽取」,成本结构很聪明。 - schema 字段支持 nested / list / computed,能抽出嵌套结构,不止平铺字段。
- LLM 抽取的分块带 overlap,避免在 chunk 边界切断一条记录。
7. 边界
- CSS/XPath schema 对结构变化敏感:站点改版选择器就失效。
- 正则只认模式,不懂上下文(抽到的「数字」未必是你要的那个价格)。
- LLM 抽取要钱、有延迟、可能产生格式不稳的输出(靠 schema 模式约束)。
8. 代码地图
| 主题 | 文件路径 | 符号名 |
|---|---|---|
| 抽取基类 | crawl4ai/extraction_strategy.py | ExtractionStrategy、input_format |
| schema 遍历 | crawl4ai/extraction_strategy.py | JsonElementExtractionStrategy.extract、_extract_field |
| CSS / Lxml / XPath | crawl4ai/extraction_strategy.py | JsonCssExtractionStrategy、JsonLxmlExtractionStrategy、JsonXPathExtractionStrategy |
| schema 自动生成 | crawl4ai/extraction_strategy.py | JsonElementExtractionStrategy.generate_schema |
| 正则抽取 | crawl4ai/extraction_strategy.py | RegexExtractionStrategy、DEFAULT_PATTERNS |
| LLM 抽取 | crawl4ai/extraction_strategy.py | LLMExtractionStrategy.run、LLMExtractionStrategy.arun |
| 分块 | crawl4ai/chunking_strategy.py | RegexChunking、IdentityChunking |