首页
/ 7个步骤掌握Crawlee:从快速上到手实战案例

7个步骤掌握Crawlee:从快速上到手实战案例

2026-03-15 03:56:08作者:卓艾滢Kingsley

你是否曾因网页结构复杂而放弃爬虫开发?是否在面对动态加载内容时感到无从下手?Crawlee作为Node.js生态中强大的网页抓取与浏览器自动化库,能帮助开发者快速构建可靠的爬虫系统。本文将通过7个步骤,带你从环境搭建到实战应用,全面掌握Crawlee的核心功能与最佳实践,让你轻松应对各类网页抓取挑战。

1. 环境检测与依赖配置:让Crawlee在你的电脑安家

准备开始Crawlee之旅?首先要确保你的开发环境符合要求。Crawlee需要Node.js 16或更高版本,这就像开车前要检查油箱和轮胎一样重要。打开终端,输入以下命令检查你的Node.js版本:

node -v  # 检查Node.js版本
npm -v   # 检查npm版本

如果你的Node.js版本低于16,需要先升级。推荐使用nvm(Node Version Manager)来管理Node.js版本,这就像给你的开发环境配备了一个灵活的"变速箱"。

两种安装方式,按需选择

1. 使用Crawlee CLI(推荐新手) Crawlee提供了便捷的命令行工具,能自动创建项目结构并安装所有必要依赖,就像一键搭建好爬虫工作室:

npx crawlee create my-crawler
cd my-crawler && npm start

运行后,Crawlee会生成完整的项目模板,包括配置文件、示例代码和存储目录,让你直接进入开发阶段。

2. 手动安装(适合集成到现有项目) 如果你需要将Crawlee集成到已有Node.js项目中,可以根据爬虫类型选择性安装:

# 基础安装(包含CheerioCrawler)
npm install crawlee

# 如果需要PlaywrightCrawler(多浏览器支持)
npm install crawlee playwright

# 如果需要PuppeteerCrawler(Chrome/Chromium专用)
npm install crawlee puppeteer

常见问题排查

  • 安装速度慢:尝试使用淘宝npm镜像 npm config set registry https://registry.npm.taobao.org
  • Playwright浏览器下载失败:手动指定浏览器下载 npx playwright install
  • 权限问题:避免使用sudo安装,推荐使用nvm管理Node.js版本

2. 核心功能场景化应用:选择你的爬虫武器

面对不同的网页类型,选择合适的爬虫类型能事半功倍。Crawlee提供了多种爬虫引擎,每种都有其独特优势,就像工具箱里的不同工具,各有所长。

场景一:静态网页数据抓取

当你需要抓取新闻网站、文档页面等静态内容时,CheerioCrawler是最佳选择。它基于Cheerio解析HTML,速度快、资源占用低,就像一把锋利的手术刀,精准高效。

import { CheerioCrawler } from 'crawlee';

const crawler = new CheerioCrawler({
    async requestHandler({ $, request }) {
        // $ 是Cheerio实例,类似jQuery语法
        const title = $('h1.article-title').text().trim();
        const publishDate = $('time.publish-date').attr('datetime');
        const content = $('.article-content').text().replace(/\s+/g, ' ').trim();
        
        console.log(`抓取文章: ${title}`);
        
        // 保存数据
        await Dataset.pushData({
            url: request.url,
            title,
            publishDate,
            content
        });
    }
});

// 启动爬虫
await crawler.run([
    'https://example-news-site.com/latest',
    'https://example-news-site.com/popular'
]);

场景二:动态内容渲染与交互

遇到需要JavaScript渲染的单页应用(SPA)或需要模拟用户操作的场景,PlaywrightCrawler是你的得力助手。它支持Chromium、Firefox和WebKit等多种浏览器,就像一个多才多艺的演员,能适应不同的舞台环境。

import { PlaywrightCrawler } from 'crawlee';

const crawler = new PlaywrightCrawler({
    // 开发时可设置为false以显示浏览器窗口
    headless: true,
    async requestHandler({ page, request }) {
        // 等待页面关键元素加载
        await page.waitForSelector('.product-list');
        
        // 提取商品数据
        const products = await page.$$eval('.product-item', items => 
            items.map(item => ({
                name: item.querySelector('.product-name').textContent.trim(),
                price: item.querySelector('.product-price').textContent.trim(),
                rating: item.querySelector('.product-rating').textContent.trim()
            }))
        );
        
        console.log(`在 ${request.url} 发现 ${products.length} 个商品`);
        
        // 保存数据
        await Dataset.pushData({
            url: request.url,
            products,
            scrapedAt: new Date().toISOString()
        });
    }
});

