使用Node.js抓取热榜信息并保存至CSV文件
在本教程中,我们将学习如何使用Node.js结合request-promise
、cheerio
和csv-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数组
});
这里的内容的获取位置和其在页面的位置有关,比如在这里title
和link
都在第二个td a
标签下面,如下图:
将数据写入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', age: 30, email: 'john.doe@example.com' },
{ name: 'Jane Smith', age: 25, email: '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文件,使得页面更美观。
希望这篇文章能够帮助大家理解如何利用Node.js抓取网页信息并保存为CSV文件。如果遇到问题或有任何建议,欢迎留言交流!