Node.js 爬虫开发核心要点
概述
Node.js 因其异步非阻塞I/O模型和丰富的生态系统,成为开发网络爬虫的优秀选择。本文将介绍开发Node.js爬虫的核心要点。
核心要点
1. 选择合适的HTTP请求库
// axios 示例
const axios = require('axios');
async function fetchData(url) {
try {
const response = await axios.get(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
},
timeout: 10000
});
return response.data;
} catch (error) {
console.error('请求失败:', error.message);
}
}
2. 使用高效的HTML解析工具
// cheerio 示例
const cheerio = require('cheerio');
function parseHTML(html) {
const $ = cheerio.load(html);
const titles = [];
$('h1, h2, h3').each((index, element) => {
titles.push($(element).text().trim());
});
return titles;
}
3. 控制请求频率与并发
// 使用p-limit控制并发
const pLimit = require('p-limit');
const limit = pLimit(5); // 最大并发数
async function crawlMultiple(urls) {
const promises = urls.map(url =>
limit(() => fetchData(url))
);
return Promise.all(promises);
}
4. 处理反爬虫机制
// 使用代理和随机延迟
const proxies = ['proxy1:port', 'proxy2:port'];
const delays = [1000, 2000, 3000];
async function stealthRequest(url) {
const proxy = proxies[Math.floor(Math.random() * proxies.length)];
const delay = delays[Math.floor(Math.random() * delays.length)];
await new Promise(resolve => setTimeout(resolve, delay));
return axios.get(url, {
proxy: {
host: proxy.split(':')[0],
port: parseInt(proxy.split(':')[1])
},
headers: {
'User-Agent': getRandomUserAgent(),
'Accept-Language': 'en-US,en;q=0.9',
'Referer': 'https://www.google.com/'
}
});
}
5. 错误处理与重试机制
// 实现指数退避重试
async function retryRequest(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await fetchData(url);
} catch (error) {
if (i === retries - 1) throw error;
const delay = Math.pow(2, i) * 1000;
console.log(`请求失败,${delay}ms后重试...`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
6. 数据存储方案
// 多种存储方式示例
const fs = require('fs');
const { MongoClient } = require('mongodb');
// 保存到JSON文件
function saveToJSON(data, filename) {
fs.writeFileSync(filename, JSON.stringify(data, null, 2));
}
// 保存到MongoDB
async function saveToMongoDB(data, collectionName) {
const client = new MongoClient('mongodb://localhost:27017');
await client.connect();
const collection = client.db('crawler').collection(collectionName);
await collection.insertMany(data);
await client.close();
}
7. 使用队列管理任务
// 使用bull队列
const Queue = require('bull');
const crawlQueue = new Queue('crawling', {
redis: { port: 6379, host: '127.0.0.1' }
});
// 添加任务到队列
crawlQueue.add({ url: 'https://example.com' });
// 处理任务
crawlQueue.process(async (job) => {
const { url } = job.data;
return await fetchData(url);
});
8. 监控和日志记录
// 使用winston记录日志
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'crawler.log' })
]
});
// 监控请求速率
let requestCount = 0;
setInterval(() => {
logger.info(`当前请求速率: ${requestCount} 请求/分钟`);
requestCount = 0;
}, 60000);
最佳实践
- 遵守robots.txt:尊重网站的爬虫规则
- 设置合理的请求间隔:避免对目标网站造成压力
- 使用缓存机制:减少重复请求
- 处理编码问题:正确解析不同编码的网页
- 定期更新User-Agent:避免被识别为爬虫
- 验证数据完整性:确保爬取的数据准确完整
常用工具库推荐
- 请求库: axios, node-fetch, got
- 解析库: cheerio, jsdom, puppeteer
- 并发控制: p-limit, async
- 队列管理: bull, bee-queue
- 代理管理: proxy-chain, puppeteer-page-proxy
- 数据处理: lodash, moment
总结
开发Node.js爬虫需要综合考虑请求管理、数据处理、反爬应对等多个方面。通过合理的工具选择和架构设计,可以构建高效、稳定的爬虫系统。记住要始终遵守法律法规和道德准则,尊重目标网站的权益。
可以进扣扣裙(651706395),互相交流!

浙公网安备 33010602011771号