Crawl4AI旨在让网页爬取和数据提取变得简单而高效。无论构建复杂的 AI 应用程序还是增强大语言模型,Crawl4AI 都能提供简化工作流程所需的工具。凭借完全的异步支持,Crawl4AI 可确保爬取任务快速、可靠且可扩展。
主要功能
-
📝 Markdown 生成
- 🧹 Clean Markdown:生成具有准确格式的干净、结构化的 Markdown。
- 🎯 Fit Markdown:基于启发式的过滤,去除噪声和不相关的部分,实现 AI 友好的处理。
- 🔗 引文和参考文献:将页面链接转换为带有清晰引文的编号参考文献列表。
- 🛠️ 自定义策略:用户可以根据特定需求创建自己的 Markdown 生成策略。
- 📚 BM25 算法:采用基于 BM25 的过滤来提取核心信息和删除不相关的内容。
-
📊 结构化数据提取
- 🤖 LLM 驱动的提取:支持所有 LLM(开源和专有)进行结构化数据提取。
- 🧱 分块策略:为目标内容处理实施分块(基于主题、正则表达式、句子级别)。
- 🌌 余弦相似度:根据用户查询查找相关内容块以进行语义提取。
- 🔎 基于 CSS 的提取:使用 XPath 和 CSS 选择器快速提取基于架构的数据。
- 🔧 Schema Definition:定义用于从重复模式中提取结构化 JSON 的自定义 Schema。
-
🌐 浏览器集成
- 🖥️ Managed Browser:使用具有完全控制权的用户拥有的浏览器,避免机器人检测。
- 🔄 远程浏览器控制:连接到 Chrome 开发者工具协议以进行远程大规模数据提取。
- 👤 Browser Profiler:使用保存的身份验证状态、Cookie 和设置创建和管理持久性配置文件。
- 🔒 会话管理:保留浏览器状态并将其重新用于多步骤爬网。
- 🧩 代理支持: 通过身份验证无缝连接到代理以实现安全访问。
- ⚙️ 完全浏览器控制:修改标头、cookie、用户代理等,以实现定制的抓取设置。
- 🌍 多浏览器支持:与 Chromium、Firefox 和 WebKit 兼容。
- 📐 动态视口调整:自动调整浏览器视口以匹配页面内容,确保完整渲染和捕获所有元素。
-
🔎 爬行和刮擦
- 🖼️ 媒体支持:提取图像、音频、视频和响应式图像格式,如 和 。
srcsetpicture
- 🚀 动态抓取:执行 JS 并等待异步或同步以进行动态内容提取。
- 📸 屏幕截图:在抓取过程中捕获页面屏幕截图以进行调试或分析。
- 📂 原始数据爬取:直接处理原始 HTML () 或本地文件 ()。
raw:file://
- 🔗 综合链接提取:提取内部、外部链接和嵌入式 iframe 内容。
- 🛠️ 可自定义的钩子:在每一步定义钩子以自定义爬网行为。
- 💾 缓存:缓存数据以提高速度并避免冗余获取。
- 📄 元数据提取:从网页中检索结构化元数据。
- 📡 IFrame 内容提取:从嵌入的 iframe 内容中无缝提取。
- 🕵️ 延迟加载处理:等待图像完全加载,确保不会因延迟加载而丢失任何内容。
- 🔄 整页扫描:模拟滚动以加载和捕获所有动态内容,非常适合无限滚动页面。
- 🖼️ 媒体支持:提取图像、音频、视频和响应式图像格式,如 和 。
-
🚀 部署
- 🐳 Dockerized Setup:使用 FastAPI 服务器优化 Docker 镜像,便于部署。
- 🔑 安全身份验证:内置 JWT 令牌身份验证,确保 API 安全。
- 🔄 API Gateway:为基于 API 的工作流提供安全令牌身份验证的一键式部署。
- 🌐 可扩展架构:专为大规模生产和优化的服务器性能而设计。
- ☁️ 云部署:主要云平台的即用型部署配置。
-
🎯 附加功能
- 🕶️ 隐身模式:通过模仿真实用户来避免机器人检测。
- 🏷️ 基于标签的内容提取:根据自定义标签、标头或元数据优化爬网。
- 🔗 链接分析:提取并分析所有链接以进行详细的数据探索。
- 🛡️ 错误处理:强大的错误管理,实现无缝执行。
- 🔐 CORS & Static Serving:支持基于文件系统的缓存和跨域请求。
- 📖 清晰的文档:简化和更新的入门和高级使用指南。
- 🙌 社区认可:感谢贡献者和拉取请求以实现透明度。
安装和使用
- 安装 Crawl4AI:
# Install the package
pip install -U crawl4ai
# For pre release versions
pip install crawl4ai --pre
# Run post-installation setup
crawl4ai-setup
# Verify your installation
crawl4ai-doctor
如果您遇到任何与浏览器相关的问题,您可以手动安装它们:
python -m playwright install --with-deps chromium
- 使用 Python 运行简单的 Web 爬虫:
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())
- 或者使用新的命令行界面:
# Basic crawl with markdown output
crwl https://www.nbcnews.com/business -o markdown
# Deep crawl with BFS strategy, max 10 pages
crwl https://docs.crawl4ai.com --deep-crawl bfs --max-pages 10
# Use LLM extraction with a specific question
crwl https://www.example.com/products -q "Extract all product prices"
实战演习
场景1:📝 使用 Clean and Fit 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.7.6/guide/",
config=run_config
)
print(len(result.markdown.raw_markdown))
print(len(result.markdown.fit_markdown))
if __name__ == "__main__":
asyncio.run(main())
场景2:🖥️ 在没有LLMs的情况下执行JavaScript并提取结构化数据
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
from crawl4ai.extraction_strategy 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())
场景3:📚 使用 LLM 提取结构化数据
import os
import asyncio
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode, LLMConfig
from crawl4ai.extraction_strategy import LLMExtractionStrategy
from pydantic import BaseModel, Field
class OpenAIModelFee(BaseModel):
model_name: str = Field(..., description="Name of the OpenAI model.")
input_fee: str = Field(..., description="Fee for input token for the OpenAI model.")
output_fee: str = Field(..., description="Fee for output token for the OpenAI model.")
async def main():
browser_config = BrowserConfig(verbose=True)
run_config = CrawlerRunConfig(
word_count_threshold=1,
extraction_strategy=LLMExtractionStrategy(
# Here you can use any provider that Litellm library supports, for instance: 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="""From the crawled content, extract all mentioned model names along with their fees for input and output tokens.
Do not miss any models in the entire content. One extracted model JSON format should look like this:
{"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())
场景4:🤖 将您自己的浏览器与自定义用户配置文件一起使用
import os, sys
from pathlib import Path
import asyncio, time
from crawl4ai import AsyncWebCrawler, BrowserConfig, CrawlerRunConfig, CacheMode
async def test_news_crawl():
# Create a persistent user data directory
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"Successfully crawled {url}")
print(f"Content length: {len(result.markdown)}")