CrawlForge
首页Playground应用场景集成价格文档博客
LlamaIndex web scraping 指南:搭配 CrawlForge MCP
Tutorials
返回博客
教程

LlamaIndex web scraping 指南:搭配 CrawlForge MCP

C
CrawlForge Team
工程团队
2026年4月14日
阅读时长 11 分钟

本页内容

LlamaIndex 是生产级 RAG 的首选框架,但它自带的 HTML 读取器在重 JavaScript 的站点和受 Cloudflare 保护的页面上会崩溃。把它们换成 CrawlForge,你的 LlamaIndex pipeline 就能处理任何 URL —— 静态 HTML、SPA 或反爬虫墙。

Python
from llama_index.core import Document
from crawlforge_llamaindex import CrawlForgeReader

reader = CrawlForgeReader(api_key="cf_live_your_key")
docs: list[Document] = reader.load_data(urls=["https://docs.stripe.com/api"])

本指南展示如何以 CrawlForge 作为数据源来进行 LlamaIndex web scraping —— 从单页加载器到完整的 RAG pipeline 和 agent 工具。

目录

  • 为什么 LlamaIndex 需要更好的网页读取器
  • 前置条件
  • 步骤 1:安装依赖
  • 步骤 2:构建一个 CrawlForge 读取器
  • 步骤 3:索引实时网页
  • 步骤 4:查询索引
  • 完整示例:带实时更新的文档 RAG
  • 进阶:为 LlamaIndex agent 提供 CrawlForge 工具
  • 故障排查
  • 常见问题

为什么 LlamaIndex 需要更好的网页读取器

LlamaIndex 内置的 SimpleWebPageReader 和 BeautifulSoupWebReader 处理静态博客文章没问题,但在以下情况会失败:

  • 由 JavaScript 渲染的内容(React、Vue、Angular 应用)
  • 受 Cloudflare / DataDome / Akamai 保护的页面(大多数 SaaS 文档)
  • 对通用 User-Agent 返回 403 的站点
  • 主要内容位于某个 <main> 同级元素中、无法轻易提取的页面

CrawlForge 解决了这全部四种情况。它的 extract_content 工具使用了针对文章、文档和产品页面调优的可读性算法。stealth_mode 应对反爬虫。scrape_with_actions 执行 JavaScript。全部 26 个工具都返回干净的文本或 markdown,可直接用于分块。要了解这在 RAG 中为何重要,请参阅我们的 RAG pipeline 指南。

前置条件

  • Python 3.9+ -- python --version
  • LlamaIndex -- pip install llama-index-core llama-index-readers-web
  • CrawlForge 账户 —— 在 crawlforge.dev/signup 免费注册,含 1,000 credits
  • OpenAI 或 Anthropic API key,用于 LlamaIndex 的 LLM 调用(或使用任何受支持的提供商)

步骤 1:安装依赖

Bash
pip install llama-index-core llama-index-embeddings-openai requests

导出你的密钥:

Bash
export CRAWLFORGE_API_KEY="cf_live_your_key_here"
export OPENAI_API_KEY="sk-..."

步骤 2:构建一个 CrawlForge 读取器

LlamaIndex 读取器继承自 BaseReader 并返回 Document 对象。下面是一个封装了 CrawlForge extract_content endpoint 的最小读取器:

Python
# crawlforge_reader.py
import os
from typing import List, Optional
import requests
from llama_index.core.readers.base import BaseReader
from llama_index.core.schema import Document


class CrawlForgeReader(BaseReader):
    """LlamaIndex reader that uses CrawlForge for web scraping."""

    BASE_URL = "https://crawlforge.dev/api/v1/tools"

    def __init__(self, api_key: Optional[str] = None, use_stealth: bool = False):
        self.api_key = api_key or os.environ["CRAWLFORGE_API_KEY"]
        self.use_stealth = use_stealth

    def load_data(self, urls: List[str]) -> List[Document]:
        documents = []
        tool = "stealth_mode" if self.use_stealth else "extract_content"

        for url in urls:
            response = requests.post(
                f"{self.BASE_URL}/{tool}",
                headers={
                    "Authorization": f"Bearer {self.api_key}",
                    "Content-Type": "application/json",
                },
                json={
                    "url": url,
                    "options": {"format": "markdown"},
                },
                timeout=30,
            )
            response.raise_for_status()
            data = response.json()

            documents.append(
                Document(
                    text=data.get("content", ""),
                    metadata={
                        "source": url,
                        "title": data.get("title"),
                        "scraped_at": data.get("scraped_at"),
                    },
                )
            )

        return documents

