开源项目

crawl4ai

crawl4ai

专为 LLM 应用设计的开源网络爬虫,将网页内容直接转化为干净的 Markdown、结构化数据,方便接入 RAG、agent 或数据管道。亮点在于内置反爬虫机制(3 级检测+代理自动切换)、Shadow DOM 展开、深爬断点续传等特性,Docker 一键部署且支持 LLM 驱动的内容提取,社区活跃,50k+ stars 验证了其可靠性。

README

🚀🤖 Crawl4AI: 面向 LLM 的开源友好 Web 爬虫与抓取工具

unclecode%2Fcrawl4ai | Trendshift

GitHub Stars GitHub Forks

PyPI version Python Version Downloads GitHub Sponsors


🚀 Crawl4AI Cloud API — 封闭测试(即将推出)

可靠的大规模 Web 数据提取,旨在比现有方案 大幅降低成本。

👉 请此处申请早期访问
我们将分阶段接入,并与早期用户紧密合作。名额有限。


在 X 上关注 在 LinkedIn 上关注 加入我们的 Discord

Crawl4AI 将 Web 转化为干净、LLM 就绪的 Markdown,适用于 RAG(检索增强生成)、agent(智能体)和数据管道。快速、可控,经 50k+ 星社区实战检验。

✨ 查看最新更新 v0.8.6

✨ 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,云友好

🚀 快速入门

  1. 安装 Crawl4AI:
# 安装包
pip install -U crawl4ai

# 预发布版本
pip install crawl4ai --pre

# 运行安装后设置
crawl4ai-setup

# 验证安装
crawl4ai-doctor

如果遇到浏览器相关问题,可以手动安装:

python -m playwright install --with-deps chromium
  1. 用 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())
  1. 或使用新的命令行界面:
# 基本爬取,输出 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,保持透明。

现在试用!

✨ 试用此 Open In Colab

✨ 访问我们的 文档网站

安装 🛠️

Crawl4AI 提供灵活的安装选项,适应不同使用场景。您可以作为 Python 包安装,或使用 Docker。

🐍 使用 pip

根据需求选择最适合的安装方式:

基础安装

适用于基本 Web 爬取和抓取任务:

pip install crawl4ai
crawl4ai-setup # 设置浏览器

默认情况下,这会安装 Crawl4AI 的异步版本,使用 Playwright 进行爬取。

👉 注意:安装 Crawl4AI 时,crawl4ai-setup 应自动安装并设置 Playwright。但如果遇到 Playwright 相关错误,可手动安装:

  1. 通过命令行:

    playwright install
    
  2. 如果上述不生效,请尝试更具体的命令:

    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 生成:干净与适配 Markdown
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())
🖥️ 执行 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
  • 60+ 错误修复,涵盖浏览器管理、代理、深度爬取、提取、CLI 和 Docker

完整 v0.8.5 发布说明 →

版本 0.8.0 重点 - 崩溃恢复与预取模式

此版本引入深度爬取的崩溃恢复、用于快速 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 发现:

    • 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__

完整 v0.8.0 发布说明 →

版本 0.7.8 重点 - 稳定性与错误修复

此版本专注于稳定性,包含 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

开源项目unclecode2026-05-28原文

相关内容