如何用Node.js实现一个高效的爬虫程序?

来源:菜鸟站长作者:长沙网站建设头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何用Node.js实现一个高效的爬虫程序?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何用Node.js实现一个高效的爬虫程序?》有用,将其分享出去将是对创作者最好的鼓励。

Node.js凭借非阻塞I/O和事件驱动的特性,非常适合用来开发爬虫程序,能够高效处理大量网络请求。下面我们从基础实现到性能优化,逐步讲解如何搭建一个高效的Node.js爬虫。

如何用Node.js实现一个高效的爬虫程序?

基础爬虫的核心依赖

实现爬虫首先需要两个核心库,分别是用于发送HTTP请求的axios和用于解析HTML页面的cheerio,可以通过npm安装:

npm install axios cheerio

基础爬虫实现步骤

1. 发送请求获取页面内容

使用axios发送GET请求获取目标页面的HTML字符串,这里需要注意设置合理的请求头,模拟浏览器访问避免被反爬:

const axios = require('axios');

// 发送请求获取页面内容
async function fetchPage(url) {
  try {
    const response = await axios.get(url, {
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
      }
    });
    return response.data;
  } catch (error) {
    console.error(`请求${url}失败:`, error.message);
    return null;
  }
}

2. 解析页面提取目标数据

拿到HTML字符串后,使用cheerio加载内容,通过CSS选择器提取需要的数据,用法和jQuery类似:

const cheerio = require('cheerio');

// 解析页面提取文章标题和链接
function parsePage(html) {
  if (!html) return [];
  const $ = cheerio.load(html);
  const result = [];
  // 假设目标数据在class为article-item的div中
  $('.article-item').each((index, element) => {
    const title = $(element).find('.title').text().trim();
    const link = $(element).find('a').attr('href');
    if (title && link) {
      result.push({ title, link });
    }
  });
  return result;
}

3. 基础流程串联

将请求和解析步骤结合,实现一个简单的单页面爬虫:

async function basicCrawler(targetUrl) {
  const html = await fetchPage(targetUrl);
  const data = parsePage(html);
  console.log('采集到的数据:', data);
  return data;
}

// 调用示例
basicCrawler('https://ipipp.com/article-list');

提升爬虫效率的优化方案

异步并发控制

单请求串行采集效率很低,Node.js支持异步并发,但如果不加控制同时发送大量请求,会导致目标服务器压力过大被封禁,也会占用过多本地资源。我们可以使用p-limit库控制并发数量:

npm install p-limit

控制并发的采集示例:

const pLimit = require('p-limit');
const limit = pLimit(5); // 最多同时5个请求

// 批量采集多个页面
async function batchCrawl(urlList) {
  const tasks = urlList.map(url => {
    return limit(async () => {
      const html = await fetchPage(url);
      return parsePage(html);
    });
  });
  const results = await Promise.all(tasks);
  // 合并所有结果
  return results.flat();
}

// 调用示例
const urlList = [
  'https://ipipp.com/page/1',
  'https://ipipp.com/page/2',
  'https://ipipp.com/page/3'
];
batchCrawl(urlList).then(data => console.log('批量采集结果:', data));

请求去重

避免重复采集同一个页面,可以使用Set存储已经访问过的URL:

const visitedUrls = new Set();

async function crawlWithDedup(url) {
  if (visitedUrls.has(url)) {
    console.log(`URL ${url} 已经采集过,跳过`);
    return [];
  }
  visitedUrls.add(url);
  const html = await fetchPage(url);
  const data = parsePage(html);
  // 假设页面中有下一页链接,继续采集
  const $ = cheerio.load(html);
  const nextPage = $('.next-page').attr('href');
  if (nextPage) {
    const nextData = await crawlWithDedup(nextPage);
    return data.concat(nextData);
  }
  return data;
}

错误重试机制

网络请求偶尔会失败,添加重试机制可以提升爬虫的稳定性,这里实现最多重试3次的逻辑:

async function fetchPageWithRetry(url, retryCount = 3) {
  for (let i = 0; i < retryCount; i++) {
    const html = await fetchPage(url);
    if (html) return html;
    console.log(`第${i + 1}次请求${url}失败,正在重试...`);
  }
  console.error(`请求${url}失败,已达最大重试次数`);
  return null;
}

注意事项

  • 遵守目标网站的robots.txt规则,不要采集禁止访问的内容
  • 控制请求频率,避免对目标服务器造成过大压力
  • 如果需要采集大量数据,建议添加代理IP池,避免本地IP被封禁
  • 采集到的数据可以存储到数据库或者本地文件中,方便后续使用

数据存储示例

将采集到的数据存储到JSON文件中:

const fs = require('fs');

function saveDataToFile(data, filename = 'crawl_result.json') {
  fs.writeFileSync(filename, JSON.stringify(data, null, 2), 'utf-8');
  console.log(`数据已保存到${filename}`);
}

// 结合之前的批量采集使用
batchCrawl(urlList).then(data => {
  saveDataToFile(data);
});

Node.js爬虫cheerioaxios异步并发修改时间:2026-07-12 15:03:24

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。