await crawler.run(['https://example-ecommerce.com/products']);

爬虫类型决策指南

以下是选择Crawlee爬虫类型的决策流程图:

graph TD
    A[开始] --> B{网页类型};
    B -->|静态HTML,无JS交互| C[CheerioCrawler];
    B -->|动态内容,需JS渲染| D{浏览器需求};
    D -->|多浏览器支持| E[PlaywrightCrawler];
    D -->|仅Chrome/Chromium| F[PuppeteerCrawler];
    C --> G[完成选择];
    E --> G;
    F --> G;

3. 数据提取与存储:让信息井井有条

爬取网页只是第一步,如何高效提取和妥善存储数据同样重要。Crawlee提供了直观的数据处理机制,让你轻松管理抓取结果。

精准提取网页数据

Crawlee支持多种数据提取方式,适应不同的网页结构:

1. CSS选择器(适合结构化数据)

// 使用CSS选择器提取数据
const title = $('h1.product-title').text().trim();
const price = $('.price-tag').text().replace('$', '').trim();

2. XPath(适合复杂层级结构)

// 使用XPath提取数据
const categories = await page.$x('//nav[@class="categories"]//a');
const categoryNames = await Promise.all(
    categories.map(el => page.evaluate(node => node.textContent, el))
);

3. 正则表达式(适合非结构化文本)

// 使用正则表达式提取数据
const phoneMatch = pageContent.match(/Phone: (\+\d{1,3}\s?\(\d{3}\)\s?\d{3}-\d{4})/);
const phoneNumber = phoneMatch ? phoneMatch[1] : null;

智能存储数据

Crawlee内置了强大的存储系统,无需额外配置即可使用:

import { Dataset } from 'crawlee';

// 存储单条数据
await Dataset.pushData({
    url: request.url,
    title: extractedTitle,
    content: extractedContent
});

// 批量存储数据
await Dataset.pushData([data1, data2, data3]);

// 导出数据为CSV
await Dataset.exportToCSV('scraped-data');

// 导出数据为JSON
await Dataset.exportToJSON('scraped-data');

数据默认存储在项目根目录的storage/datasets/default文件夹中,每条数据会按时间戳排序,方便后续分析和处理。

4. 反屏蔽策略配置:让爬虫隐形

网站反爬机制常常让爬虫项目功亏一篑。Crawlee内置了多种反屏蔽功能,就像给你的爬虫穿上了"隐形衣",让它在网络世界中畅行无阻。

会话池与代理管理

Crawlee的会话池(Session Pool)功能可以模拟不同用户的浏览行为,配合代理使用效果更佳:

import { PlaywrightCrawler, ProxyConfiguration } from 'crawlee';

// 配置代理
const proxyConfiguration = new ProxyConfiguration({
    proxyUrls: [
        'http://proxy1:port',
        'http://proxy2:port',
        // 更多代理...
    ]
});

const crawler = new PlaywrightCrawler({
    proxyConfiguration,
    useSessionPool: true,
    sessionPoolOptions: {
        sessionOptions: {
            maxUsageCount: 5, // 每个会话最多使用5次
            maxAgeSecs: 300   // 会话最长存活时间5分钟
        }
    },
    // 随机请求延迟,模拟人类行为
    minConcurrency: 1,
    maxConcurrency: 5,
    minDelayBetweenRequestsMillis: 1000,
    maxDelayBetweenRequestsMillis: 3000,
    // 失败重试机制
    maxRequestRetries: 3,
    async requestHandler({ page, request, session }) {
        console.log(`使用代理: ${session.proxyUrl}`);
        // 爬虫逻辑...
    }
});

Crawlee会话池工作原理 Crawlee会话池工作原理:通过轮换会话和代理,模拟多个用户的浏览行为,降低被屏蔽风险

指纹伪装与用户行为模拟

除了代理,Crawlee还能模拟真实浏览器指纹和用户行为:

const crawler = new PlaywrightCrawler({
    // 随机用户代理
    useFingerprints: true,
    // 模拟真实用户的鼠标移动
    launchContext: {
        launchOptions: {
            slowMo: 100, // 模拟人类操作延迟
        },
    },
    async requestHandler({ page }) {
        // 模拟滚动行为
        await page.evaluate(() => {
            window.scrollBy(0, window.innerHeight / 2);
        });
        await page.waitForTimeout(1000 + Math.random() * 2000);
        
        // 继续滚动到底部
        await page.evaluate(() => {
            window.scrollTo(0, document.body.scrollHeight);
        });
        // ...
    }
});