费用:使用 extract_content 每个 URL 2 credits,使用 stealth_mode 为 5 credits。

步骤 3:索引实时网页

把读取器接入标准的 LlamaIndex pipeline:

Python
# build_index.py
from llama_index.core import VectorStoreIndex
from crawlforge_reader import CrawlForgeReader

reader = CrawlForgeReader()
docs = reader.load_data(urls=[
    "https://docs.stripe.com/api/charges/create",
    "https://docs.stripe.com/api/payment_intents/create",
    "https://docs.stripe.com/api/refunds/create",
])

index = VectorStoreIndex.from_documents(docs)
index.storage_context.persist(persist_dir="./storage/stripe_docs")

现在你就有了一个由实时文档构建、并持久化的 Stripe API 索引。费用:6 credits(3 个 URL x 2)。

步骤 4:查询索引

Python
# query_index.py
from llama_index.core import StorageContext, load_index_from_storage

storage = StorageContext.from_defaults(persist_dir="./storage/stripe_docs")
index = load_index_from_storage(storage)

query_engine = index.as_query_engine()
response = query_engine.query(
    "What are the required fields to create a Charge in Stripe's API?"
)
print(response)
# -> "To create a Charge, you must provide amount (integer in cents) and
#     currency (three-letter ISO code). Additionally you need a source
#     (payment method) or customer."

完整示例:带实时更新的文档 RAG

把它们组合起来 —— 一个每晚刷新的 Stripe 文档 RAG:

Python
# docs_rag.py
import os
from datetime import datetime
from llama_index.core import VectorStoreIndex, StorageContext, load_index_from_storage
from crawlforge_reader import CrawlForgeReader

PERSIST_DIR = "./storage/stripe_docs"
TARGET_URLS = [
    "https://docs.stripe.com/api/charges/create",
    "https://docs.stripe.com/api/payment_intents/create",
    "https://docs.stripe.com/api/refunds/create",
    "https://docs.stripe.com/api/customers/create",
    "https://docs.stripe.com/api/subscriptions/create",
]


def refresh_index() -> VectorStoreIndex:
    """Re-scrape sources and rebuild the index."""
    reader = CrawlForgeReader()
    docs = reader.load_data(urls=TARGET_URLS)
    index = VectorStoreIndex.from_documents(docs)
    index.storage_context.persist(persist_dir=PERSIST_DIR)
    print(f"Indexed {len(docs)} docs at {datetime.utcnow().isoformat()}Z")
    return index


def load_index() -> VectorStoreIndex:
    """Load the persisted index from disk."""
    storage = StorageContext.from_defaults(persist_dir=PERSIST_DIR)
    return load_index_from_storage(storage)


def ask(question: str) -> str:
    index = load_index() if os.path.exists(PERSIST_DIR) else refresh_index()
    return str(index.as_query_engine().query(question))


if __name__ == "__main__":
    # Refresh once a day in a cron job: python docs_rag.py --refresh
    import sys
    if "--refresh" in sys.argv:
        refresh_index()
    else:
        print(ask("How do I create a refund for a charge?"))

每晚刷新费用:10 credits(5 个 URL x 2)。30 天下来是 300 credits —— 远在免费套餐范围之内。

进阶:为 LlamaIndex agent 提供 CrawlForge 工具

LlamaIndex 的 agent 系统接受任意的 FunctionTool 定义。把 CrawlForge 调用封装成工具,你的 agent 就能按需 scraping:

Python
# crawlforge_tools.py
from llama_index.core.tools import FunctionTool
from crawlforge_reader import CrawlForgeReader


