🔥🕷️ Crawl4AI: Open-source LLM Friendly Web Crawler & Scrapper
crawl4ai基本信息
crawl4ai介绍
Crawl4AI 是一个开源的 Python 库,旨在简化网络爬取并轻松从网页中提取有价值信息。无论您是将其集成为 REST API 还是直接在 Python 项目中使用,Crawl4AI都提供了一个强大、灵活和完全异步的解决方案,专为大型语言模型(LLMs)和 AI 应用量身定制。
简介
Crawl4AI旨在使网络爬取和从网页中提取数据变得简单高效。无论您是构建复杂的 AI 应用程序还是增强大型语言模型,Crawl4AI都提供了您需要简化工作流程的工具。通过完全的异步支持,Crawl4AI确保您的爬取任务快速、可靠和可扩展。
快速入门 🚀
在短时间内快速上手Crawl4AI!以下是一个展示其强大异步功能的简单示例:
import asyncio
from crawl4ai import AsyncWebCrawler
async def main():
# 初始化异步网络爬虫
async with AsyncWebCrawler(verbose=True) as crawler:
# 爬取指定的 URL
result = await crawler.arun(url="https://www.nbcnews.com/business")
# 以 Markdown 格式显示提取的内容
print(result.markdown)
# 执行异步主函数
if __name__ == "__main__":
asyncio.run(main())
解释:
-
导入库:从
crawl4ai
库和asyncio
模块导入AsyncWebCrawler
。 -
创建异步上下文:使用异步上下文管理器实例化
AsyncWebCrawler
。 -
运行爬虫:利用
arun()
方法异步爬取指定的 URL 并提取有意义的内容。 -
打印结果:输出提取的内容,以 Markdown 格式呈现。
-
执行异步函数:使用
asyncio.run()
执行异步main
函数。
特点 ✨
Crawl4AI充满了旨在使您的网络爬取和数据提取任务无缝进行的功能:
-
🆓 完全免费和开源:没有隐藏成本或许可费用。
-
🚀 极速性能:以卓越的速度胜过许多付费服务。
-
🤖 LLM友好的输出格式:支持 JSON、清理的 HTML 和 Markdown。
-
🌍 并发爬取:同时爬取多个 URL,实现最大效率。
-
🎨 媒体标签提取:检索包括图像、音频和视频在内的所有媒体标签。
-
🔗 全面的链接提取:收集外部和内部链接。
-
📚 元数据提取:从网页中提取详细的元数据。
-
🔄 自定义钩子和身份验证:自定义标头、身份验证并在爬取之前修改页面。
-
🕵 ️ 用户代理定制:轻松模仿不同的浏览器或设备。
-
🖼 ️ 网页截图:捕获网页的视觉快照。
-
📜 JavaScript 执行:在爬取动态内容之前执行自定义 JavaScript。
-
📊 结构化数据提取:利用
JsonCssExtractionStrategy
进行精确的数据结构化。 -
📚 多功能分块策略:包括基于主题、正则表达式、基于句子等。
-
🧠 高级提取技术:具有余弦聚类和基于LLM的提取功能。
-
🎯 精确的 CSS 选择器支持:使用准确的 CSS 选择器定位特定数据点。
-
📝 基于指令的细化:传递指令或关键字以增强数据提取。
-
🔒 代理支持:通过代理配置增强隐私和访问权限。
-
🔄 会话管理:轻松处理复杂的多页面爬取场景。
-
🌐 完全异步架构:通过异步支持提升性能和可扩展性。
安装 🛠 ️
Crawl4AI提供灵活的安装选项,以满足各种用例。选择最适合您工作流程的方法:
使用 pip 🐍
基本安装
用于标准网络爬取和抓取任务:
pip install crawl4ai
默认情况下,这将使用 Playwright 安装 Crawl4AI 的异步版本进行网络爬取。
👉 注意:如果在安装过程中遇到与 Playwright 相关的错误,请使用以下方法手动安装 Playwright:
- 命令行:
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 .
高级用法 🔬
通过这些高级功能和用例发挥Crawl4AI的全部潜力:
执行 JavaScript & 使用 CSS 选择器
通过执行自定义 JavaScript 和使用 CSS 选择器来增强您的爬取任务。
import asyncio
from crawl4ai import AsyncWebCrawler
async def main():
async with AsyncWebCrawler(verbose=True) as crawler:
js_code = [
"const loadMoreButton = Array.from(document.querySelectorAll('button')).find(button => button.textContent.includes('Load More')); loadMoreButton && loadMoreButton.click();"
]
result = await crawler.arun(
url="https://www.nbcnews.com/business",
js_code=js_code,
css_selector="article.tease-card",
bypass_cache=True
)
print(result.extracted_content)
if __name__ == "__main__":
asyncio.run(main())
使用代理
通过代理路由您的爬取任务,增强隐私和访问权限。
import asyncio
from crawl4ai import AsyncWebCrawler
async def main():
async with AsyncWebCrawler(verbose=True, proxy="http://127.0.0.1:7890") as crawler:
result = await crawler.arun(
url="https://www.nbcnews.com/business",
bypass_cache=True
)
print(result.markdown)
if __name__ == "__main__":
asyncio.run(main())
无需LLM提取结构化数据
使用JsonCssExtractionStrategy
通过 CSS 选择器精确提取结构化数据。
import asyncio
import json
from crawl4ai import AsyncWebCrawler
from crawl4ai.extraction_strategy import JsonCssExtractionStrategy
async def extract_news_teasers():
schema = {
"name": "News Teaser Extractor",
"baseSelector": ".wide-tease-item__wrapper",
"fields": [
{"name": "category", "selector": ".unibrow span[data-testid='unibrow-text']", "type": "text"},
{"name": "headline", "selector": ".wide-tease-item__headline", "type": "text"},
{"name": "summary", "selector": ".wide-tease-item__description", "type": "text"},
{"name": "time", "selector": "[data-testid='wide-tease-date']", "type": "text"},
{
"name": "image",
"type": "nested",
"selector": "picture.teasePicture img",
"fields": [
{"name": "src", "type": "attribute", "attribute": "src"},
{"name": "alt", "type": "attribute", "attribute": "alt"},
],
},
{"name": "link", "selector": "a[href]", "type": "attribute", "attribute": "href"},
],
}
extraction_strategy = JsonCssExtractionStrategy(schema, verbose=True)
async with AsyncWebCrawler(verbose=True) as crawler:
result = await crawler.arun(
url="https://www.nbcnews.com/business",
extraction_strategy=extraction_strategy,
bypass_cache=True,
)
assert result.success, "Failed to crawl the page"
news_teasers = json.loads(result.extracted_content)
print(f"Successfully extracted {len(news_teasers)} news teasers")
print(json.dumps(news_teasers[0], indent=2))
if __name__ == "__main__":
asyncio.run(extract_news_teasers())
利用OpenAI提取结构化数据
利用OpenAI的能力动态提取和结构化数据。
import os
import asyncio
from crawl4ai import AsyncWebCrawler
from crawl4ai.extraction_strategy import LLMExtractionStrategy
from pydantic import BaseModel, Field
class OpenAIModelFee(BaseModel):
model_name: str = Field(..., description="OpenAI 模型的名称。")
input_fee: str = Field(..., description="OpenAI 模型的输入令牌费用。")
output_fee: str = Field(..., description="OpenAI 模型的输出令牌费用。")
async def main():
async with AsyncWebCrawler(verbose=True) as crawler:
result = await crawler.arun(
url='https://openai.com/api/pricing/',
word_count_threshold=1,
extraction_strategy=LLMExtractionStrategy(
provider="openai/gpt-4o",
api_token=os.getenv('OPENAI_API_KEY'),
schema=OpenAIModelFee.schema(),
extraction_type="schema",
instruction="""从爬取的内容中提取所有提到的模型名称以及它们的输入和输出令牌费用。
不要错过整个内容中的任何模型。提取的模型 JSON 格式应如下所示:
{"model_name": "GPT-4", "input_fee": "US$10.00 / 1M tokens", "output_fee": "US$30.00 / 1M tokens"}。"""
),
bypass_cache=True,
)
print(result.extracted_content)
if __name__ == "__main__":
asyncio.run(main())
``````python
import asyncio
import re
from bs4 import BeautifulSoup
from crawl4ai import AsyncWebCrawler
async def crawl_typescript_commits():
first_commit = ""
async def on_execution_started(page):
nonlocal first_commit
try:
while True:
await page.wait_for_selector('li.Box-sc-g0xbh4-0 h4')
commit = await page.query_selector('li.Box-sc-g0xbh4-0 h4')
commit = await commit.evaluate('(element) => element.textContent')
commit = re.sub(r'\s+', '', commit)
if commit and commit != first_commit:
first_commit = commit
break
await asyncio.sleep(0.5)
except Exception as e:
print(f"Warning: New content didn't appear after JavaScript execution: {e}")
async with AsyncWebCrawler(verbose=True) as crawler:
crawler.crawler_strategy.set_hook('on_execution_started', on_execution_started)
url = "https://github.com/microsoft/TypeScript/commits/main"
session_id = "typescript_commits_session"
all_commits = []
js_next_page = """
const button = document.querySelector('a[data-testid="pagination-next-button"]');
if (button) button.click();
"""
for page in range(3): # Crawl 3 pages
result = await crawler.arun(
url=url,
session_id=session_id,
css_selector="li.Box-sc-g0xbh4-0",
js=js_next_page if page > 0 else None,
bypass_cache=True,
js_only=page > 0
)
assert result.success, f"Failed to crawl page {page + 1}"
soup = BeautifulSoup(result.cleaned_html, 'html.parser')
commits = soup.select("li.Box-sc-g0xbh4-0")
all_commits.extend(commits)
print(f"Page {page + 1}: Found {len(commits)} commits")
await crawler.crawler_strategy.kill_session(session_id)
print(f"Successfully crawled {len(all_commits)} commits across 3 pages")
if __name__ == "__main__":
asyncio.run(crawl_typescript_commits())
速度比较 🚀
Crawl4AI 专为速度和效率而设计,始终优于许多付费服务。以下是我们的性能基准的一瞥:
服务耗时内容长度发现的图片Firecrawl7.02 秒42,074 个字符49**Crawl4AI (简单爬取)1.60 秒18,238 个字符49Crawl4AI (带 JS 执行)**4.64 秒40,869 个字符89
要点:
-
简单爬取: Crawl4AI 比 Firecrawl 快 4 倍。
-
带 JavaScript 执行: 即使执行 JavaScript 来加载额外内容(图片数量翻倍),Crawl4AI 仍然比 Firecrawl 的简单爬取快得多。
要了解全面的比较,请查看我们在存储库中的 Crawl4AI vs. Firecrawl 示例。
参考资料
https://github.com/unclecode/crawl4ai