提取 JSON(无需大语言模型)
Crawl4AI 最强大的功能之一是从网站提取结构化 JSON,而无需依赖大语言模型。Crawl4AI 提供了多种无需大语言模型的提取策略:
- 通过
JsonCssExtractionStrategy
和JsonXPathExtractionStrategy
进行基于CSS或XPath选择器的模式提取 - 使用
RegexExtractionStrategy
进行正则表达式提取,实现快速模式匹配
这些方法让您能够即时提取数据——即使是从复杂或嵌套的 HTML 结构中——也无需承担大语言模型的成本、延迟或环境影响。
为什么基本提取要避免使用大语言模型?
- 更快更便宜:无需 API 调用或 GPU 开销。
- 更低碳足迹:大语言模型推理可能消耗大量能源。基于模式的提取实际上零碳排放。
- 精确且可重复:CSS/XPath 选择器和正则表达式模式完全按您的指定执行。大语言模型的输出可能多变或产生幻觉。
- 易于扩展:对于数千个页面,基于模式的提取可以快速并行运行。
下面,我们将探讨如何设计这些模式,并将其与 JsonCssExtractionStrategy(如果您更喜欢 XPath,则使用 JsonXPathExtractionStrategy)一起使用。我们还将重点介绍嵌套字段和基础元素属性等高级功能。
1. 基于模式的提取简介
模式定义了:
- 一个基础选择器,用于标识页面上的每个“容器”元素(例如,产品行、博客文章卡片)。
- 字段,描述要为要捕获的每条数据(文本、属性、HTML 块等)使用哪些 CSS/XPath 选择器。
- 用于重复或分层结构的嵌套或列表类型。
例如,如果您有一个产品列表,每个产品可能有一个名称、价格、评论和“相关产品”。对于结构一致的页面,这种方法比使用大语言模型更快、更可靠。
2. 简单示例:加密货币价格
让我们从使用 JsonCssExtractionStrategy
的简单基于模式的提取开始。下面是一个从网站提取加密货币价格的代码片段(类似于传统的 Coinbase 示例)。请注意,我们没有调用任何大语言模型:
import json
import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig, CacheMode
from crawl4ai import JsonCssExtractionStrategy
async def extract_crypto_prices():
# 1. 定义一个简单的提取模式
schema = {
"name": "Crypto Prices",
"baseSelector": "div.crypto-row", # 重复元素
"fields": [
{
"name": "coin_name",
"selector": "h2.coin-name",
"type": "text"
},
{
"name": "price",
"selector": "span.coin-price",
"type": "text"
}
]
}
# 2. 创建提取策略
extraction_strategy = JsonCssExtractionStrategy(schema, verbose=True)
# 3. 设置爬虫配置(如果需要)
config = CrawlerRunConfig(
# 例如,如果页面是动态的,传递 js_code 或 wait_for
# wait_for="css:.crypto-row:nth-child(20)"
cache_mode = CacheMode.BYPASS,
extraction_strategy=extraction_strategy,
)
async with AsyncWebCrawler(verbose=True) as crawler:
# 4. 运行爬取和提取
result = await crawler.arun(
url="https://example.com/crypto-prices",
config=config
)
if not result.success:
print("Crawl failed:", result.error_message)
return
# 5. 解析提取的 JSON
data = json.loads(result.extracted_content)
print(f"Extracted {len(data)} coin entries")
print(json.dumps(data[0], indent=2) if data else "No data found")
asyncio.run(extract_crypto_prices())
亮点:
baseSelector
:告诉我们每个“项目”(加密货币行)在哪里。fields
:使用简单 CSS 选择器的两个字段(coin_name
,price
)。- 每个字段都定义了一个
type
(例如,text
,attribute
,html
,regex
等)。
不需要大语言模型,对于数百或数千个项目,性能近乎即时。
使用 raw://
HTML 的 XPath 示例
下面是一个简短的示例,演示了 XPath 提取以及 raw://
方案。我们将直接传递一个虚拟 HTML(无网络请求),并在 CrawlerRunConfig
中定义提取策略。
import json
import asyncio
from crawl4ai import AsyncWebCrawler, CrawlerRunConfig
from crawl4ai import JsonXPathExtractionStrategy
async def extract_crypto_prices_xpath():
# 1. 包含一些重复行的最小虚拟 HTML
dummy_html = """
<html>
<body>
<div class='crypto-row'>
<h2 class='coin-name'>Bitcoin</h2>
<span class='coin-price'>$28,000</span>
</div>
<div class='crypto-row'>
<h2 class='coin-name'>Ethereum</h2>
<span class='coin-price'>$1,800</span>
</div>
</body>
</html>
"""
# 2. 定义 JSON 模式(XPath 版本)
schema = {
"name": "Crypto Prices via XPath",
"baseSelector": "//div[@class='crypto-row']",
"fields": [
{
"name": "coin_name",
"selector": ".//h2[@class='coin-name']",
"type": "text"
},
{
"name": "price",
"selector": ".//span[@class='coin-price']",
"type": "text"
}
]
}
# 3. 将策略放入 CrawlerRunConfig
config = CrawlerRunConfig(
extraction_strategy=JsonXPathExtractionStrategy(schema, verbose=True)
)
# 4. 使用 raw:// 方案直接传递 dummy_html
raw_url = f"raw://{dummy_html}"
async with AsyncWebCrawler(verbose=True) as crawler:
result = await crawler.arun(
url=raw_url,
config=config
)
if not result.success:
print("Crawl failed:", result.error_message)
return
data极好的,我们继续翻译剩余部分:
```python
data = json.loads(result.extracted_content)
print(f"Extracted {len(data)} coin rows")
if data:
print("First item:", data[0])
asyncio.run(extract_crypto_prices_xpath())
关键点:
- 使用
JsonXPathExtractionStrategy
而不是JsonCssExtractionStrategy
。 baseSelector
和每个字段的"selector"
使用 XPath 而不是 CSS。raw://
让我们传递dummy_html
而无需真正的网络请求——便于本地测试。- 所有内容(包括提取策略)都在
CrawlerRunConfig
中。
这就是如何保持配置自包含、说明 XPath 用法以及演示用于直接 HTML 输入的 raw 方案——同时避免将 extraction_strategy
直接传递给 arun()
的旧方法。
3. 高级模式与嵌套结构
真实网站通常具有嵌套或重复的数据——例如包含产品的类别,而产品本身又具有评论或功能列表。为此,我们可以定义嵌套或列表(甚至是嵌套列表)字段。
示例电子商务 HTML
我们在 GitHub 上有一个示例电子商务 HTML 文件(示例):
https://gist.githubusercontent.com/githubusercontent/2d7b8ba3cd8ab6cf3c8da771ddb36878/raw/1ae2f90c6861极好的,我们继续翻译剩余部分:
```python
# ... (代码块保持不变,仅翻译注释和字符串)
关键要点:
- 嵌套 vs. 列表:
type: "nested"
表示一个单一子对象(如details
)。type: "list"
表示多个简单字典或单文本字段的项目。type: "nested_list"
表示重复的复杂对象(如products
或reviews
)。- 基础字段:我们可以通过
"baseFields"
从容器元素提取属性。例如,"data_cat_id"
可能是data-cat-id="elect123"
。 - 转换:如果我们想要小写/大写、去除空格甚至运行自定义函数,我们也可以定义一个
transform
。
运行提取
import json
import asyncio
from crawl4ai import Async极好的,我们继续翻译剩余部分:
```python
# ... (代码块保持不变,仅翻译注释和字符串)
如果一切顺利,您将获得一个结构化的 JSON 数组,其中每个“类别”包含一个 products
数组。每个产品包括 details
、features
、reviews
等。所有这些都无需大语言模型。
4. RegexExtractionStrategy - 基于模式的快速提取
Crawl4AI 现在提供了一个强大的新零大语言模型提取策略:RegexExtractionStrategy
。该策略使用预编译的正则表达式,以闪电般的速度提取常见数据类型,如电子邮件、电话号码、URL、日期等。
主要特性
- 零大语言模型依赖:无需任何 AI 模型调用即可提取数据
- 极速:使用预编译的正则表达式模式以实现最大性能
- 内置模式:包含开箱即用的常见数据类型模式
- 自定义模式:添加您自己的正则表达式模式以进行特定领域提取
- 大语言模型辅助模式生成:可选择使用大语言模型一次生成优化模式,然后无需进一步的大语言模型调用即可重用
简单示例:提取常见实体
最简单的开始方式是使用内置模式目录:
import json
import asyncio
from crawl4ai import (
AsyncWebCrawler,
CrawlerRunConfig,
RegexExtractionStrategy
)
async def extract_with_regex():
# 使用内置模式创建策略,用于 URL 和货币
strategy = RegexExtractionStrategy(
pattern = RegexExtractionStrategy.Url | RegexExtractionStrategy.Currency
)
config = Crawler极好的,我们继续翻译剩余部分:
```python
# ... (代码块保持不变,仅翻译注释和字符串)
可用的内置模式
RegexExtractionStrategy
提供这些常见模式作为 IntFlag 属性,便于组合:
# 使用单个模式
strategy = RegexExtractionStrategy(pattern=RegexExtractionStrategy.Email)
# 组合多个模式
strategy = RegexExtractionStrategy(
pattern = (
RegexExtractionStrategy.Email |
RegexExtractionStrategy.PhoneUS |
RegexExtractionStrategy.Url
)
)
# 使用所有可用模式
strategy = RegexExtractionStrategy(pattern=RegexExtractionStrategy.All)
可用模式包括:
- Email
- 电子邮件地址
- PhoneIntl
- 国际电话号码
- PhoneUS
- 美国格式电话号码
- Url
- HTTP/HTTPS URL
- IPv4
- IPv4 地址
- IPv6
- IPv6 地址
- Uuid
- UUID
- Currency
- 货币值(美元、欧元等)
- Percentage
- 百分比值
- Number
- 数值
- DateIso
- ISO 格式日期
- DateUS
- 美国格式日期
- Time24h
- 24 小时制时间
- PostalUS
- 美国邮政编码
- PostalUK
- 英国邮政编码
- `极好的,我们继续翻译剩余部分:
自定义模式示例
对于更有针对性的提取,您可以提供自定义模式:
import json
import asyncio
from crawl4ai import (
AsyncWebCrawler,
CrawlerRunConfig,
RegexExtractionStrategy
)
async def extract_prices():
# 为美元价格定义自定义模式
price_pattern = {"usd_price": r"\$\s?\d{1,3}(?:,\d{3})*(?:\.\d{2})?"}
# 使用自定义模式创建策略
strategy = RegexExtractionStrategy(custom=price_pattern)
config = CrawlerRunConfig(extraction_strategy=strategy)
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(
url="https://www.example.com/products",
config=config
)
if result.success:
data = json.loads(result.extracted_content)
for item in data:
print(f"Found price: {item['value']}")
asyncio.run(extract_prices())
大语言模型辅助模式生成
对于复杂或特定站点的模式,您可以使用大语言模型一次生成优化模式,然后保存并重用它,而无需进一步的大语言模型调用:
import json
import asyncio
from pathlib import Path
from crawl4ai import (
AsyncWebCrawler,
CrawlerRunConfig,
RegexExtractionStrategy,
LLMConfig
)
async def extract_with_generated_pattern():
cache_dir = Path("./pattern_cache")
cache_dir.mkdir(exist_ok=True)
pattern_file = cache_dir / "price_pattern.json"
# 1. 生成或加载模式
if pattern_file.exists():
pattern = json.load(pattern_file.open())
print(f"Using cached pattern: {pattern}")
else:
print("Generating pattern via LLM...")
# 配置大语言模型
llm_config = LLMConfig(
provider="openai/gpt-4o-mini",
api_token="env:OPENAI_API_KEY",
)
# 获取用于上下文的示例 HTML
async with AsyncWebCrawler() as crawler:
result = await crawler.arun("https://example.com/products")
html = result.fit_html
# 生成模式(一次性大语言模型使用)
pattern = RegexExtractionStrategy.generate_pattern(
label="price",
html=html,
query="Product prices in USD format",
llm_config=llm_config,
)
# 缓存模式以供将来使用
json.dump(pattern, pattern_file.open("w"), indent=2)
# 2. 使用模式进行提取(无大语言模型调用)
strategy = RegexExtractionStrategy(custom=pattern)
极好的,我们继续翻译剩余部分:
```python
# ... (代码块保持不变,仅翻译注释和字符串)
这种模式允许您: 1. 使用大语言模型一次为您的特定站点生成高度优化的正则表达式 2. 将模式保存到磁盘以供重用 3. 在生产中仅使用正则表达式提取数据(无需进一步的大语言模型调用)
提取结果格式
RegexExtractionStrategy
以一致的格式返回结果:
[
{
"url": "https://example.com",
"label": "email",
"value": "contact极好的,我们继续翻译剩余部分:
```python
# ... (代码块保持不变,仅翻译注释和字符串)
每个匹配项包括:
- url
:源 URL
- label
:匹配的模式名称(例如,“email”, “phone_us”)
- value
:提取的文本
- span
:在源内容中的开始和结束位置
5. 为什么“无需大语言模型”通常更好
- 零幻觉:基于模式的提取不会猜测文本。它要么找到,要么找不到。
- 保证结构:相同的模式或正则表达式在许多页面上产生一致的 JSON,因此您的下游管道可以依赖稳定的键。
- 速度:对于大规模爬取,基于大语言模型的提取可能慢 10–1000 倍。
- 可扩展:添加或更新字段只需调整模式或正则表达式,而不是重新调整模型。
什么时候您可能考虑使用大语言模型? 可能是在网站结构极其混乱或者您需要 AI 摘要时。但对于重复或一致的数据模式,请始终首先尝试模式或正则表达式方法。
6. 基础元素属性和附加字段
使用以下方式可以轻松提取属性(如 href
、src
或 data-xxx
)从您的基础或嵌套元素:
您可以在 baseFields
(从主容器元素提取)或每个字段的子列表中定义它们。如果您需要存储在父 <div>
中的项目链接或 ID,这尤其有用。
7. 综合应用:更大示例
考虑一个博客网站。我们有一个模式,通过 baseFields
和 "attribute": "href"
从每个帖子卡片提取 URL,以及标题、日期、摘要和作者:
schema = {
"name": "Blog Posts",
"baseSelector": "a.blog-post-card",
"baseFields": [
{"name": "post_url", "type": "attribute", "attribute": "href"}
],
"fields": [
{"name": "title", "selector": "h2.post-title", "type": "text", "default": "No Title"},
{"name": "date", "selector": "time.post-date", "type": "text", "default": ""},
{"name": "summary", "selector极好的,我们继续翻译剩余部分:
```python
# ... (代码块保持不变,仅翻译注释和字符串)
然后使用 JsonCssExtractionStrategy(schema)
运行,以获得博客文章对象的数组,每个对象包含 "post_url"
、"title"
、"date"
、"summary"
、"author"
。
8. 提示与最佳实践
- 在 Chrome DevTools 或 Firefox 的 Inspector 中检查 DOM 以找到稳定的选择器。
- 从简单开始:验证您可以提取单个字段。然后添加复杂性,如嵌套对象或列表。
- 测试您的模式,在大型爬取之前,在部分 HTML 或测试页面上进行。
- 如果网站动态加载内容,与 JS 执行结合。您可以在
CrawlerRunConfig
中传递js_code
或wait_for
。 - 当
verbose=True
时查看日志:如果您的选择器有误或模式格式错误,通常会显示警告。 - 如果您需要从容器元素(例如,
href
、data-id
)获取属性,特别是对于“父”项目,请使用 baseFields。 - 性能:对于大型页面,确保您的选择器尽可能窄。
- 考虑首先使用正则表达式:对于简单数据类型如电子邮件、URL 和日期,
RegexExtractionStrategy
通常是最快的方法。
9. 模式生成实用工具
虽然手动制作模式功能强大且精确,但 Crawl4AI 现在提供了一个便捷的实用工具,使用大语言模型自动生成提取模式。这在以下情况下特别有用:
- 您正在处理新的网站结构并希望快速入门
- 您需要提取复杂的嵌套数据结构
- 您希望避免学习 CSS/XPath 选择器语法的曲线
使用模式生成器
模式生成器作为静态方法在 JsonCssExtractionStrategy
和 JsonXPathExtractionStrategy
上都可用。您可以选择使用 OpenAI 的 GPT-4 或开源的 Ollama 进行模式生成:
from crawl4ai import JsonCssExtractionStrategy, JsonXPathExtractionStrategy
from crawl4ai import LLMConfig
# 包含产品信息的示例 HTML
html = """
<div class="product-card">
<h2极好的,我们继续翻译剩余部分:
```python
# ... (代码块保持不变,仅翻译注释和字符串)
大语言模型提供商选项
- OpenAI GPT-4 (
openai/gpt4o
) - 默认提供商
- 需要 API 令牌
- 通常提供更准确的模式
-
通过环境变量设置:
OPENAI_API_KEY
-
Ollama (
ollama/llama3.3
) - 开源替代方案
- 无需 API 令牌
- 自托管选项
- 适用于开发和测试
模式生成的好处
- 一次性成本:虽然模式生成使用大语言模型,但它是一次性成本。生成的模式可以无限次重复用于提取,无需进一步的大语言模型调用。
- 智能模式识别:大语言模型分析 HTML 结构并识别常见模式,通常产生比手动尝试更强大的选择器。
- 自动嵌套:自动检测复杂的嵌套结构并在模式中正确表示。
- 学习工具:生成的模式是学习如何编写自己模式的优秀示例。
最佳实践
- 审查生成模式:虽然生成器很智能,但在生产中使用之前,始终审查和测试生成模式。
- 提供代表性 HTML:您的示例 HTML 越能代表整体结构,生成模式就越准确。
- 考虑 CSS 和 XPath:尝试两种模式类型,并选择最适合您特定情况的模式。
- 缓存生成模式:由于生成使用大语言模型,请保存成功的模式以供重用。
- API 令牌安全:切勿硬编码 API 令牌。使用环境变量或安全配置管理。
- 明智选择提供商:
- 使用 OpenAI 获取生产质量模式
- 使用 Ollama 进行开发、测试或需要自托管解决方案时
10. 结论
借助 Crawl4AI 的无大语言模型提取策略 - JsonCssExtractionStrategy
、JsonXPathExtractionStrategy
,以及现在的 RegexExtractionStrategy
- 您可以构建强大的管道,用于:
- 为结构化数据爬取任何一致的网站。
- 支持嵌套对象、重复列表或基于模式的提取。
- 快速可靠地扩展到数千个页面。
选择正确的策略:
- 使用
RegexExtractionStrategy
快速提取常见数据类型,如电子邮件、电话、URL、日期等。 - 使用
JsonCssExtractionStrategy
或JsonXPathExtractionStrategy
提取具有清晰 HTML 模式的结构化数据 - 如果需要两者:首先使用 JSON 策略提取结构化数据,然后在特定字段上使用正则表达式
记住:对于重复的、结构化的数据,您无需为大语言模型付费或等待。精心设计的模式和正则表达式可以更快、更清晰、更便宜地获取数据——这是 Crawl4AI 的真正力量。
最后更新:2025-05-02
这就是提取 JSON(无需大语言模型)的全部内容!您已经看到基于模式的方法(CSS 或 XPath)和正则表达式模式如何从简单列表到深度嵌套的产品目录处理所有内容——即时且开销最小。享受构建强大的爬虫程序,为您的数据管道生成一致、结构化的 JSON!