Node.js 实现异步并发爬虫(第 1 部分)
这个部分主要实现了如何使用 Node.js 编写一个异步并发爬虫,利用 axios
发送请求,cheerio
解析页面,并使用 p-limit
控制并发数。
步骤:
1. 初始化项目
在你的项目文件夹中初始化一个 Node.js 项目:
mkdir node-crawler
cd node-crawler
npm init -y
npm install axios cheerio p-limit
axios
用于发起 HTTP 请求;cheerio
用于解析 HTML 内容(类似于 jQuery);p-limit
控制并发请求的数量,避免请求过多导致服务器负载过高。
2. 编写爬虫代码
创建 crawler.js
文件:
const axios = require('axios');
const cheerio = require('cheerio');
const pLimit = require('p-limit');
// 模拟要爬取的一组 URL
const urls = [
'https://example.com',
'https://example.org',
'https://example.net',
// 你可以继续添加更多 URL
];
// 设置最大并发数(例如:最多同时5个请求)
const limit = pLimit(5);
// 获取网页内容的函数
async function fetchPage(url) {
try {
// 使用 axios 发送 GET 请求
const response = await axios.get(url, {
timeout: 5000, // 设置请求超时
headers: {
'User-Agent': 'Mozilla/5.0 (Crawler Bot)' // 模拟常见的浏览器
}
});
// 解析 HTML
const html = response.data;
const $ = cheerio.load(html);
// 从页面中提取标题
const title = $('title').text();
console.log(`[Success] ${url} - ${title}`);
return { url, title };
} catch (error) {
console.error(`[Error] ${url} - ${error.message}`);
return { url, error: error.message };
}
}
// 运行爬虫并控制并发
async function run() {
// 使用 limit 函数限制并发请求
const tasks = urls.map(url => limit(() => fetchPage(url)));
// 等待所有任务完成
const results = await Promise.all(tasks);
// 输出所有任务结果
console.log('\nAll tasks completed:');
console.log(results);
}
// 启动爬虫
run();
3. 代码解析:
urls
: 定义了一组要爬取的网页 URL,你可以根据需求添加更多的 URL;p-limit
: 使用p-limit
限制并发请求的数量。此例中设置为5
,表示同时最多只能发起 5 个请求;fetchPage
: 该函数负责处理每个网页的请求、HTML 解析及数据提取;- 使用
axios
获取网页内容,设置了 5 秒的请求超时; - 使用
cheerio
解析 HTML 文档,并提取<title>
标签中的内容; - 捕获任何请求错误,并输出错误信息;
- 使用
run
: 负责调度多个爬虫任务并使用Promise.all()
等待所有任务完成。
4. 执行爬虫
在命令行中运行爬虫:
node crawler.js
如果一切顺利,输出类似如下:
[Success] https://example.com - Example Domain
[Success] https://example.org - Example Domain
[Success] https://example.net - Example Domain
All tasks completed:
[
{ url: 'https://example.com', title: 'Example Domain' },
{ url: 'https://example.org', title: 'Example Domain' },
{ url: 'https://example.net', title: 'Example Domain' }
]
5. 下一步的优化建议:
- 错误重试机制: 如果请求失败,尝试重新请求。可以使用
axios-retry
实现。 - 代理支持: 如果服务器限制访问,可以使用代理来绕过。
- 数据存储: 将抓取的数据存储到数据库中,比如 MongoDB 或 MySQL。
- URL 队列管理: 你可以增加一个 URL 队列管理器,实现深度爬取。
你现在有一个基本的爬虫框架。如果有其他需求(比如增加重试机制或存储数据),可以告诉我,我们可以进一步扩展这个爬虫。
发表回复