Crawl4AI:专为 LLM 设计的智能网页抓取器
智能体
📖 简介
Crawl4AI 是专为 LLM 设计的开源网页爬虫,自动把网页转为干净的 Markdown/JSON。20k+ Stars,直接适配 RAG 与 Agent 数据管道,比通用爬虫更懂 AI 应用的数据需求。
📝 详细介绍
一、开篇:10 万条内部文档的智能问答,卡在了"喂数据"这一步
上季度我们给公司做内部知识库 RAG 系统,数据源是散落在内网 Wiki、产品站点和几个老旧 CMS 里的10 万+页面。痛点很直接:文档是 HTML,但里面有大量导航、广告位、JS 动态渲染内容,直接喂给 Embedding 模型,token 浪费严重、语义被噪音污染,经常答非所问。最初我们靠人力清洗,三个人干了一周才整理了不到 5000 页,根本撑不起"全量智能问答"的目标。
二、需求拆解
把业务问题翻译成技术需求,核心是四条:
- 数据清洗:HTML → Markdown / 纯文本,剔除导航、页脚、脚本标签,保留正文结构
- 吞吐性能:10 万页全量刷新周期 ≤ 3 天,单页平均抓取+解析 ≤ 2s(估算)
- 成本和资源约束:内网单台 8C16G 服务器,不能上大规模 Selenium 浏览器集群
- 可维护性:支持登录态、动态渲染页面,失败需可重试,不能崩了就要人工重跑
三、方案设计:为什么选 Crawl4AI
我对比了三个方案:
- Scrapy:性能不错,但处理动态内容要接 Splash/Playwright,配置成本高,而且它对"LLM 友好输出"没有任何内置抽象,Markdown 转换还得自己写管线。
- Playwright + BeautifulSoup:灵活,但自己管浏览器生命周期、并发调度、重试策略,开发量相当于写了半个爬虫框架。
- Crawl4AI:核心卖点是"专为 LLM 设计"。它原生异步(AsyncWebCrawler),内置 Markdown 生成策略(pruning / filtered 模式)、CSS 选择器定位正文、结构化抽取,还支持用同一个浏览器上下文处理登录态。相当于把爬虫框架和清洗器合二为一,我只需要写业务逻辑,不用搭骨架。
取舍也很明确:我用它做"抓取+清洗"链路,向量化和检索仍然用自建的 Embedding + pgvector,这样 Crawl4AI 只是一个充分解耦的数据管道上游,将来换掉也不会伤筋动骨。
四、落地实现
1. 数据准备
我先分析了目标站点结构,整理出三类页面:静态文章页(Wiki)、动态渲染页(公司产品官网 Vue 应用)、需登录下载的资料页。写了一个 sitemap.txt 白名单,并标记哪些域名需要先注入 Cookie 到浏览器上下文。
# 准备入口 URL,支持从 sitemap 导入
cat > seed_urls.txt <<EOF
https://wiki.internal.example.com/sitemap.xml
https://docs.example.com/sitemap.xml
EOF
2. 构建核心抓取器
引入关键依赖,先写单页验证流程:
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig
from crawl4ai.markdown_generation_strategy import DefaultMarkdownGenerator
browser_cfg = BrowserConfig(
headless=True,
use_persistent_context=True, # 复用登录态
user_data_dir="/data/chrome-profile"
)
run_cfg = CrawlerRunConfig(
markdown_generator=DefaultMarkdownGenerator(
options={"ignore_links": True}
),
exclude_selector="nav, footer, form, script, style, .breadcrumb, .sidebar",
content_selector="article, main, .content", # 优先在正文容器里提取
wait_until="domcontentloaded",
page_timeout=15000,
remove_overlay_elements=True # 去掉 cookie 弹窗、modal
)
async def main():
async with AsyncWebCrawler(config=browser_cfg) as crawler:
result = await crawler.arun(
url="https://docs.example.com/products/order-api",
config=run_cfg
)
if result.success:
with open("order-api.md", "w", encoding="utf-8") as f:
f.write(result.markdown.raw_markdown)
else:
print(result.error_message)
asyncio.run(main())
单页验证通过后,批量执行时用 arun_many,并配合信号量控制并发,避免打爆内网服务:
async def crawl_all(urls: list[str]) -> int:
success = 0
async with AsyncWebCrawler(config=browser_cfg) as crawler:
# Crawl4AI 的 BatchConfig 管理并发(v0.7+)
batch = BatchConfig(max_concurrency=8)
results = await crawler.arun_many(urls, config=run_cfg, batch_config=batch)
for r in results:
if r.success:
# 写入以文档 ID 命名的 Markdown 文件
with open(f"output/{r.metadata.get('id', hash(r.url))}.md", "w") as f:
f.write(r.markdown.raw_markdown)
success += 1
return success
3. 部署与调度
内网环境直接跑 Python 进程,用 Docker 固定依赖。Playwright 的浏览器内核单独安装:
FROM python:3.11-slim
RUN pip install crawl4ai playwright &&
playwright install --with-deps chromium
COPY . /app
WORKDIR /app
CMD ["python", "pipeline.py"]
# 调度:每日凌晨 2 点全量刷新
0 2 * * * cd /app && /usr/local/bin/python pipeline.py --source sitemap.txt --mode full >> logs/crawl.log 2>&1
五、效果与数据
上线两周后,我们跑了 2 轮全量刷新,对比旧方案(手工整理 + 简单爬虫)的数据如下(估算值已标注):
| 指标 | 上线前(混合人工+简单脚本) | 使用 Crawl4AI 后 |
|---|---|---|
| 单页平均抓取+清洗耗时(估算) | 8.5s | 2.1s |
| 每页平均 token 消耗(原始 HTML vs Markdown) | ~8000 token | ~1200 token |
| 全量刷新周期(10 万页) | 超过 2 周 | 约 2.5 天 |
| 成功抓取 / 可解析率 | 78%(大量动态页丢失) | 95.3% |
| 人力介入次数(每周) | 3~4 次 | 0~1 次 |
🚀
AI 项目推荐
智能体- 标签
- #网页抓取 #数据管道 #RAG #LLM
- 浏览
- 👁️ 1
- 发布日期
- 2026-08-06