Node.js爬虫实战:从TopHub抓取热榜数据并导出为CS

50 阅读4分钟

使用Node.js抓取热榜信息并保存至CSV文件

在本教程中,我们将学习如何使用Node.js结合request-promisecheeriocsv-writer三个库来抓取网页上的热榜信息,并将其导出为CSV文件。

准备工作

确保你的环境中已经安装了Node.js。然后通过npm安装所需的依赖包:

npm install request-promise cheerio csv-writer

代码实现与解析

导入必要的模块

首先,我们需要导入将要使用的模块。这些模块帮助我们发送HTTP请求、解析HTML文档以及创建CSV文件。

const request = require('request-promise'); // 用于发起HTTP请求
const cheerio = require('cheerio'); // 用于解析和操作DOM结构
const createCsvWriter = require('csv-writer').createObjectCsvWriter; // 用于生成CSV文件

定义目标网址

接下来,定义我们要爬取的网页地址。这里以TopHub网站的一个特定页面为例,它汇总了一些平台的热门话题。

const url = 'https://tophub.today/n/KqndgxeLl9'; // 目标网址

发送HTTP请求并解析HTML内容

使用request-promise库发送GET请求获取网页的HTML源码,再用Cheerio加载这段HTML,以便我们可以像在浏览器中一样进行DOM查询。

request(url)
  .then(html => {
    const $ = cheerio.load(html); // 加载HTML到Cheerio对象中
    const hotList = []; // 创建一个数组来存储提取的数据

提取表格中的数据

遍历页面中包含热榜信息的表格行(<tr>标签),对于每一行,提取排名、标题、热度及链接等信息,并将它们添加到之前创建的数组中。

    $('table tbody tr').each((index, element) => { // 遍历每个<tr>元素
      const rank = $(element).find('td:nth-child(1)').text().trim(); // 获取排名
      const title = $(element).find('td:nth-child(2) a').text().trim(); // 获取标题
      const heat = $(element).find('td:nth-child(3)').text().trim(); // 获取热度
      const link = $(element).find('td:nth-child(2) a').attr('href'); // 获取链接

      hotList.push({ rank, title, heat, link }); // 将提取的信息加入hotList数组
    });

这里的内容的获取位置和其在页面的位置有关,比如在这里titlelink都在第二个td a标签下面,如下图:

image.png

将数据写入CSV文件

最后,我们使用csv-writer库将收集到的数据写入CSV文件中,方便后续查看或进一步处理。

    const csvWriter = createCsvWriter({
      path: 'web_hotList.csv', // CSV文件路径
      header: [ // CSV文件头部信息
        { id: 'rank', title: '排名' },
        { id: 'title', title: '标题' },
        { id: 'heat', title: '热度' },
        { id: 'link', title: '链接' }
      ]
    });

    csvWriter.writeRecords(hotList) // 写入数据到CSV文件
      .then(() => console.log('数据已成功写入 web_hotList.csv'))
      .catch(err => console.error('写入CSV文件失败:', err));
  })
  .catch(err => console.error('请求失败:', err)); // 捕获请求错误
writeRecords 方法
  • writeRecords 是 csv-writer 库中的一个固定 API,用于将一组对象写入 CSV 文件。它是一个非常方便的方法,适用于需要将结构化数据写入 CSV 文件的场景。

    • 功能: writeRecords 方法用于将一组对象写入 CSV 文件。每个对象的键(属性)对应 CSV 文件中的列。

    • 参数: 该方法接受一个数组,数组中的每个元素都是一个对象,对象的键与 CSV 文件的列标题相对应。

    • 返回值: 返回一个Promise 对象,可以在 .then() 中处理成功写入的情况,或者在 .catch() 中处理错误。

注意事项

如果 header 中的 id 与 records 中的对象键不对应,csv-writer 将无法正确地将数据写入 CSV 文件,可能会导致某些列为空或数据不匹配。例如,如果 header 定义如下:

const csvWriter = createCsvWriter({

    path'out.csv',

    header: [

        { id'firstName'title'Name' },

        { id'age'title'Age' },

        { id'email'title'Email' }

    ]

});

而 records 数组如下:

const records = [

    { name'John Doe'age30email'john.doe@example.com' },

    { name'Jane Smith'age25email'jane.smith@example.com' }

];

在这种情况下,firstName 列将为空,因为 records 中的对象没有 firstName 键。正确的 header 应该是:

const csvWriter = createCsvWriter({

    path'out.csv',

    header: [

        { id'name'title'Name' },

        { id'age'title'Age' },

        { id'email'title'Email' }

    ]

});
  • header 中的 id 必须与 records 数组中对象的键相对应,以确保数据正确地写入 CSV 文件的相应列。

  • 如果不对应,可能会导致某些列为空或数据不匹配。

总结

  • 遵守规则:在编写网络爬虫时,请务必遵守目标网站的robots.txt协议及其他相关法律法规。
  • 频率控制:不要过于频繁地访问同一网站,以免给服务器带来不必要的压力;可以在请求之间设置适当的延迟。
  • 异常处理:实际开发中应更加完善错误处理机制,比如应对网络故障或者页面结构调整等情况。

当然,你也可以使用csv-parser库去解析csv文件,然后写入HTML文件,使得页面更美观。

image.png 希望这篇文章能够帮助大家理解如何利用Node.js抓取网页信息并保存为CSV文件。如果遇到问题或有任何建议,欢迎留言交流!