Nodejs 最近做的一个爬虫,功能比较全面

Nodejs 最近做的一个爬虫,功能比较全面

https://github.com/dlutwuwei/CrawlerX 在github上找过一些爬虫,都不带深度遍历,总缺少一些东西,现在做了一个,对请求并发做了控制,可以设置并发数,对不同URL做不同处理,可以设置中文(GBK)的解码,有需要的人看看,有什么需要改进的,欢迎提意见。

2 回复

当然,下面是一个关于 Node.js 爬虫的详细示例,包括并发控制、不同 URL 的处理以及中文解码等功能。

示例代码

const axios = require('axios');
const cheerio = require('cheerio');
const url = require('url');

// 并发控制
const MAX_CONCURRENT_REQUESTS = 5;
let activeRequests = 0;

// 存储已经访问过的 URL 避免重复抓取
const visitedUrls = new Set();

// 需要抓取的初始 URL 列表
const urlsToVisit = [
    'http://example.com',
    'http://example.org'
];

// 处理不同 URL 的函数
async function handleUrl(urlStr, depth) {
    if (visitedUrls.has(urlStr)) return;

    visitedUrls.add(urlStr);

    try {
        const response = await axios.get(urlStr);
        const decodedContent = Buffer.from(response.data, 'binary').toString('gbk');
        
        const $ = cheerio.load(decodedContent);
        console.log(`Depth ${depth}: ${urlStr}`);
        console.log($('title').text());

        // 查找并处理所有链接
        $('a').each((i, link) => {
            const href = $(link).attr('href');
            if (href && !visitedUrls.has(href)) {
                const absoluteUrl = url.resolve(urlStr, href);
                urlsToVisit.push(absoluteUrl);
            }
        });

    } catch (error) {
        console.error(`Error fetching ${urlStr}:`, error.message);
    }
}

// 控制并发请求
async function processQueue() {
    while (urlsToVisit.length > 0) {
        while (activeRequests < MAX_CONCURRENT_REQUESTS && urlsToVisit.length > 0) {
            const currentUrl = urlsToVisit.shift();
            activeRequests++;
            handleUrl(currentUrl, 1); // 这里可以根据需求调整深度
        }

        await new Promise(resolve => setTimeout(resolve, 100)); // 避免过于频繁地检查队列
    }
}

processQueue().then(() => console.log('Crawling finished'));

解释

  1. 并发控制

    • 使用 MAX_CONCURRENT_REQUESTS 来限制同时进行的请求数量。
    • activeRequests 记录当前正在进行的请求数量,确保不超过设定的最大值。
  2. 避免重复抓取

    • 使用 visitedUrls 集合来记录已经访问过的 URL,防止重复抓取。
  3. 处理不同 URL

    • handleUrl 函数负责处理每个 URL,获取页面内容,并使用 Cheerio 解析 HTML。
    • 对于页面中的每个链接,将其转换为绝对 URL 并加入待访问队列。
  4. 中文解码

    • 使用 Buffer.from(response.data, 'binary').toString('gbk') 将响应内容从 GBK 编码解码为字符串。
  5. 递归抓取

    • 通过递归调用 handleUrl 函数来处理新的 URL,从而实现深度遍历。

希望这个示例能帮助你理解如何构建一个功能全面的 Node.js 爬虫。如果有任何问题或改进建议,欢迎留言讨论!


根据你的描述,你已经完成了一个较为全面的爬虫项目,并且已经在GitHub上分享了代码。以下是一个简单的示例代码,展示如何使用Node.js进行爬虫开发,并包含一些基本功能如请求并发控制、不同URL的处理以及字符编码支持。

示例代码

const axios = require('axios');
const cheerio = require('cheerio');

// 并发控制队列
const MAX_CONCURRENT_REQUESTS = 5;
let activeRequests = 0;

async function handleRequest(url) {
    try {
        const response = await axios.get(url, { responseType: 'text' });
        const $ = cheerio.load(response.data);
        
        // 处理响应数据
        console.log(`Processing ${url}`);
        $('a').each((index, element) => {
            const link = $(element).attr('href');
            if (link && link.startsWith('http')) {
                // 将新的URL添加到队列中
                addUrlToQueue(link);
            }
        });
    } catch (error) {
        console.error(`Error processing ${url}:`, error);
    } finally {
        // 请求完成后减少活动请求计数
        activeRequests--;
    }
}

function addUrlToQueue(url) {
    // 控制并发数量
    while (activeRequests >= MAX_CONCURRENT_REQUESTS) {
        // 等待直到有空闲的请求槽位
        await new Promise(resolve => setTimeout(resolve, 100));
    }
    
    activeRequests++;
    handleRequest(url);
}

// 初始URL
addUrlToQueue('https://example.com');

代码解释

  • 依赖库:使用axios进行HTTP请求,cheerio解析HTML。
  • 并发控制:通过activeRequests变量来跟踪当前活跃的请求数量,限制最大并发数为MAX_CONCURRENT_REQUESTS
  • 请求处理:在handleRequest函数中,处理每个请求返回的数据,并提取页面中的链接,递归地将新链接添加到队列中。
  • 字符编码支持:在这个例子中没有明确提到字符编码,但可以通过配置axios选项来指定所需的字符编码(例如GBK)。

提示

如果你需要进一步增强爬虫的功能,可以考虑加入错误重试机制、异常处理、日志记录、数据库存储等功能。此外,如果目标网站结构复杂或反爬策略严格,建议深入研究网站的HTML结构和服务器响应,以提高爬取效率和成功率。

回到顶部