def scrape_url(url: str) -> str:
    """Scrape a URL and return its main content as markdown."""
    reader = CrawlForgeReader()
    docs = reader.load_data(urls=[url])
    return docs[0].text if docs else ""


def search_and_scrape(query: str, n: int = 3) -> list[str]:
    """Search the web and return content from the top N results."""
    import os, requests
    resp = requests.post(
        "https://crawlforge.dev/api/v1/tools/search_web",
        headers={"Authorization": f"Bearer {os.environ['CRAWLFORGE_API_KEY']}"},
        json={"query": query, "limit": n},
        timeout=30,
    ).json()
    urls = [r["url"] for r in resp.get("results", [])]
    reader = CrawlForgeReader()
    return [d.text for d in reader.load_data(urls=urls)]


scrape_tool = FunctionTool.from_defaults(fn=scrape_url)
search_tool = FunctionTool.from_defaults(fn=search_and_scrape)

然后把 [scrape_tool, search_tool] 传给任何 LlamaIndex agent:

Python
from llama_index.core.agent import ReActAgent
from llama_index.llms.openai import OpenAI

agent = ReActAgent.from_tools(
    tools=[scrape_tool, search_tool],
    llm=OpenAI(model="gpt-4o-mini"),
    verbose=True,
)

response = agent.chat(
    "Research the current state of Anthropic's MCP protocol adoption in 2026. "
    "Cite at least 3 sources."
)
print(response)

credits 费用明细

操作工具Credits
摄取一个静态页面extract_content2
摄取一个重 JS 的页面scrape_with_actions5
摄取一个受 Cloudflare 保护的页面stealth_mode5
agent 搜索 + scraping(3 个 URL)search_web + 3x extract_content11
完整深度研究deep_research10

故障排查

某些 URL 的 Document.text 为空 —— 该页面很可能需要 JavaScript。用 use_stealth=True 实例化,或构建一个调用 scrape_with_actions 的读取器变体。

requests.exceptions.HTTPError: 429 —— 你触发了 CrawlForge 的速率限制。添加带退避的重试,或将批量加载拆分为每批 10 个 URL。

LlamaIndex 索引很慢 —— 用 concurrent.futures.ThreadPoolExecutor 批量并发执行你的读取器调用(这是 I/O 密集型,GIL 不是瓶颈)。在 50 个以上 URL 上通常能获得 10 倍提速。

Document 元数据缺失 —— CrawlForge 的 scrape_structured endpoint 不会像 extract_content 那样填充 title。RAG 摄取请坚持使用 extract_content;仅在做带类型的字段提取时才使用 scrape_structured。

embedding 成本暴涨 —— LlamaIndex 在每次调用 VectorStoreIndex.from_documents 时都会重新生成 embedding。用 index.storage_context.persist() 持久化,并用 load_index_from_storage() 加载,以避免重复工作。

下一步

  • 阅读 RAG pipeline 指南,了解端到端的检索模式
  • 在我们的 LangChain 集成文章中探索其他框架
  • 查看入门文档,了解完整的 REST API
  • 在 Firecrawl 替代方案中对比各家 scraping 供应商

在 crawlforge.dev/signup 免费开始,赠送 1,000 credits。无需信用卡。

亲自试一试——无需注册

在 Playground 中运行 CrawlForge 的 27 个抓取与提取工具中的任意一个,然后免费开始,获取 1,000 credits。

1,000 免费 credits • 每月补充 • 无需信用卡

标签

LlamaIndexweb-scrapingRAGPythontutorialvector-searchAI-agents

关于作者

C

CrawlForge Team

工程团队

我们正在打造功能最全面的 Web 抓取 MCP server。我们开发的工具帮助开发者为 AI 应用提取、分析和转换 Web 数据。

及时获取最新洞察

将教程、产品更新与 Web 抓取技巧直接发送到你的收件箱。

拒绝垃圾邮件,随时可取消订阅。

付诸实践

在任意 URL 上测试 CrawlForge 的工具——免费,无需注册。

本页内容

Frequently Asked Questions

