想用 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: 数据准确性如何保证?

  • 始终验证抓取的内容是否符合预期
  • 对于关键数据,建议人工审核
  • 定期重新抓取以确保数据新鲜度

最佳实践总结

  1. 始终使用环境变量存储 API Key,不要硬编码
  2. 实现缓存机制,避免重复抓取相同内容
  3. 设置合理的爬取限制,尊重目标网站的 robots.txt
  4. 监控 API 使用量,避免超出额度
  5. 错误处理要完善,网络请求可能随时失败
  6. 定期更新知识库,确保数据新鲜度
  7. 遵守目标网站的使用条款,不要抓取禁止的内容

结语

Firecrawl 让网页数据抓取变得前所未有的简单。通过本文的学习,你应该能够:

  • 理解 Firecrawl 的核心功能和使用场景
  • 快速上手抓取单个页面和整个网站
  • 构建完整的 RAG 知识库应用
  • 优化抓取性能和处理常见问题

现在,开始用 Firecrawl 为你的 AI 应用注入高质量的网页数据吧!


参考资源:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注