Skip to main content
本指南展示如何将 Apify 与 LangChain 结合使用,以从 Apify 数据集加载文档。

概述

Apify 是一个用于网络爬虫和数据提取的云平台,它提供了一个包含超过 10,000 个现成应用的生态系统,这些应用称为 Actors,适用于各种网络爬虫、抓取和数据提取用例。 本指南展示如何从 Apify 数据集 加载文档:这是一个可扩展的追加存储,专为存储结构化网络爬虫结果而构建,例如产品列表或 Google SERP,然后将其导出为 JSON、CSV 或 Excel 等各种格式。 数据集通常用于保存不同 Actors 的结果。例如:
  • 网站内容爬虫 Actor 深度爬取网站,如文档、知识库、帮助中心或博客,并将网页的文本内容存储到数据集中
  • RAG 网络浏览器 Actor 查询 Google 搜索,从结果中抓取前 N 个页面,并返回清理后的内容(Markdown 格式),供大型语言模型进一步处理

集成详情

加载器特性

来源文档延迟加载原生异步支持
Apify 数据集

设置

凭证

您需要注册一个 Apify 账户 并获取您的 Apify API 令牌。将其设置为环境变量:
process.env.APIFY_TOKEN = "your-apify-token"

安装

您首先需要安装官方的 Apify 客户端和 LangChain 包:
npm
npm install apify-client @langchain/community @langchain/core @langchain/openai hnswlib-node

定价

许多 Actors 支持按事件付费 (PPE) 定价,您需要为 Actor 作者定义的明确事件付费(例如,按数据集项付费)。 这对于您希望明确每个操作成本的代理工作负载来说是一个很好的选择。 Apify 还提供按使用付费的定价,并提供免费层级。 定价因 Actor 而异——有些 Actor 是免费的(您只需支付平台使用费),而其他 Actor 则按结果或事件收费。有关详细信息,请参阅 Apify 定价

用法

从新数据集(爬取网站并将数据存储在 Apify 数据集中)

如果您在 Apify 平台上还没有现有数据集,则需要通过调用 Actor 并等待结果来初始化文档加载器。 在下面的示例中,我们使用 网站内容爬虫 Actor 来爬取 LangChain 文档,将结果存储在 Apify 数据集中,然后使用 ApifyDatasetLoader 加载数据集。 在此演示中,我们将使用快速的 Cheerio 爬虫类型,并将爬取的页面数量限制为 10。 注意: 运行网站内容爬虫可能需要一些时间,具体取决于网站的大小。对于大型网站,可能需要几个小时甚至几天! 以下是一个示例:
import { ApifyDatasetLoader } from "@langchain/community/document_loaders/web/apify_dataset";
import { HNSWLib } from "@langchain/community/vectorstores/hnswlib";
import { OpenAIEmbeddings, ChatOpenAI } from "@langchain/openai";
import { Document } from "@langchain/core/documents";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { createStuffDocumentsChain } from "@langchain/classic/chains/combine_documents";
import { createRetrievalChain } from "@langchain/classic/chains/retrieval";

const APIFY_TOKEN = "YOUR-APIFY-TOKEN"; // 或设置为 process.env.APIFY_TOKEN
const OPENAI_API_KEY = "YOUR-OPENAI-API-KEY"; // 或设置为 process.env.OPENAI_API_KEY

/*
 * datasetMappingFunction 是一个函数,用于将您的 Apify 数据集格式映射到 LangChain 文档。
 * 在下面的示例中,Apify 数据集格式如下所示:
 * {
 *   "url": "https://apify.com",
 *   "text": "Apify is the best web scraping and automation platform."
 * }
 */
const loader = await ApifyDatasetLoader.fromActorCall(
  "apify/website-content-crawler",
  {
    maxCrawlPages: 10,
    crawlerType: "cheerio",
    startUrls: [{ url: "https://js.langchain.com/docs/" }],
  },
  {
    datasetMappingFunction: (item) =>
      new Document({
        pageContent: (item.text || "") as string,
        metadata: { source: item.url },
      }),
    clientOptions: {
      token: APIFY_TOKEN,
    },
  }
);

const docs = await loader.load();

const vectorStore = await HNSWLib.fromDocuments(
  docs,
  new OpenAIEmbeddings({ apiKey: OPENAI_API_KEY })
);

const model = new ChatOpenAI({
  model: "gpt-5-mini",
  temperature: 0,
  apiKey: OPENAI_API_KEY,
});

const questionAnsweringPrompt = ChatPromptTemplate.fromMessages([
  [
    "system",
    "Answer the user's questions based on the below context:\n\n{context}",
  ],
  ["human", "{input}"],
]);

const combineDocsChain = await createStuffDocumentsChain({
  llm: model,
  prompt: questionAnsweringPrompt,
});

const chain = await createRetrievalChain({
  retriever: vectorStore.asRetriever(),
  combineDocsChain,
});

const res = await chain.invoke({ input: "What is LangChain?" });

console.log(res.answer);
console.log(res.context.map((doc) => doc.metadata.source));

/*
  LangChain is a framework for developing applications powered by language models.
  [
    'https://js.langchain.com/docs/',
    'https://js.langchain.com/docs/modules/chains/',
    'https://js.langchain.com/docs/modules/chains/llmchain/',
    'https://js.langchain.com/docs/category/functions-4'
  ]
*/

何时使用 Apify

