You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化基于已抓取URL批量拉取供应商商品详情的慢速代码

爬虫代码优化方案

性能瓶颈原因

当前代码运行慢的核心原因是详情页采用串行请求逻辑:25个商品详情页必须等待前一个请求、解析完全完成后才会发起下一个,总耗时是所有单个请求耗时的叠加。

优化后代码

import fetch from "isomorphic-fetch";
import cheerio from "cheerio";
// 域名提取为常量,避免重复硬编码
const BASE_URL = "https://www.supplier.co.uk";

// 单个商品详情页抓取逻辑抽离为独立函数
const fetchProductDetail = async (productUrl) => {
  try {
    const detailRes = await fetch(productUrl);
    const detailHtml = await detailRes.text();
    const $detail = cheerio.load(detailHtml);
    return {
      pageSrc: productUrl,
      imageSrc: $detail("#product-main-image .main-image-inner:first-child img").attr("src"),
      name: $detail("#product-details dd:nth-child(2)").text().trim(),
      brand: $detail("#product-details dd:nth-child(4)").text().trim(),
      price: $detail("#product-details dd:nth-child(6)").text().trim()
    }
  } catch (err) {
    // 单个商品抓取失败打印日志,不影响整体返回
    console.error(`商品${productUrl}抓取失败:`, err.message);
    return null;
  }
}

export const fetchNewProducts = async (page) => {
  try {
    const listRes = await fetch(
      `${BASE_URL}/newarrivals/?setPerPage=25&search_direction=asc&pageID=${page}`
    );
    const listHtml = await listRes.text();
    const $list = cheerio.load(listHtml);
    // 批量提取所有商品链接,不用硬编码1-25的索引,适配列表变化
    const productUrls = [];
    $list("#product_listing > tbody tr td:nth-child(2) > a").each((_, el) => {
      productUrls.push(`${BASE_URL}${$list(el).attr("href")}`);
    });
    // 并发请求所有详情页,大幅压缩耗时
    const productTasks = productUrls.map(url => fetchProductDetail(url));
    const rawProducts = await Promise.all(productTasks);
    // 过滤掉抓取失败的空值
    return rawProducts.filter(Boolean);
  } catch (err) {
    console.error("列表页抓取失败:", err.message);
    return [];
  }
};

// 注意:原代码混用ES模块和CommonJS导出规范,这里统一用ES模块导出,如果你的项目用CommonJS可以改为下面的写法
// module.exports = { fetchNewProducts }

主要优化点

  • 采用并发请求替代串行请求,在站点无并发限制的情况下,整体耗时可以压缩到原来的1/10~1/20
  • 抽离单个商品抓取逻辑,代码结构更清晰,后续修改规则更方便
  • 修复原代码模块导出规范混用的问题,避免运行报错
  • 补全全链路错误处理,单个商品/列表页抓取失败不会直接返回空,也有日志方便排查问题
  • 优化列表页链接提取逻辑,不用硬编码遍历1-25的索引,适配列表页商品数量变动的场景
  • 统一提取域名为常量,所有文本结果加trim()去除多余空格,数据更规范
  • 如果需要控制并发数避免被站点封IP,可以自己实现简单的并发队列,或者引入对应工具包实现分批并发。

内容的提问来源于stack exchange,提问作者Liiaam93

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 09:57:03