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

如何实现多网页爬取与存储?基于Node.js+Vue.js的技术咨询

多网页爬虫实现方案

核心结论

不用给每个网页写全量重复代码,但必须针对每个目标站点定义专属的爬取规则——毕竟不同网站的DOM结构、CSS选择器肯定不一样。但你可以把启动浏览器、滚动加载、页面解析这类通用逻辑抽成工具函数,只给每个站点单独配置「URL、滚动规则、数据提取选择器」即可。

具体实现步骤

1. 抽象通用爬虫工具函数

把你现有代码里的重复逻辑(比如Puppeteer启动/关闭、滚动加载、页面内容获取)抽成可复用的函数,接受站点配置作为参数:

// 通用爬虫工具函数
async function crawlSite(config) {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();
  
  // 跳转到目标站点
  await page.goto(config.url, { waitUntil: 'networkidle2' });
  
  // 执行滚动加载(仅当站点需要时)
  if (config.needScroll) {
    let previousHeight;
    while (true) {
      const currentHeight = await page.evaluate('document.body.scrollHeight');
      if (currentHeight === previousHeight) break;
      previousHeight = currentHeight;
      await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
      // 加延迟避免滚动过快导致内容未加载
      await page.waitForTimeout(1000);
    }
  }
  
  // 解析页面内容
  const content = await page.content();
  const $ = cheerio.load(content);
  
  // 调用站点专属的数据提取逻辑
  const data = config.extractData($);
  
  await browser.close();
  return data;
}

2. 为每个站点定义爬取规则

每个站点单独写一个配置对象,只包含该站点独有的规则,不用重复写爬虫核心逻辑:

// 你的原有新闻站点配置
const newsSiteAConfig = {
  url: process.env.VUE_APP_PROD_NEWS_DOMAIN,
  needScroll: true,
  extractData: ($) => {
    const newsList = [];
    $(".list-bigger-wrap").each((index, item) => {
      const imgsrc = $(item).find("img").attr('src');
      const title = $(item).find(".list-bigger-txt p:first-child").text().trim();
      const period = $(item).find(".list-bigger-txt p:nth-child(2)").text().trim();
      const place = $(item).find(".list-bigger-txt p:nth-child(3)").text().trim();
      const exclusive = $(item).find(".list-bigger-txt p:nth-child(4)").text().trim();
      
      newsList.push({ imgsrc, title, period, place, exclusive });
    });
    return newsList;
  }
};

// 示例:第二个新闻站点的配置
const newsSiteBConfig = {
  url: 'https://example-news-site.com/latest',
  needScroll: false,
  extractData: ($) => {
    const newsList = [];
    $(".news-card").each((index, item) => {
      const title = $(item).find(".card-title").text().trim();
      const content = $(item).find(".card-summary").text().trim();
      const publishTime = $(item).find(".card-time").text().trim();
      
      newsList.push({ title, content, publishTime });
    });
    return newsList;
  }
};

3. 批量执行爬取并整合数据

在路由里调用通用函数,并行或串行处理多个站点的爬取请求,最后整合结果:

router.get('/multi-news', async function(req, res, next) {
  try {
    // 并行爬取多个站点(效率更高,也可根据需求改成串行)
    const [siteANews, siteBNews] = await Promise.all([
      crawlSite(newsSiteAConfig),
      crawlSite(newsSiteBConfig)
    ]);
    
    // 整合所有数据(可按站点分类,或合并成统一格式)
    const allNews = [...siteANews, ...siteBNews];
    
    // 执行数据入库逻辑(复用你之前的代码)
    // await saveNewsToDB(allNews);
    
    res.status(200).json({
      total: allNews.length,
      data: allNews
    });
  } catch (error) {
    console.error('爬取失败:', error);
    res.status(500).json({ message: '爬取任务执行失败' });
  }
});

实用优化建议

  • 规则可配置化:把站点规则存在JSON文件或数据库里,新增站点时直接加配置,不用修改核心代码。
  • 错误隔离:给每个站点的爬取任务单独加try-catch,避免某个站点爬取失败导致整个批量任务中断。
  • 反爬适配:添加随机User-Agent、请求延迟,必要时使用代理IP,降低被目标站点封禁的风险。
  • 数据去重:爬取后根据标题、链接等唯一标识去重,避免重复数据入库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 22:13:18