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);

最佳实践

  1. 遵守robots.txt:尊重网站的爬虫规则
  2. 设置合理的请求间隔:避免对目标网站造成压力
  3. 使用缓存机制:减少重复请求
  4. 处理编码问题:正确解析不同编码的网页
  5. 定期更新User-Agent:避免被识别为爬虫
  6. 验证数据完整性:确保爬取的数据准确完整

常用工具库推荐

  • 请求库: axios, node-fetch, got
  • 解析库: cheerio, jsdom, puppeteer
  • 并发控制: p-limit, async
  • 队列管理: bull, bee-queue
  • 代理管理: proxy-chain, puppeteer-page-proxy
  • 数据处理: lodash, moment

总结

开发Node.js爬虫需要综合考虑请求管理、数据处理、反爬应对等多个方面。通过合理的工具选择和架构设计,可以构建高效、稳定的爬虫系统。记住要始终遵守法律法规和道德准则,尊重目标网站的权益。

可以进扣扣裙(651706395),互相交流!

posted @ 2025-09-12 09:56  深圳蔓延科技有限公司  阅读(9)  评论(0)    收藏  举报