当您需要以下功能时,Apify 是理想的选择:
  • 访问数千个预构建的 Actors,适用于各种平台(社交媒体、电子商务、搜索引擎等)
  • 超越简单搜索的自定义网络爬虫和自动化工作流
  • 灵活的 Actor 生态系统:运行 Apify Store 中的任何 Actor

从现有数据集

如果您已经运行过 Actor 并且在 Apify 平台上拥有现有数据集,您可以直接使用构造函数初始化文档加载器
import { ApifyDatasetLoader } from "@langchain/community/document_loaders/web/apify_dataset";
import { HNSWLib } from "@langchain/community/vectorstores/hnswlib";
import { OpenAIEmbeddings, ChatOpenAI } from "@langchain/openai";
import { Document } from "@langchain/core/documents";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { createRetrievalChain } from "@langchain/classic/chains/retrieval";
import { createStuffDocumentsChain } from "@langchain/classic/chains/combine_documents";

const APIFY_TOKEN = "YOUR-APIFY-TOKEN"; // 或设置为 process.env.APIFY_TOKEN
const OPENAI_API_KEY = "YOUR-OPENAI-API-KEY"; // 或设置为 process.env.OPENAI_API_KEY

/*
 * datasetMappingFunction 是一个函数,用于将您的 Apify 数据集格式映射到 LangChain 文档。
 * 在下面的示例中,Apify 数据集格式如下所示:
 * {
 *   "url": "https://apify.com",
 *   "text": "Apify is the best web scraping and automation platform."
 * }
 */
const loader = new ApifyDatasetLoader("your-dataset-id", {
  datasetMappingFunction: (item) =>
    new Document({
      pageContent: (item.text || "") as string,
      metadata: { source: item.url },
    }),
  clientOptions: {
    token: APIFY_TOKEN,
  },
});

const docs = await loader.load();

const vectorStore = await HNSWLib.fromDocuments(
  docs,
  new OpenAIEmbeddings({ apiKey: OPENAI_API_KEY })
);

const model = new ChatOpenAI({
  model: "gpt-5-mini",
  temperature: 0,
  apiKey: OPENAI_API_KEY,
});

const questionAnsweringPrompt = ChatPromptTemplate.fromMessages([
  [
    "system",
    "Answer the user's questions based on the below context:\n\n{context}",
  ],
  ["human", "{input}"],
]);

const combineDocsChain = await createStuffDocumentsChain({
  llm: model,
  prompt: questionAnsweringPrompt,
});

const chain = await createRetrievalChain({
  retriever: vectorStore.asRetriever(),
  combineDocsChain,
});

const res = await chain.invoke({ input: "What is LangChain?" });

console.log(res.answer);
console.log(res.context.map((doc) => doc.metadata.source));

/*
  LangChain is a framework for developing applications powered by language models.
  [
    'https://js.langchain.com/docs/',
    'https://js.langchain.com/docs/modules/chains/',
    'https://js.langchain.com/docs/modules/chains/llmchain/',
    'https://js.langchain.com/docs/category/functions-4'
  ]
*/

其他 Actor 示例

Apify Store 包含数千个预构建的 Actors。以下是您可以与文档加载器一起使用的其他流行 Actors 示例:

Instagram Scraper

import { ApifyDatasetLoader } from "@langchain/community/document_loaders/web/apify_dataset";
import { Document } from "@langchain/core/documents";

const docs = await ApifyDatasetLoader.fromActorCall(
  "apify/instagram-scraper",
  {
    directUrls: ["https://www.instagram.com/p/ABC123/"],
    resultsType: "posts",
    resultsLimit: 10,
  },
  {
    datasetMappingFunction: (item) =>
      new Document({
        pageContent: item.caption || "",
        metadata: {
          source: item.url,
          likesCount: item.likesCount,
          commentsCount: item.commentsCount,
        },
      }),
    clientOptions: { token: process.env.APIFY_TOKEN },
  }
);

Google Search Results Scraper

import { ApifyDatasetLoader } from "@langchain/community/document_loaders/web/apify_dataset";
import { Document } from "@langchain/core/documents";

const searchDocs = await ApifyDatasetLoader.fromActorCall(
  "apify/google-search-scraper",
  {
    queries: "langchain javascript tutorial",
    maxPagesPerQuery: 1,
    countryCode: "us",
    languageCode: "en",
  },
  {
    datasetMappingFunction: (item) => {
      const organicResults = Array.isArray(item.organicResults)
        ? item.organicResults
        : [];

      const pageContent = organicResults
        .map(
          (r) =>
            `${r.position}. ${r.title}\n${r.url}\n${r.description ?? ""}`.trim()
        )
        .join("\n\n");

      return new Document({
        pageContent,
        metadata: {
          source: item.searchQuery?.url ?? item.url,
          query: item.searchQuery?.term,
          page: item.searchQuery?.page,
        },
      });
    },
    clientOptions: { token: process.env.APIFY_TOKEN },
  }
);
浏览 Apify Store 以发现更多适用于您用例的 Actors。

使用 Apify MCP 服务器

不确定使用哪个 Actor 或它需要什么参数? Apify MCP(模型上下文协议)服务器 可以帮助您发现可用的 Actors,探索其输入模式,并了解参数要求。 通过 HTTP 连接到 Apify MCP 服务器时,请在请求头中包含您的 Apify 令牌:
Authorization: Bearer <APIFY_TOKEN>
有关更多信息,请参阅 LangChain MCP 文档Apify MCP 服务器