为什么不直接用 LlamaIndex 内置的网页读取器?+

SimpleWebPageReader 和 BeautifulSoupWebReader 适用于静态博客文章,但在由 JavaScript 渲染的页面、受 Cloudflare 保护的文档,以及对通用客户端返回 403 的站点上会失败。CrawlForge 用 extract_content(可读性)、scrape_with_actions(JS 执行)和 stealth_mode(反爬虫)解决了这全部三种情况。

用 CrawlForge + LlamaIndex 索引 100 个页面要花多少钱?+

通过 extract_content 处理静态页面每个花费 2 credits,因此 100 个页面 = 200 credits。受 Cloudflare 保护或重 JS 的页面每个花费 5 credits(100 个为 500 credits)。对于一次性的索引构建,两者都在 1,000 credits 的免费套餐范围之内。

CrawlForge 能充当 LlamaIndex 的 agent 工具吗?+

可以。把任何 CrawlForge API 调用封装进一个 LlamaIndex FunctionTool,并将其注册到 ReActAgent 或 OpenAIAgent。agent 会根据用户查询决定何时 scraping 一个 URL 或执行一次网页搜索。可工作的代码请见上文的 agent 一节。

CrawlForge 支持 HyDE 等 LlamaIndex 查询变换吗?+

CrawlForge 是一个数据源,而不是检索层。查询变换发生在摄取之后的 LlamaIndex 内部。CrawlForge 返回干净的 markdown 或结构化数据来喂给 VectorStoreIndex —— 下游的一切(HyDE、多步推理、SubQuestionQueryEngine)都无需改动即可工作。

我该如何用实时网页数据保持 LlamaIndex 索引的新鲜度?+

安排一个每日 cron,在同一份 URL 列表上重新运行你的 CrawlForgeReader,并通过 VectorStoreIndex.from_documents 重建索引。由于 CrawlForge 返回干净的 markdown,文档每次的形态都相同,因此 embedding 是稳定的。对于增量更新,可使用 LlamaIndex 的 upsert API,并采用从 URL 派生的文档 ID。

相关文章

如何用 Claude Code 抓取网站(2026 指南)
Tutorials

如何用 Claude Code 抓取网站(2026 指南)

用 Claude Code 和 CrawlForge MCP 从你的终端抓取任何网站。抓取页面、提取数据并绕过反爬虫,全程不到 2 分钟。

C
CrawlForge Team
|
4月14日
|
10 分钟
如何在 Cursor IDE 中使用 CrawlForge MCP 抓取网站
Tutorials

如何在 Cursor IDE 中使用 CrawlForge MCP 抓取网站

把 Cursor IDE 变成网页抓取工作站。接入 CrawlForge MCP,无需离开编辑器即可从任意站点提取结构化数据。

C
CrawlForge Team
|
4月14日
|
9 分钟
如何在 Zed AI 中使用 CrawlForge MCP 进行网页抓取
Tutorials

如何在 Zed AI 中使用 CrawlForge MCP 进行网页抓取

3 分钟为 Zed AI 添加 web scraping 能力。在 Zed 中配置 CrawlForge MCP,让你的编辑器按需抓取、提取并研究实时网页数据。

C
CrawlForge Team
|
4月14日
|
9 分钟

页脚

CrawlForge

面向 AI Agent 的企业级网页抓取。27 个专业 MCP 工具,专为构建智能系统的现代开发者而设计。

产品

  • 功能
  • Playground
  • 价格
  • 应用场景
  • 集成
  • 替代方案
  • 更新日志

资源

  • 快速上手
  • API 参考
  • 模板
  • 指南
  • 博客
  • 术语表
  • 常见问题
  • 网站地图

开发者

  • MCP 协议
  • Claude Desktop
  • Cursor IDE
  • LangChain
  • LlamaIndex

公司

  • 关于我们
  • 联系我们
  • 隐私政策
  • 服务条款
  • 可接受使用政策
  • Cookie

保持更新

获取新工具和新功能的最新动态。

基于 Next.js 和 MCP 协议构建

© 2025-2026 CrawlForge。保留所有权利。