CrawlForge MCP
中级指南

批量 处理指南

通过高效的队列管理、错误恢复和性能优化策略,将网页抓取扩展到数千个 URL。

使用 batch_scrape 工具
队列管理
错误恢复
性能优化

1. 使用 batch_scrape 工具

batch_scrape 工具在单次同步请求中最多并发抓取 50 个 URL。每个 URL 都会返回各自的状态,因此单个失效页面不会拖垮整批任务。

基础批量抓取

每个尝试的 URL 5 credits(50 个 URL = 250 credits)

Bash
curl -X POST https://crawlforge.dev/api/v1/tools/batch_scrape \
  -H "X-API-Key: cf_test_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": [
      { "url": "https://example.com/page1" },
      { "url": "https://example.com/page2" },
      { "url": "https://example.com/page3" }
    ],
    "batch_config": { "concurrency": 5 }
  }'
REST API 没有异步模式: 通过 HTTP 调用的 batch_scrape 是同步的——一次请求进入,完成的结果返回。没有可轮询的作业 id,也没有 webhook:batch_id 是 get_batch_results 的检索键,而不是作业句柄。超过 50 个 URL 时请按下文的方式分块。CrawlForge MCP 服务器则可以用 mode: 'async' 和可选的 webhook 在后台运行同样的 50 URL 批次。

2. 队列管理

通过将数千个 URL 切分成多个批次并管理队列来处理它们。

切分策略

将大型 URL 列表拆分成可管理的批次

Typescript
// Chunk array into batches of 50
function chunkArray<T>(array: T[], size: number): T[][] {
  const chunks: T[][] = [];
  for (let i = 0; i < array.length; i += size) {
    chunks.push(array.slice(i, i + size));
  }
  return chunks;
}

// Process all URLs in batches
async function processBatches(urls: string[]) {
  const batches = chunkArray(urls, 50); // Max 50 URLs per batch
  const allResults: any[] = [];

  for (let i = 0; i < batches.length; i++) {
    const batch = batches[i];
    console.log(`Processing batch ${i + 1}/${batches.length}...`);

    const response = await fetch('https://crawlforge.dev/api/v1/tools/batch_scrape', {
      method: 'POST',
      headers: {
        'X-API-Key': process.env.CRAWLFORGE_API_KEY!,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        urls: batch.map(url => ({ url })),
        batch_config: { concurrency: 8 },
      }),
    });

    const data = await response.json();
    allResults.push(...data.data.results);

    // Wait between batches to respect rate limits
    if (i < batches.length - 1) {
      await new Promise(resolve => setTimeout(resolve, 2000));
    }
  }

  return allResults;
}

// Usage
const urls = [...]; // 500 URLs
const results = await processBatches(urls);
console.log(`Scraped ${results.length} total pages`);
专业提示: 使用 Redis 或数据库来存储你的队列。这样在脚本崩溃或需要重启时,你可以恢复处理。

3. 错误恢复

通过重试逻辑和错误追踪优雅地处理失败。

健壮的错误处理

Typescript
interface BatchResult {
  successful: any[];
  failed: { url: string; error: string }[];
}

async function batchScrapeWithRetry(
  urls: string[],
  maxRetries = 3
): Promise<BatchResult> {
  const successful: any[] = [];
  const failed: { url: string; error: string }[] = [];
  let remainingUrls = [...urls];
  let retries = 0;

  while (remainingUrls.length > 0 && retries <= maxRetries) {
    try {
      const response = await fetch('https://crawlforge.dev/api/v1/tools/batch_scrape', {
        method: 'POST',
        headers: {
          'X-API-Key': process.env.CRAWLFORGE_API_KEY!,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          urls: remainingUrls.map(url => ({ url })),
          batch_config: { concurrency: 5 },
        }),
      });

      const data = await response.json();

      // Each result carries its own status: 'success' | 'failed' | 'skipped'.
      // 'skipped' means the request's time budget ran out before that URL was
      // started — those are not charged, so they are always worth retrying.
      const batchSuccessful = data.data.results.filter((r: any) => r.status === 'success');
      const batchUnfinished = data.data.results.filter((r: any) => r.status !== 'success');

      successful.push(...batchSuccessful);

      // Only retry the URLs that did not come back successful
      remainingUrls = batchUnfinished.map((r: any) => r.url);

      if (remainingUrls.length > 0) {
        console.log(`Retrying ${remainingUrls.length} failed URLs...`);
        retries++;
        await new Promise(resolve => setTimeout(resolve, 2000 * retries));
      }

    } catch (error) {
      console.error('Batch request failed:', error);
      retries++;

      if (retries > maxRetries) {
        // Mark all remaining URLs as failed
        failed.push(...remainingUrls.map(url => ({
          url,
          error: String(error)
        })));
        break;
      }

      await new Promise(resolve => setTimeout(resolve, 2000 * retries));
    }
  }

  return { successful, failed };
}

// Usage
const { successful, failed } = await batchScrapeWithRetry(urls);
console.log(`Success: ${successful.length}, Failed: ${failed.length}`);

// Save failed URLs for manual review
if (failed.length > 0) {
  fs.writeFileSync('failed-urls.json', JSON.stringify(failed, null, 2));
}

4. 性能优化

通过这些优化策略,最大化吞吐量并最小化成本。

优化并发数
从 batch_config.concurrency: 5 开始。该 API 接受 1-10,实际最多运行 8 个工作线程
注意时间预算
单次请求的抓取时间约为 20 秒。未能开始的 URL 会返回 skipped,而被跳过的 URL 不计费
重新读取,而不是重新抓取
结果会保存 24 小时。请用 get_batch_results(1 credit)翻页读取,而不是重跑整批(每个 URL 5 credits)
缓存结果
将抓取的数据存储在 Redis/数据库中,避免重复抓取相同的 URL
避免过度批处理
每批次不要超过 50 个 URL——应拆分成多个请求
不要忽视速率限制
遵守你所在套餐的速率限制(Free:1/s,Hobby:2/s,Pro:4/s,Business:10/s)

预期性能

场景时间设置
小批量(10 个 URL)约 5 秒concurrency: 5
中批量(50 个 URL)约 15 秒concurrency: 8
大批量(500 个 URL)约 3 分钟10 批 × 50 个 URL
超大批量(5,000 个 URL)约 30 分钟100 批 × 50 个 URL
下一步
继续学习更多高级指南
Credit 优化 →
降低成本
隐身技术 →
绕过反爬虫系统

页脚

CrawlForge MCP

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

产品

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

资源

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

开发者

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

公司

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

保持更新

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

基于 Next.js 和 MCP 协议构建

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