想用 AI 分析网页内容但不知道如何获取数据?Firecrawl 帮你把任何网站转换成 LLM -ready 的 Markdown 格式,让 RAG 应用开发变得前所未有的简单。
在构建基于大语言模型(LLM)的应用时,一个常见的需求是从网页获取高质量的结构化数据。无论是构建知识库问答系统、竞品分析工具,还是内容聚合平台,你都需要一种可靠的方式来抓取和转换网页内容。
这就是 Firecrawl 诞生的原因。
什么是 Firecrawl?
Firecrawl 是一个专为 AI 应用设计的网页抓取 API 服务。它的核心功能是将任何 URL 转换成干净、结构化的 Markdown 格式,可以直接喂给大语言模型使用。
核心特点
- LLM-ready 输出:直接输出 Markdown 格式,无需额外清洗
- 智能内容提取:自动识别并提取主要内容,过滤导航、广告等噪音
- 支持动态渲染:可以处理 JavaScript 渲染的单页应用(SPA)
- 批量抓取:支持爬取整个网站的所有页面
- API 优先设计:简单的 REST API,支持多种编程语言 SDK
- 内置重试机制:自动处理网络错误和反爬机制
与传统爬虫的区别
| 特性 | 传统爬虫 (Scrapy/BeautifulSoup) | Firecrawl |
|---|---|---|
| 输出格式 | HTML,需要手动解析 | 干净的 Markdown |
| JavaScript 支持 | 需要额外配置 (Selenium/Puppeteer) | 原生支持 |
| 内容清洗 | 手动编写规则 | 自动智能提取 |
| 反爬处理 | 需要自己处理 | 内置处理 |
| 开发时间 | 数小时到数天 | 几分钟 |
安装与配置
获取 API Key
首先访问 Firecrawl 官网 注册账号。新用户可以获得免费额度用于测试。
注册后,在 Dashboard 中找到你的 API Key,类似这样:
fc-YOUR_API_KEY_HERE
安装 SDK
Firecrawl 提供了多种语言的 SDK。以下是常用语言的安装方法:
Python:
pip install firecrawl-py
Node.js:
npm install @mendable/firecrawl-js
其他语言支持:
- Go:
go get github.com/mendableai/firecrawl-go - Rust:
cargo add firecrawl-rs - PHP:
composer require mendable/firecrawl-php
环境配置
建议将 API Key 存储在环境变量中,而不是硬编码在代码里:
# Linux/Mac export FIRECRAWL_API_KEY="fc-YOUR_API_KEY_HERE" # Windows PowerShell $env:FIRECRAWL_API_KEY="fc-YOUR_API_KEY_HERE"
基础使用:抓取单个页面
Python 示例
让我们从一个简单的例子开始,抓取一个技术博客文章:
from firecrawl import FirecrawlApp
import os
# 初始化客户端
app = FirecrawlApp(api_key=os.getenv('FIRECRAWL_API_KEY'))
# 抓取单个页面
url = 'https://example.com/blog/ai-trends-2026'
response = app.scrape_url(url)
# 输出结果
print(f"标题:{response['metadata']['title']}")
print(f"内容长度:{len(response['markdown'])} 字符")
print(f"前 500 字符预览:\n{response['markdown'][:500]}")
Node.js 示例
import FirecrawlApp from '@mendable/firecrawl-js';
const app = new FirecrawlApp({
apiKey: process.env.FIRECRAWL_API_KEY
});
const response = await app.scrapeUrl('https://example.com/blog/ai-trends-2026');
console.log('标题:', response.metadata.title);
console.log('内容:', response.markdown.substring(0, 500));
响应结构解析
Firecrawl 的响应包含以下关键字段:
{
"success": true,
"markdown": "# 文章标题\n\n文章内容...",
"html": "<h1>文章标题</h1><p>文章内容...</p>",
"metadata": {
"title": "文章标题",
"description": "文章描述",
"language": "zh-CN",
"sourceURL": "https://example.com/blog/ai-trends-2026",
"ogTitle": "OG 标题",
"ogDescription": "OG 描述"
},
"links": ["https://example.com/link1", ...],
"actions": null
}
进阶功能:爬取整个网站
Firecrawl 最强大的功能之一是能够自动爬取整个网站的所有页面。
基础爬取
from firecrawl import FirecrawlApp
app = FirecrawlApp(api_key='fc-YOUR_API_KEY')
# 爬取整个网站
crawl_response = app.crawl_url(
'https://example.com',
params={
'limit': 100, # 最多抓取 100 个页面
'scrapeOptions': {
'formats': ['markdown', 'html']
}
}
)
print(f"抓取完成,共 {len(crawl_response['data'])} 个页面")
# 处理每个页面
for page in crawl_response['data']:
print(f"页面:{page['metadata']['title']}")
print(f"内容:{page['markdown'][:200]}...")
高级爬取选项
crawl_response = app.crawl_url(
'https://docs.example.com',
params={
'limit': 500,
'maxDepth': 3, # 最大爬取深度
'ignoreSitemap': False, # 使用 sitemap
'includePaths': ['/docs/*'], # 只包含特定路径
'excludePaths': ['/docs/api/v1/*'], # 排除特定路径
'scrapeOptions': {
'formats': ['markdown'],
'onlyMainContent': True, # 只抓取主要内容
'waitFor': 2000 # 等待 JS 渲染时间 (毫秒)
}
}
)
实战案例:构建 RAG 知识库
让我们用一个完整的例子展示如何用 Firecrawl 构建一个 RAG(检索增强生成)应用的知识库。
场景描述
假设我们要构建一个”AI 工具知识库问答机器人”,需要从多个 AI 工具官网抓取文档内容。
步骤 1:定义目标网站列表
target_sites = [
'https://docs.anthropic.com',
'https://platform.openai.com/docs',
'https://docs.langchain.com',
'https://docs.llamaindex.ai'
]
步骤 2:抓取并存储数据
import json
from datetime import datetime
def build_knowledge_base(urls, output_file='knowledge_base.json'):
app = FirecrawlApp(api_key=os.getenv('FIRECRAWL_API_KEY'))
knowledge_base = {
'created_at': datetime.now().isoformat(),
'sources': [],
'documents': []
}
for url in urls:
print(f"正在抓取:{url}")
try:
response = app.crawl_url(
url,
params={
'limit': 50,
'scrapeOptions': {
'formats': ['markdown'],
'onlyMainContent': True
}
}
)
# 记录源信息
knowledge_base['sources'].append({
'url': url,
'pages_count': len(response['data']),
'crawl_date': datetime.now().isoformat()
})
# 存储每个页面的数据
for page in response['data']:
knowledge_base['documents'].append({
'url': page['metadata']['sourceURL'],
'title': page['metadata'].get('title', 'Untitled'),
'content': page['markdown'],
'description': page['metadata'].get('description', '')
})
print(f"✓ 完成,共 {len(response['data'])} 个页面")
except Exception as e:
print(f"✗ 抓取失败:{e}")
# 保存到文件
with open(output_file, 'w', encoding='utf-8') as f:
json.dump(knowledge_base, f, ensure_ascii=False, indent=2)
print(f"\n知识库已保存到:{output_file}")
print(f"总计:{len(knowledge_base['documents'])} 个文档")
return knowledge_base
# 执行
kb = build_knowledge_base(target_sites)
步骤 3:与向量数据库集成
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
def index_documents(knowledge_base, collection_name='ai_tools_kb'):
# 文本分块
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
documents = []
for doc in knowledge_base['documents']:
chunks = text_splitter.split_text(doc['content'])
for chunk in chunks:
documents.append({
'text': chunk,
'metadata': {
'source': doc['url'],
'title': doc['title']
}
})
# 创建向量存储
embeddings = OpenAIEmbeddings()
# 提取文本和元数据
texts = [doc['text'] for doc in documents]
metadatas = [doc['metadata'] for doc in documents]
# 存储到 Chroma
vectorstore = Chroma.from_texts(
texts=texts,
embedding=embeddings,
metadatas=metadatas,
collection_name=collection_name
)
print(f"已索引 {len(texts)} 个文本块到向量数据库")
return vectorstore
# 执行索引
vs = index_documents(kb)
步骤 4:构建问答链
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA
def create_qa_chain(vectorstore):
llm = ChatOpenAI(
model_name='gpt-4',
temperature=0
)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type='stuff',
retriever=vectorstore.as_retriever(search_kwargs={'k': 3}),
return_source_documents=True
)
return qa_chain
# 使用示例
qa = create_qa_chain(vs)
query = "如何调用 Anthropic 的 API?"
result = qa(query)
print(f"问题:{query}")
print(f"答案:{result['result']}")
print(f"参考来源:")
for doc in result['source_documents']:
print(f" - {doc.metadata['title']}: {doc.metadata['source']}")
性能优化技巧
1. 使用缓存避免重复抓取
import hashlib
import pickle
from pathlib import Path
class CachedFirecrawl:
def __init__(self, api_key, cache_dir='.firecrawl_cache'):
self.app = FirecrawlApp(api_key=api_key)
self.cache_dir = Path(cache_dir)
self.cache_dir.mkdir(exist_ok=True)
def _get_cache_key(self, url):
return hashlib.md5(url.encode()).hexdigest()
def scrape_url(self, url, use_cache=True):
cache_key = self._get_cache_key(url)
cache_file = self.cache_dir / f"{cache_key}.pkl"
if use_cache and cache_file.exists():
with open(cache_file, 'rb') as f:
return pickle.load(f)
result = self.app.scrape_url(url)
with open(cache_file, 'wb') as f:
pickle.dump(result, f)
return result
# 使用
cached_app = CachedFirecrawl(api_key='fc-YOUR_API_KEY')
2. 并发抓取提高效率
from concurrent.futures import ThreadPoolExecutor, as_completed
def scrape_multiple_urls(urls, max_workers=5):
app = FirecrawlApp(api_key=os.getenv('FIRECRAWL_API_KEY'))
results = []
def scrape_single(url):
try:
return {'url': url, 'data': app.scrape_url(url), 'success': True}
except Exception as e:
return {'url': url, 'error': str(e), 'success': False}
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {executor.submit(scrape_single, url): url for url in urls}
for future in as_completed(futures):
result = future.result()
results.append(result)
status = '✓' if result['success'] else '✗'
print(f"{status} {result['url']}")
return results
3. 设置合理的请求限制
import time
from datetime import datetime, timedelta
class RateLimitedFirecrawl:
def __init__(self, api_key, requests_per_minute=60):
self.app = FirecrawlApp(api_key=api_key)
self.min_interval = 60 / requests_per_minute
self.last_request = datetime.min
def scrape_url(self, url):
# 等待到允许请求的时间
elapsed = (datetime.now() - self.last_request).total_seconds()
if elapsed < self.min_interval:
time.sleep(self.min_interval - elapsed)
result = self.app.scrape_url(url)
self.last_request = datetime.now()
return result
常见问题解答
Q1: Firecrawl 的免费额度够用吗?
新用户通常有 500-1000 个页面的免费额度。对于个人项目和学习来说足够使用。生产环境建议升级到付费计划。
Q2: 如何处理登录后的页面?
Firecrawl 支持设置 Cookie 和自定义请求头:
response = app.scrape_url(
'https://example.com/dashboard',
params={
'scrapeOptions': {
'headers': {
'Cookie': 'session=your_session_token'
}
}
}
)
Q3: 抓取速度慢怎么办?
- 使用并发抓取(见上文优化技巧)
- 减少
waitFor等待时间 - 设置
onlyMainContent: true减少处理时间 - 考虑升级到更高等级的 API 计划
Q4: 如何处理反爬机制?
Firecrawl 内置了反反爬机制,但如果你遇到封禁:
- 降低请求频率
- 使用
excludePaths避免敏感路径 - 联系 Firecrawl 支持团队获取帮助
Q5: 数据准确性如何保证?
- 始终验证抓取的内容是否符合预期
- 对于关键数据,建议人工审核
- 定期重新抓取以确保数据新鲜度
最佳实践总结
- 始终使用环境变量存储 API Key,不要硬编码
- 实现缓存机制,避免重复抓取相同内容
- 设置合理的爬取限制,尊重目标网站的 robots.txt
- 监控 API 使用量,避免超出额度
- 错误处理要完善,网络请求可能随时失败
- 定期更新知识库,确保数据新鲜度
- 遵守目标网站的使用条款,不要抓取禁止的内容
结语
Firecrawl 让网页数据抓取变得前所未有的简单。通过本文的学习,你应该能够:
- 理解 Firecrawl 的核心功能和使用场景
- 快速上手抓取单个页面和整个网站
- 构建完整的 RAG 知识库应用
- 优化抓取性能和处理常见问题
现在,开始用 Firecrawl 为你的 AI 应用注入高质量的网页数据吧!
参考资源:
