将网页转换为LLM友好的Markdown格式,支持RAG和Agent数据管道,提供Docker快速部署和内存自适应调度器修复。
可靠的、大规模网页提取工具,现已构建为比现有任何解决方案都更经济高效的方案。
👉 点击此处申请抢先体验 我们将分阶段开放,并与众早期用户紧密合作。名额有限。
Crawl4AI 将网页转换为干净的、可供 LLM 使用的 Markdown,用于 RAG、AI 智能体和数据管道。由 5 万+ star 的社区验证,快速、可控。
✨ 查看最新更新 v0.9.2
✨ v0.9.2 新特性:维护补丁版本。修复了流式爬取关闭时 MemoryAdaptiveDispatcher 的任务/页面泄漏问题、Docker Playground「高级配置」和监控 WebSocket 认证、Playwright headless-shell 打包,以及 GPU (ENABLE_GPU=true) Docker 构建。发布说明 →
✨ v0.9.0 新特性:Docker API 服务器主要的默认安全版本。认证默认开启,服务器默认绑定 loopback(除非提供 token),请求体现在是不受信任的信任边界。发布说明 →
✨ v0.8.7 新特性:安全加固版本。修复了关键 Docker API 漏洞(RCE、SSRF、认证绕过、文件写入、XSS、硬编码 JWT secret),新增 DomainMapper,并包含爬取、深度爬取和 LLM 提取的修复。发布说明 →
✨ v0.8.0 新特性:崩溃恢复与预取模式!深度爬取崩溃恢复,支持 resume_state 和 on_state_change 回调用于长时间运行的爬取任务。新的 prefetch=True 模式,URL 发现速度提升 5-10 倍。发布说明 →
✨ v0.7.8 新特性:稳定性与 bug 修复版本!修复了 11 个 bug,涉及 Docker API 问题、LLM 提取改进、URL 处理修复和依赖更新。发布说明 →
我在 Amstrad 上长大,感谢我的父亲,从此再也没有停止过构建。在研究生阶段,我专攻 NLP 并为研究构建爬虫。正是在那里,我明白了提取(extraction)有多重要。
2023 年,我需要网页转 Markdown。当时的「开源」选项需要账号、API token,还要 16 美元,但实际表现仍然不达标。我进入了狂暴模式,花了几天构建出 Crawl4AI,然后它就火了。现在它是 GitHub 上 star 最多的爬虫。
我做开源是为了可获取性,任何人都可以无门槛使用它。现在我正在构建一个面向可负担性的平台,任何人都可以低成本运行大规模爬取。如果这引起你的共鸣,欢迎加入,发送反馈,或者就去爬取一些精彩的内容。
✨ LLM 就绪的输出,智能 Markdown,包含标题、表格、代码、引用提示
✨ 实践中的快速,异步浏览器池、缓存、最小跳转次数
✨ 完全控制,会话、代理、cookies、用户脚本、钩子
✨ 自适应智能,学习站点模式,只探索重要的内容
✨ 任意部署,零 key、CLI 和 Docker,云友好
# 安装包
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 "Extract all product prices"
🎉 赞助计划现已开放!在为 51,000+ 开发者提供动力并经历一年成长后,Crawl4AI 正式推出面向初创企业和企业用户的专属支持服务。加入前 50 位创始赞助商,即可永久收录于我们的名人堂。
Crawl4AI 是 GitHub 上排名第一的开源网页爬虫。您的支持使其保持独立、创新,并对社区免费——同时让您直接获得 premium 权益。
🌱 Believer(5 美元/月)—— 加入数据民主化运动
🚀 Builder(50 美元/月)—— 优先支持与新功能抢先体验
💼 Growing Team(500 美元/月)—— 双周同步与优化帮助
🏢 Data Infrastructure Partner(2000 美元/月)—— 完整合作伙伴关系与专属支持 支持自定义方案——详见 SPONSORS.md
为什么要赞助?没有限速 API。没有锁定。以数据民主化为使命,直接获得 Crawl4AI 创建者的指导,构建并拥有自己的数据管道。
查看所有等级与权益 →
🧹 清洁 Markdown:生成干净、结构化的 Markdown,格式准确。
🎯 适配 Markdown:基于启发式的过滤,移除噪音和无相关内容,利于 AI 处理。
🔗 引用和参考文献:将页面链接转换为带clean引用标记的编号参考文献列表。
🛠️ 自定义策略:用户可以创建定制化的 Markdown 生成策略以满足特定需求。
📚 BM25 算法:使用 BM25 过滤提取核心信息并移除无关内容。
🤖 LLM 驱动提取:支持所有 LLM(开源和闭源)进行结构化数据提取。
🧱 分块策略:实现分块(基于主题、regex、句子级别)用于目标内容处理。
🌌 余弦相似度:基于用户查询查找相关内容块,用于语义提取。
🔎 基于 CSS 的提取:使用 XPath 和 CSS 选择器进行快速的基于模式的数据提取。
🔧 模式定义:定义自定义模式,从重复模式中提取结构化 JSON。
🖥️ 托管浏览器:使用用户自有浏览器,完全控制,避免机器人检测。
🔄 远程浏览器控制:连接 Chrome 开发者工具协议,用于远程、大规模数据提取。
👤 浏览器配置管理器:创建和管理持久化配置,包含保存的认证状态、cookies 和设置。
🔒 会话管理:保留浏览器状态并在多步爬取中复用。
🧩 代理支持:无缝连接需要认证的代理,实现安全访问。
⚙️ 完全浏览器控制:修改请求头、cookies、用户代理等,定制爬取设置。
🌍 多浏览器支持:兼容 Chromium、Firefox 和 WebKit。
📐 动态视口调整:自动调整浏览器视口以匹配页面内容,确保完整渲染和捕获所有元素。
🖼️ 媒体支持:提取图片、音频、视频和响应式图片格式(如 srcset 和 picture)。
🚀 动态爬取:执行 JS 并等待异步或同步内容,用于动态内容提取。
📸 截图:在爬取期间捕获页面截图,用于调试或分析。
📂 原始数据爬取:直接处理原始 HTML (raw:) 或本地文件 (file://)。
🔗 全面的链接提取:提取内部链接、外部链接和嵌入的 iframe 内容。
🛠️ 可自定义钩子:在每个步骤定义钩子以自定义爬取行为(支持字符串和函数两种 API 形式)。
💾 缓存:缓存数据以提升速度并避免重复抓取。
📄 元数据提取:从网页中获取结构化元数据。
📡 iframe 内容提取:无缝提取嵌入式 iframe 内容。
🕵️ 懒加载处理:等待图片完全加载,确保不会因懒加载而遗漏任何内容。
🔄 全页扫描:模拟滚动以加载并捕获所有动态内容,适用于无限滚动页面。
🐳 Docker 化部署:优化的 Docker 镜像,内置 FastAPI 服务器,便于部署。
🔑 安全认证:内置 JWT 令牌认证,保障 API 安全。
🔄 API 网关:一键部署,支持安全令牌认证的 API 工作流。
🌐 可扩展架构:为大规模生产设计,优化服务器性能。
☁️ 云端部署:针对主流云平台的即用型配置。
🕶️ 隐身模式:通过模拟真实用户来规避机器人检测。
🏷️ 基于标签的内容提取:基于自定义标签、头部或元数据精确定义爬取范围。
🔗 链接分析:提取并分析所有链接以进行详细数据探索。
🛡️ 错误处理:稳健的错误管理,确保无缝执行。
🔐 CORS 和静态资源服务:支持基于文件系统的缓存和跨域请求。
📖 清晰的文档:简化的更新指南,助力快速入门和进阶使用。
🙌 社区认可:致谢贡献者和 Pull Request,保持透明。
✨ 动手试试
✨ 访问我们的文档网站
Crawl4AI 提供了灵活的安装选项,以满足各种使用场景。你可以将它作为 Python 包安装,也可以使用 Docker。
选择最适合你需求的安装方式:
适用于基础网页爬取任务:
pip install crawl4ai
crawl4ai-setup # 设置浏览器
默认情况下,这将安装异步版本的 Crawl4AI,使用 Playwright 进行网页爬取。
👉 注意:安装 Crawl4AI 时,crawl4ai-setup 应该会自动安装并配置 Playwright。但是,如果遇到任何与 Playwright 相关的错误,可以使用以下方法之一手动安装:
通过命令行:playwright install
通过命令行:
playwright install
如果上述方法不起作用,尝试这个更具体的命令:python -m playwright install chromium
如果上述方法不起作用,尝试这个更具体的命令:
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 实现包括:
实时监控仪表板,展示系统指标和浏览器池状态
浏览器池化与页面预热,更快响应
交互式 Playground,可测试和生成请求代码
MCP 集成,可直接连接到 Claude Code 等 AI 工具
全面的 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
# 或 Playground 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("Crawl job submitted successfully.")
if "results" in response.json():
results = response.json()["results"]
print("Crawl job completed. Results:")
for result in results:
print(result)
else:
task_id = response.json()["task_id"]
print(f"Crawl job submitted. Task ID:: {task_id}")
result = requests.get(f"http://localhost:11235/task/{task_id}")
更多示例请参阅 Docker Examples。高级配置、监控功能和生产环境部署,请参阅 Self-Hosting Guide。
🔬 高级用法示例 🔬
你可以在 docs/examples 目录中查看项目结构。在那里可以找到各种示例,以下分享一些热门示例。
import 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())
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"Successfully extracted {len(companies)} companies")
print(json.dumps(companies[0], indent=2))
if __name__ == "__main__":
asyncio.run(main())
import os
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode, LLMConfig
from crawl4ai import LLMExtractionStrategy
from pydantic import BaseModel, Field
```python
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 = "一个具有挑战性网站的地址"
result = await crawler.arun(
url,
config=run_config,
magic=True,
)
print(f"成功爬取 {url}")
print(f"内容长度:{len(result.markdown)}")
修复了 dispatcher、Docker 和 GPU 构建中的 bug 的维护补丁版本。MemoryAdaptiveDispatcher 不再在关闭流式爬取时泄漏爬取任务和浏览器页面。Docker 修复涉及 Playground "Advanced Config" 400 错误、JWT 认证下 Monitor WebSocket 500 错误,以及 Playwright headless-shell 打包问题。ENABLE_GPU=true 的 Docker 构建不再在 CUDA toolkit 上失败。
无新功能,无破坏性变更。
pip install -U crawl4ai
完整 v0.9.2 发布说明 →
修复了 12 个 bug 并新增一个功能的小版本。PruningContentFilter 新增的 preserve_classes / preserve_tags 参数允许将不应被裁剪的 CSS 类或 HTML 标签列入白名单——可用于保护作者名、时间戳等短元数据元素。
Bug 修复涵盖 Docker(认证门 UI、supervisord/redis 目录、FastAPI 兼容性、redis 认证)、浏览器(Windows channel 崩溃、上下文快照泄漏)、核心(HTTP 超时单位不匹配、最佳优先排序)和抽取(html2text 表格属性)。
pip install -U crawl4ai
完整 v0.9.1 发布说明 →
Docker API 服务器的重量级安全默认发布。开箱即用的部署经过深度防御加固:默认开启认证、服务器绑定 loopback(除非你提供 token)、网络请求体被视为不可信边界。
pip install -U crawl4ai
迁移指南 → · 完整 v0.9.0 发布说明 →
安全加固版本。修复关键 Docker API 漏洞(AST 沙箱逃逸 RCE、hook 沙箱 RCE、硬编码 JWT secret、webhook 和爬取端点上的 SSRF、任意文件写入、monitor 认证绕过、存储型 XSS,以及未认证的 JS 执行),新增 DomainMapper 功能,并修复了一大批爬取、深度爬取和 LLM 相关问题。如果你自托管 Docker API,请立即升级。
pip install -U crawl4ai
完整 v0.8.7 发布说明 →
因 PyPI 供应链攻击影响原包,将 litellm 依赖替换为 unclecode-litellm。如果你使用的是 v0.8.5 或更早版本,请立即升级。
pip install -U crawl4ai
自 v0.8.0 以来最大的版本。反机器人检测与代理升级、Shadow DOM 扁平化、深度爬取取消,以及 60 多个 bug 修复。
🛡️ 反机器人检测与代理升级:
3 层检测:已知厂商、通用拦截指标、结构完整性检查
自动重试与代理链及备用获取函数
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)
🛑 深度爬取取消: