crawl4ai
专为 LLM 应用设计的开源网络爬虫,将网页内容直接转化为干净的 Markdown、结构化数据,方便接入 RAG、agent 或数据管道。亮点在于内置反爬虫机制(3 级检测+代理自动切换)、Shadow DOM 展开、深爬断点续传等特性,Docker 一键部署且支持 LLM 驱动的内容提取,社区活跃,50k+ stars 验证了其可靠性。
README
🚀🤖 Crawl4AI: 面向 LLM 的开源友好 Web 爬虫与抓取工具
🚀 Crawl4AI Cloud API — 封闭测试(即将推出)
可靠的大规模 Web 数据提取,旨在比现有方案 大幅降低成本。
👉 请此处申请早期访问
我们将分阶段接入,并与早期用户紧密合作。名额有限。
Crawl4AI 将 Web 转化为干净、LLM 就绪的 Markdown,适用于 RAG(检索增强生成)、agent(智能体)和数据管道。快速、可控,经 50k+ 星社区实战检验。
✨ v0.8.6 新功能:安全热修复 —— 由于 PyPI 供应链被入侵,将 litellm 替换为 unclecode-litellm。如果您正在使用 v0.8.5,请立即升级。
✨ 近期 v0.8.5:反机器人检测、Shadow DOM 及 60+ 错误修复!自动三层反机器人检测及代理升级、Shadow DOM 扁平化、深度爬取取消、配置默认 API、同意弹窗移除以及关键安全补丁。发布说明 →
✨ 上一版本 v0.8.0:崩溃恢复与预取模式!深度爬取崩溃恢复,支持 resume_state 和 on_state_change 回调用于长时间运行的爬取。新增 prefetch=True 模式,URL 发现速度提升 5-10 倍。发布说明 →
✨ 上一版本 v0.7.8:稳定性与错误修复版!11 项错误修复,涉及 Docker API 问题、LLM 提取改进、URL 处理修复和依赖更新。发布说明 →
🤓 我的个人故事我从小用 Amstrad 电脑长大,感谢我的父亲,从此一直在构建东西。研究生期间我专攻 NLP(自然语言处理),并为研究编写爬虫。那时我深刻理解了数据提取的重要性。
2023 年,我需要将 Web 内容转为 Markdown。所谓的“开源”选项要求注册、API token 和 16 美元,结果还达不到预期。我愤怒至极,几天内构建了 Crawl4AI,然后它火了。现在它是 GitHub 上星标最多的爬虫。
我将其开源是为了 可用性,任何人都可以无障碍使用。现在我在构建平台以实现 可负担性,让每个人都能以低廉成本运行严肃的爬取。如果你对此有共鸣,欢迎加入、反馈,或者爬取一些精彩的内容。
为什么开发者选择 Crawl4AI- LLM 就绪输出,智能 Markdown,包含标题、表格、代码、引用提示
- 实际运行快速,异步浏览器池、缓存、最小跳转
- 完全可控,会话、代理、cookie、用户脚本、钩子
- 自适应智能,学习网站模式,只探索有价值的内容
- 随处部署,零密钥、CLI 和 Docker,云友好
🚀 快速入门
- 安装 Crawl4AI:
# 安装包
pip install -U crawl4ai
# 预发布版本
pip install crawl4ai --pre
# 运行安装后设置
crawl4ai-setup
# 验证安装
crawl4ai-doctor
如果遇到浏览器相关问题,可以手动安装:
python -m playwright install --with-deps chromium
- 用 Python 运行简单爬虫:
import asyncio
from crawl4ai import *
async def main():
async with AsyncWebCrawler() as crawler:
result = await crawler.arun(
url="https://www.nbcnews.com/business",
)
print(result.markdown)
if __name__ == "__main__":
asyncio.run(main())
- 或使用新的命令行界面:
# 基本爬取,输出 markdown
crwl https://www.nbcnews.com/business -o markdown
# BFS 策略深度爬取,最多 10 页
crwl https://docs.crawl4ai.com --deep-crawl bfs --max-pages 10
# 使用 LLM 提取,指定问题
crwl https://www.example.com/products -q "提取所有产品价格"
💖 支持 Crawl4AI
🎉 赞助计划现已开放! 在服务 51K+ 开发者并经过一年发展后,Crawl4AI 正在为 初创公司 和 企业 推出专属支持。成为首批 50 位创始赞助商,将在名人堂中获得永久认可。
Crawl4AI 是 GitHub 上排名第一的开源 Web 爬虫趋势项目。您的支持使其保持独立、创新并免费提供给社区——同时让您直接获得高级福利。
🤝 赞助等级
- 🌱 信仰者($5/月) — 加入数据民主化运动
- 🚀 构建者($50/月) — 优先支持与功能早期访问
- 💼 成长团队($500/月) — 双周同步与优化帮助
- 🏢 数据基础设施合作伙伴($2000/月) — 完整合作伙伴关系,含专属支持
可定制方案 - 详见 SPONSORS.md 获取详情与联系方式
为什么赞助?
没有速率限制的 API。没有锁定。在 Crawl4AI 创造者的直接指导下,构建并拥有您自己的数据管道。
✨ 功能特点
📝 Markdown 生成- 🧹 干净 Markdown:生成格式准确、干净、结构化的 Markdown。
- 🎯 适配 Markdown:基于启发式过滤,去除噪声和无关部分,生成 AI 友好的内容。
- 🔗 引用与参考文献:将页面链接转换为带编号的参考文献列表,包含清晰引用。
- 🛠️ 自定义策略:用户可根据特定需求创建自己的 Markdown 生成策略。
- 📚 BM25 算法:使用 BM25 过滤提取核心信息,去除无关内容。
- 🤖 LLM 驱动的提取:支持所有 LLM(开源与商业),用于结构化数据提取。
- 🧱 分块策略:实现主题、正则、句子级别的分块,用于针对性内容处理。
- 🌌 余弦相似度:根据用户查询查找相关内容块,进行语义提取。
- 🔎 CSS 选择器提取:基于 XPath 和 CSS 选择器的快速模式化数据提取。
- 🔧 模式定义:定义自定义模式,从重复模式中提取结构化 JSON。
- 🖥️ 托管浏览器:使用用户自有的浏览器,完全控制,避免机器人检测。
- 🔄 远程浏览器控制:连接 Chrome DevTools 协议,进行远程大规模数据提取。
- 👤 浏览器配置:创建并管理持久化配置,保存认证状态、cookie 和设置。
- 🔒 会话管理:保留浏览器状态,用于多步爬取复用。
- 🧩 代理支持:无缝连接带认证的代理,确保安全访问。
- ⚙️ 完整浏览器控制:修改 headers、cookie、user agent 等,量身定制爬取配置。
- 🌍 多浏览器支持:兼容 Chromium、Firefox 和 WebKit。
- 📐 动态视口调整:自动调整浏览器视口以匹配页面内容,确保完整渲染和捕获所有元素。
- 🖼️ 媒体支持:提取图像、音频、视频及响应式图像格式(如
srcset和picture)。 - 🚀 动态爬取:执行 JavaScript 并等待异步或同步内容加载。
- 📸 截图:在爬取过程中捕获页面截图,用于调试或分析。
- 📂 原始数据爬取:直接处理原始 HTML(
raw:)或本地文件(file://)。 - 🔗 全面链接提取:提取内链、外链及嵌入的 iframe 内容。
- 🛠️ 可定制钩子:在每一步定义钩子,自定义爬取行为(支持字符串和函数两种 API)。
- 💾 缓存:缓存数据以提高速度,避免重复获取。
- 📄 元数据提取:从网页中提取结构化元数据。
- 📡 IFrame 内容提取:无缝提取嵌入的 iframe 内容。
- 🕵️ 懒加载处理:等待图像完全加载,确保不因懒加载丢失内容。
- 🔄 全页扫描:模拟滚动以加载和捕获所有动态内容,非常适合无限滚动页面。
- 🐳 Docker 化部署:优化的 Docker 镜像,集成 FastAPI 服务器,易于部署。
- 🔑 安全认证:内置 JWT token 认证,保障 API 安全。
- 🔄 API 网关:一键部署,带安全 token 认证,适用于 API 工作流。
- 🌐 可扩展架构:专为大规模生产设计,优化服务器性能。
- ☁️ 云部署:为各大云平台提供即用型配置。
- 🕶️ 隐身模式:通过模拟真实用户规避机器人检测。
- 🏷️ 基于标签的内容提取:根据自定义标签、标题或元数据细化爬取。
- 🔗 链接分析:提取并分析所有链接,进行详细数据探索。
- 🛡️ 错误处理:稳健的错误管理,保障执行流畅。
- 🔐 CORS 与静态服务:支持基于文件系统的缓存和跨域请求。
- 📖 清晰文档:简化且更新的指南,帮助入门与高级使用。
- 🙌 社区认可:表彰贡献者和 pull request,保持透明。
现在试用!
✨ 访问我们的 文档网站
安装 🛠️
Crawl4AI 提供灵活的安装选项,适应不同使用场景。您可以作为 Python 包安装,或使用 Docker。
🐍 使用 pip根据需求选择最适合的安装方式:
基础安装
适用于基本 Web 爬取和抓取任务:
pip install crawl4ai
crawl4ai-setup # 设置浏览器
默认情况下,这会安装 Crawl4AI 的异步版本,使用 Playwright 进行爬取。
👉 注意:安装 Crawl4AI 时,crawl4ai-setup 应自动安装并设置 Playwright。但如果遇到 Playwright 相关错误,可手动安装:
通过命令行:
playwright install如果上述不生效,请尝试更具体的命令:
python -m playwright install chromium
第二种方法在某些情况下更可靠。
同步版本安装
同步版本已弃用,将在未来版本中移除。如需使用 Selenium 的同步版本:
pip install crawl4ai[sync]
开发安装
适用于需要修改源代码的贡献者:
git clone https://github.com/unclecode/crawl4ai.git
cd crawl4ai
pip install -e . # 可编辑模式的基础安装
安装可选功能:
pip install -e ".[torch]" # 带 PyTorch 功能
pip install -e ".[transformer]" # 带 Transformer 功能
pip install -e ".[cosine]" # 带余弦相似度功能
pip install -e ".[sync]" # 带同步爬取(Selenium)
pip install -e ".[all]" # 安装所有可选功能
🐳 Docker 部署🚀 现已可用! 我们完全重新设计的 Docker 实现来了!这个新解决方案使部署比以往更高效、更流畅。
新 Docker 功能
新的 Docker 实现包括:
- 实时监控仪表盘,提供实时系统指标和浏览器池可视性
- 浏览器池,带页面预热功能,响应时间更快
- 交互式游乐场,用于测试和生成请求代码
- MCP 集成,直接连接 AI 工具(如 Claude Code)
- 全面 API 端点,包括 HTML 提取、截图、PDF 生成和 JavaScript 执行
- 多架构支持,自动检测(AMD64/ARM64)
- 优化资源,改进内存管理
开始使用
# 拉取并运行最新版本
docker pull unclecode/crawl4ai:latest
docker run -d -p 11235:11235 --name crawl4ai --shm-size=1g unclecode/crawl4ai:latest
# 访问监控仪表盘:http://localhost:11235/dashboard
# 或游乐场:http://localhost:11235/playground
快速测试
运行快速测试(两种 Docker 选项均适用):
import requests
# 提交爬取任务
response = requests.post(
"http://localhost:11235/crawl",
json={"urls": ["https://example.com"], "priority": 10}
)
if response.status_code == 200:
print("爬取任务提交成功。")
if "results" in response.json():
results = response.json()["results"]
print("爬取任务完成。结果:")
for result in results:
print(result)
else:
task_id = response.json()["task_id"]
print(f"爬取任务已提交。任务 ID:{task_id}")
result = requests.get(f"http://localhost:11235/task/{task_id}")
更多示例请参见 Docker 示例。有关高级配置、监控功能和生产部署,请参阅 自托管指南。
🔬 高级用法示例 🔬
您可以在目录 docs/examples 中查看项目结构。那里有各种示例;这里分享一些常用的。
📝 启发式 Markdown 生成:干净与适配 Markdownimport asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
from crawl4ai.content_filter_strategy import PruningContentFilter, BM25ContentFilter
from crawl4ai.markdown_generation_strategy import DefaultMarkdownGenerator
async def main():
browser_config = BrowserConfig(
headless=True,
verbose=True,
)
run_config = CrawlerRunConfig(
cache_mode=CacheMode.ENABLED,
markdown_generator=DefaultMarkdownGenerator(
content_filter=PruningContentFilter(threshold=0.48, threshold_type="fixed", min_word_threshold=0)
),
# markdown_generator=DefaultMarkdownGenerator(
# content_filter=BM25ContentFilter(user_query="WHEN_WE_FOCUS_BASED_ON_A_USER_QUERY", bm25_threshold=1.0)
# ),
)
async with AsyncWebCrawler(config=browser_config) as crawler:
result = await crawler.arun(
url="https://docs.micronaut.io/4.9.9/guide/",
config=run_config
)
print(len(result.markdown.raw_markdown))
print(len(result.markdown.fit_markdown))
if __name__ == "__main__":
asyncio.run(main())
🖥️ 执行 JavaScript & 提取结构化数据(无需 LLM)import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
from crawl4ai import JsonCssExtractionStrategy
import json
async def main():
schema = {
"name": "KidoCode Courses",
"baseSelector": "section.charge-methodology .w-tab-content > div",
"fields": [
{
"name": "section_title",
"selector": "h3.heading-50",
"type": "text",
},
{
"name": "section_description",
"selector": ".charge-content",
"type": "text",
},
{
"name": "course_name",
"selector": ".text-block-93",
"type": "text",
},
{
"name": "course_description",
"selector": ".course-content-text",
"type": "text",
},
{
"name": "course_icon",
"selector": ".image-92",
"type": "attribute",
"attribute": "src"
}
]
}
extraction_strategy = JsonCssExtractionStrategy(schema, verbose=True)
browser_config = BrowserConfig(
headless=False,
verbose=True
)
run_config = CrawlerRunConfig(
extraction_strategy=extraction_strategy,
js_code=["""(async () => {const tabs = document.querySelectorAll("section.charge-methodology .tabs-menu-3 > div");for(let tab of tabs) {tab.scrollIntoView();tab.click();await new Promise(r => setTimeout(r, 500));}})();"""],
cache_mode=CacheMode.BYPASS
)
async with AsyncWebCrawler(config=browser_config) as crawler:
result = await crawler.arun(
url="https://www.kidocode.com/degrees/technology",
config=run_config
)
companies = json.loads(result.extracted_content)
print(f"成功提取 {len(companies)} 个条目")
print(json.dumps(companies[0], indent=2))
if __name__ == "__main__":
asyncio.run(main())
📚 使用 LLM 提取结构化数据import os
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode, LLMConfig
from crawl4ai import LLMExtractionStrategy
from pydantic import BaseModel, Field
class OpenAIModelFee(BaseModel):
model_name: str = Field(..., description="OpenAI 模型的名称。")
input_fee: str = Field(..., description="OpenAI 模型的输入 token 费用。")
output_fee: str = Field(..., description="OpenAI 模型的输出 token 费用。")
async def main():
browser_config = BrowserConfig(verbose=True)
run_config = CrawlerRunConfig(
word_count_threshold=1,
extraction_strategy=LLMExtractionStrategy(
# 这里可以使用 Litellm 库支持的任何 provider,例如:ollama/qwen2
# provider="ollama/qwen2", api_token="no-token",
llm_config = LLMConfig(provider="openai/gpt-4o", api_token=os.getenv('OPENAI_API_KEY')),
schema=OpenAIModelFee.schema(),
extraction_type="schema",
instruction="""从爬取的内容中,提取所有提到的模型名称及其输入和输出 token 的费用。不要遗漏整个内容中的任何模型。提取的模型 JSON 格式应如下所示:
{"model_name": "GPT-4", "input_fee": "US$10.00 / 1M tokens", "output_fee": "US$30.00 / 1M tokens"}."""
),
cache_mode=CacheMode.BYPASS,
)
async with AsyncWebCrawler(config=browser_config) as crawler:
result = await crawler.arun(
url='https://openai.com/api/pricing/',
config=run_config
)
print(result.extracted_content)
if __name__ == "__main__":
asyncio.run(main())
🤖 使用自己的浏览器和自定义用户配置import os, sys
from pathlib import Path
import asyncio, time
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
async def test_news_crawl():
# 创建持久化用户数据目录
user_data_dir = os.path.join(Path.home(), ".crawl4ai", "browser_profile")
os.makedirs(user_data_dir, exist_ok=True)
browser_config = BrowserConfig(
verbose=True,
headless=True,
user_data_dir=user_data_dir,
use_persistent_context=True,
)
run_config = CrawlerRunConfig(
cache_mode=CacheMode.BYPASS
)
async with AsyncWebCrawler(config=browser_config) as crawler:
url = "ADDRESS_OF_A_CHALLENGING_WEBSITE"
result = await crawler.arun(
url,
config=run_config,
magic=True,
)
print(f"成功爬取 {url}")
print(f"内容长度:{len(result.markdown)}")
💡 提示: 某些网站可能使用 CAPTCHA 验证机制防止自动访问。如果您的工作流遇到此类挑战,可以选择集成第三方 CAPTCHA 处理服务,例如 CapSolver。它们支持 reCAPTCHA v2/v3、Cloudflare Turnstile、Challenge、AWS WAF 等。请确保您的使用方式符合目标网站的服务条款和适用法律。
✨ 近期更新
版本 0.8.6 — 安全热修复:litellm 供应链修复因原始包受 PyPI 供应链攻击影响,将 litellm 依赖替换为 unclecode-litellm。如果您使用的是 v0.8.5 或更早版本,请立即升级。
pip install -U crawl4ai
版本 0.8.5 重点 - 反机器人检测、Shadow DOM 及 60+ 错误修复自 v0.8.0 以来最大的发布。反机器人检测及代理升级、Shadow DOM 扁平化、深度爬取取消,以及 60 多项错误修复。
🛡️ 反机器人检测与代理升级:
- 三层检测:已知厂商、通用封锁指标、结构完整性检查
- 自动重试,带代理链和回退 fetch 函数
from crawl4ai import CrawlerRunConfig from crawl4ai.async_configs import ProxyConfig config = CrawlerRunConfig( proxy_config=[ProxyConfig.DIRECT, ProxyConfig(server="http://my-proxy:8080")], max_retries=2, fallback_fetch_function=my_web_unlocker, )🌑 Shadow DOM 扁平化:
- 提取隐藏在 shadow DOM 组件中的内容
config = CrawlerRunConfig(flatten_shadow_dom=True)🛑 深度爬取取消:
- 使用
cancel()或should_cancel回调优雅停止长时间运行的爬取 - 支持 BFS、DFS 和 BestFirst 策略
- 使用
⚙️ 配置默认 API:
set_defaults()/get_defaults()/reset_defaults()方法(BrowserConfig 和 CrawlerRunConfig)
🔒 关键安全修复:
- Docker
/crawl端点反序列化导致 RCE — 移除eval(),添加白名单 - Redis CVE-2025-49844(CVSS 10.0)— 升级至 7.2.7
- Docker
60+ 错误修复,涵盖浏览器管理、代理、深度爬取、提取、CLI 和 Docker
此版本引入深度爬取的崩溃恢复、用于快速 URL 发现的新预取模式,以及 Docker 部署的关键安全修复。
🔄 深度爬取崩溃恢复:
- 每个 URL 触发
on_state_change回调,实现实时状态持久化 resume_state参数用于从已保存的检查点继续- JSON 可序列化状态,适合 Redis/数据库存储
- 支持 BFS、DFS 和 Best-First 策略
from crawl4ai.deep_crawling import BFSDeepCrawlStrategy strategy = BFSDeepCrawlStrategy( max_depth=3, resume_state=saved_state, # 从检查点继续 on_state_change=save_to_redis, # 每个 URL 后调用 )- 每个 URL 触发
⚡ 预取模式,快速 URL 发现:
prefetch=True跳过 markdown、提取和媒体处理- 比完整处理快 5-10 倍
- 适合两阶段爬取:先发现,再有选择地处理
config = CrawlerRunConfig(prefetch=True) result = await crawler.arun("https://example.com", config=config) # 仅返回 HTML 和链接 - 不生成 markdown🔒 安全修复(Docker API):
- 默认禁用钩子(
CRAWL4AI_HOOKS_ENABLED=false) - API 端点阻止
file://URL 以防止 LFI - 从钩子执行沙箱中移除
__import__
- 默认禁用钩子(
此版本专注于稳定性,包含 11 项社区报告问题的错误修复。无新功能,但显著提升了可靠性。
🐳 Docker API 修复:
- 修复深度爬取请求中
ContentRelevanceFilter的反序列化问题(#1642) - 修复
BrowserConfig.to_dict()中ProxyConfig的 JSON 序列化问题(#1629) - 修复 Docker 镜像中
.cache目录权限问题(#1638)
- 修复深度爬取请求中
🤖 LLM 提取改进:
- 可配置速率限制退避,新增
LLMConfig参数(#1269):from crawl4ai import LLMConfig config = LLMConfig( provider="openai/gpt-4o-mini", backoff_base_delay=5, # 首次重试等待 5 秒 backoff_max_attempts=5, # 最多重试 5 次 backoff_exponential_factor=3 # 每次重试延迟乘以 3 ) LLMExtractionStrategy支持 HTML 输入格式(#1178):from crawl4ai import LLMExtractionStrategy strategy = LLMExtractionStrategy( llm_config=config, instruction="提取表格数据", input_format="html" # 现在支持:"html", "markdown", "fit_markdown" )- 修复原始 HTML URL 变量 - 提取策略现在接收
"Raw HTML"而非 HTML 数据块(#1116)
- 可配置速率限制退避,新增
🔗 URL 处理:
- 修复 JavaScript 重定向后的相对 URL 解析问题(#1268)
- 修复提取代码中的 import 语句格式问题(#1181)
📦 依赖更新:
- 将已弃用的 PyPDF2 替换为 pypdf(#1412)
- Pydantic v2 ConfigDict 兼容性 - 不再出现弃用警告(#678)
🧠 AdaptiveCrawler:
- 修复查询扩展,使其实际使用 LLM 而非硬编码模拟数据(#1621)
[完整 v