5. 实战案例:电商产品价格监控器

理论学得差不多了?让我们通过一个实战案例来巩固所学知识。我们将构建一个电商产品价格监控器,定期抓取指定商品的价格信息并记录变化。

项目需求分析

  • 定期抓取指定电商网站的产品价格
  • 记录价格历史变化
  • 当价格低于设定阈值时发出通知
  • 支持多个产品同时监控

完整实现代码

import { PlaywrightCrawler, Dataset, KeyValueStore } from 'crawlee';
import nodemailer from 'nodemailer';

// 加载监控配置
const kvStore = await KeyValueStore.open();
const监控配置 = await kvStore.getValue('config') || {
    products: [
        {
            url: 'https://example-ecommerce.com/product1',
            name: '无线蓝牙耳机',
            targetPrice: 299
        },
        {
            url: 'https://example-ecommerce.com/product2',
            name: '机械键盘',
            targetPrice: 399
        }
    ],
    email: 'your-email@example.com'
};

// 配置邮件通知
const transporter = nodemailer.createTransport({
    service: 'gmail',
    auth: {
        user: 'your-email@gmail.com',
        pass: 'your-app-password'
    }
});

// 创建爬虫
const crawler = new PlaywrightCrawler({
    headless: true,
    async requestHandler({ page, request, log }) {
        const product = 监控配置.products.find(p => p.url === request.url);
        if (!product) return;
        
        // 等待价格元素加载
        await page.waitForSelector('.product-price');
        
        // 提取价格信息
        const priceText = await page.$eval('.product-price', el => el.textContent);
        const currentPrice = parseFloat(priceText.replace(/[^0-9.]/g, ''));
        const productName = await page.$eval('.product-title', el => el.textContent.trim());
        
        log.info(`监控商品: ${productName}, 当前价格: ${currentPrice}`);
        
        // 获取历史价格数据
        const历史价格 = (await Dataset.getData()) || [];
        
        // 记录新价格
        const priceRecord = {
            productName,
            url: request.url,
            price: currentPrice,
            timestamp: new Date().toISOString()
        };
        await Dataset.pushData(priceRecord);
        
        // 价格低于目标时发送通知
        if (currentPrice <= product.targetPrice) {
            await transporter.sendMail({
                from: '"价格监控器" <your-email@gmail.com>',
                to: 监控配置.email,
                subject: `【价格提醒】${productName} 已降至目标价格`,
                text: `商品: ${productName}\n当前价格: ${currentPrice}\n目标价格: ${product.targetPrice}\n链接: ${request.url}`
            });
            log.info(`价格低于目标,已发送通知: ${productName}`);
        }
    }
});

// 启动爬虫
await crawler.run(监控配置.products.map(p => p.url));

console.log('价格监控任务完成');

运行与结果查看

运行爬虫:

node src/price-monitor.js

爬取结果会保存在storage/datasets/default目录下,你可以通过以下代码查看历史价格趋势:

import { Dataset } from 'crawlee';

const数据 = await Dataset.getData();
const产品价格趋势 = {};

// 整理数据
for (const item of 数据) {
    if (!产品价格趋势[item.productName]) {
        产品价格趋势[item.productName] = [];
    }
    产品价格趋势[item.productName].push({
        price: item.price,
        timestamp: item.timestamp
    });
}

// 打印价格趋势
for (const [name, prices] of Object.entries(产品价格趋势)) {
    console.log(`\n${name} 价格趋势:`);
    prices.forEach(p => {
        console.log(`${p.timestamp}: ${p.price}`);
    });
}

6. 高级功能探索:让爬虫更智能

Crawlee提供了许多高级功能,帮助你构建更强大、更智能的爬虫系统。

自动发现与添加链接

使用enqueueLinks功能可以让爬虫自动发现并添加新的URL,实现整站爬取:

import { PlaywrightCrawler } from 'crawlee';

const crawler = new PlaywrightCrawler({
    async requestHandler({ page, enqueueLinks, request }) {
        log.info(`正在处理: ${request.url}`);
        
        // 提取当前页面的所有链接并添加到爬取队列
        await enqueueLinks({
            // 只提取特定区域的链接
            selector: '.article-list a',
            // 过滤链接,只保留同一域名下的文章页面
            filter: ({ url }) => {
                return url.hostname === 'example-blog.com' && 
                       url.pathname.startsWith('/articles/');
            },
            // 为新请求添加标签,便于识别
            label: 'article'
        });
        
        // 如果是文章页面,提取内容
        if (request.label === 'article') {
            // 提取文章内容...
        }
    }
});

