7个步骤掌握Crawlee:从快速上到手实战案例
你是否曾因网页结构复杂而放弃爬虫开发?是否在面对动态加载内容时感到无从下手?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还能模拟真实浏览器指纹和用户行为:
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的环境中运行:
- 创建
Dockerfile:
FROM apify/actor-node:16
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --production
COPY . ./
CMD ["node", "src/main.js"]
- 构建并运行容器:
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为例:
- 创建
Procfile:
web: node src/main.js
- 使用EB CLI部署:
eb init
eb create production
eb deploy
实际应用场景拓展
Crawlee可以应用于多种实际场景,以下是几个常见案例:
1. 市场价格监控 定期抓取电商平台商品价格,分析价格趋势,在价格低谷时自动下单。
2. 新闻聚合系统 爬取多个新闻源,提取关键信息,按主题分类整理,构建个性化新闻流。
3. 社交媒体分析 收集社交媒体平台上的用户评论和话题讨论,进行情感分析和趋势预测。
4. 房地产信息聚合 爬取多个房产网站,整合房源信息,提供价格对比和趋势分析。
Crawlee爬取的住宿信息数据示例:结构化存储便于后续分析和应用开发
总结
通过本文介绍的7个步骤,你已经掌握了Crawlee的核心功能和使用方法。从环境搭建到实战应用,从数据提取到反屏蔽策略,Crawlee提供了一套完整的解决方案,帮助你轻松应对各种网页抓取挑战。
记住,优秀的爬虫不仅要能获取数据,还要做到尊重网站规则、避免过度请求。合理配置爬取速度和并发数,使用代理和会话池,既是技术要求,也是对网站运营者的尊重。
现在,是时候用Crawlee来解决你遇到的实际问题了。无论是市场分析、数据聚合还是内容监控,Crawlee都能成为你的得力助手。开始你的爬虫项目吧,探索数据背后的无限可能!
官方文档:docs/introduction/02-first-crawler.mdx 示例代码库:docs/examples/ API参考:packages/core/src/
GLM-5智谱 AI 正式发布 GLM-5,旨在应对复杂系统工程和长时域智能体任务。Jinja00
GLM-5-w4a8GLM-5-w4a8基于混合专家架构,专为复杂系统工程与长周期智能体任务设计。支持单/多节点部署,适配Atlas 800T A3,采用w4a8量化技术,结合vLLM推理优化,高效平衡性能与精度,助力智能应用开发Jinja00
jiuwenclawJiuwenClaw 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。Python0193- QQwen3.5-397B-A17BQwen3.5 实现了重大飞跃,整合了多模态学习、架构效率、强化学习规模以及全球可访问性等方面的突破性进展,旨在为开发者和企业赋予前所未有的能力与效率。Jinja00
AtomGit城市坐标计划AtomGit 城市坐标计划开启!让开源有坐标,让城市有星火。致力于与城市合伙人共同构建并长期运营一个健康、活跃的本地开发者生态。01
awesome-zig一个关于 Zig 优秀库及资源的协作列表。Makefile00