await crawler.run(['https://example-blog.com/latest']);

处理无限滚动页面

许多现代网站使用无限滚动加载内容,Crawlee提供了专门的解决方案:

import { PlaywrightCrawler } from 'crawlee';

const crawler = new PlaywrightCrawler({
    async requestHandler({ page, log }) {
        log.info('开始抓取无限滚动页面');
        
        let previousHeight;
        const itemSelector = '.product-item';
        const maxItems = 100; // 限制最大抓取数量
        
        // 初始等待
        await page.waitForSelector(itemSelector);
        
        // 滚动直到加载所有内容或达到最大数量
        while (true) {
            // 提取当前页面的商品
            const items = await page.$$(itemSelector);
            log.info(`已加载 ${items.length} 个商品`);
            
            // 达到最大数量则停止
            if (items.length >= maxItems) break;
            
            // 滚动到页面底部
            previousHeight = await page.evaluate('document.body.scrollHeight');
            await page.evaluate('window.scrollTo(0, document.body.scrollHeight)');
            
            // 等待新内容加载
            await page.waitForFunction(`document.body.scrollHeight > ${previousHeight}`, {
                timeout: 10000 // 10秒超时
            }).catch(() => {
                // 超时,说明没有更多内容
                log.info('没有更多内容加载,停止滚动');
                return;
            });
        }
        
        // 提取所有商品数据
        const products = await page.$$eval(itemSelector, items => 
            items.map(item => ({
                name: item.querySelector('.name').textContent.trim(),
                price: item.querySelector('.price').textContent.trim()
            }))
        );
        
        log.info(`成功提取 ${products.length} 个商品数据`);
        await Dataset.pushData({ products, url: page.url() });
    }
});

await crawler.run(['https://example-infinite-scroll.com/products']);

无限滚动页面抓取示意图 Crawlee处理无限滚动页面示意图:通过模拟滚动行为,加载并提取动态内容

7. 部署与应用拓展:让爬虫持续工作

开发完成的爬虫需要部署到服务器才能发挥实际价值。Crawlee支持多种部署方式,满足不同场景需求。

Docker容器化部署

将爬虫打包成Docker容器,便于在任何支持Docker的环境中运行:

  1. 创建Dockerfile
FROM apify/actor-node:16

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm install --production

COPY . ./

CMD ["node", "src/main.js"]
  1. 构建并运行容器:
docker build -t my-crawlee-crawler .
docker run -v $(pwd)/storage:/usr/src/app/storage my-crawlee-crawler

云平台部署

Crawlee可以部署到各种云平台,如AWS、GCP、Azure等。以AWS Elastic Beanstalk为例:

  1. 创建Procfile
web: node src/main.js
  1. 使用EB CLI部署:
eb init
eb create production
eb deploy

实际应用场景拓展

Crawlee可以应用于多种实际场景,以下是几个常见案例:

1. 市场价格监控 定期抓取电商平台商品价格,分析价格趋势,在价格低谷时自动下单。

2. 新闻聚合系统 爬取多个新闻源,提取关键信息,按主题分类整理,构建个性化新闻流。

3. 社交媒体分析 收集社交媒体平台上的用户评论和话题讨论,进行情感分析和趋势预测。

4. 房地产信息聚合 爬取多个房产网站,整合房源信息,提供价格对比和趋势分析。

Crawlee爬取结果示例 Crawlee爬取的住宿信息数据示例:结构化存储便于后续分析和应用开发

总结

通过本文介绍的7个步骤,你已经掌握了Crawlee的核心功能和使用方法。从环境搭建到实战应用,从数据提取到反屏蔽策略,Crawlee提供了一套完整的解决方案,帮助你轻松应对各种网页抓取挑战。

记住,优秀的爬虫不仅要能获取数据,还要做到尊重网站规则、避免过度请求。合理配置爬取速度和并发数,使用代理和会话池,既是技术要求,也是对网站运营者的尊重。

现在,是时候用Crawlee来解决你遇到的实际问题了。无论是市场分析、数据聚合还是内容监控,Crawlee都能成为你的得力助手。开始你的爬虫项目吧,探索数据背后的无限可能!

官方文档:docs/introduction/02-first-crawler.mdx 示例代码库:docs/examples/ API参考:packages/core/src/

登录后查看全文
热门项目推荐
相关项目推荐