别再手动刷商品价格啦!作为电商运营,你是不是每天都要盯着竞品的价格变动?手动记录,效率低不说,还容易出错。今天,我就教你用Playwright,轻松搭建一套自动化电商价格监控系统,让你彻底解放双手!
为什么选择Playwright?
你可能会问,市面上自动化测试工具那么多,为啥偏偏要选Playwright?原因很简单:
- 支持多浏览器: Chrome、Firefox、Safari、Edge,主流浏览器全覆盖,保证监控的全面性。
- 跨平台: Windows、macOS、Linux,无论你用什么操作系统,都能轻松运行。
- 强大的选择器: CSS、XPath、文本,各种选择器应有尽有,轻松定位到你想要监控的价格元素。
- 自动等待: 自动等待元素加载,避免因网络延迟导致的错误。
- 易于使用: API简洁明了,上手快,学习成本低。
准备工作
在开始之前,你需要先安装Node.js和Playwright。如果你已经安装了Node.js,可以直接使用npm安装Playwright:
npm install -D @playwright/test
安装完成后,运行以下命令,安装浏览器驱动:
npx playwright install
核心代码:价格抓取
接下来,我们来编写核心代码,实现价格抓取功能。这里以某电商网站为例,假设我们要监控商品的价格元素CSS选择器是.price
。代码如下:
const { chromium } = require('playwright');
async function getPrice(url) {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(url);
// 等待价格元素加载
await page.waitForSelector('.price');
// 获取价格文本
const price = await page.$eval('.price', el => el.innerText);
await browser.close();
return price;
}
// 示例URL
const productUrl = 'https://www.example.com/product/123';
getPrice(productUrl)
.then(price => {
console.log(`商品价格:${price}`);
})
.catch(error => {
console.error('抓取价格失败:', error);
});
这段代码做了什么?
- 启动浏览器: 使用
chromium.launch()
启动一个Chrome浏览器实例。 - 新建页面: 使用
browser.newPage()
新建一个页面。 - 跳转到商品页面: 使用
page.goto(url)
跳转到指定的商品页面。 - 等待价格元素加载: 使用
page.waitForSelector('.price')
等待价格元素加载完成。这很重要,可以避免因页面加载延迟导致抓取失败。 - 获取价格文本: 使用
page.$eval('.price', el => el.innerText)
获取价格元素的文本内容。$eval
方法会在指定的选择器找到的元素上执行一个函数,这里我们使用el => el.innerText
获取元素的文本内容。 - 关闭浏览器: 使用
browser.close()
关闭浏览器实例,释放资源。 - 返回价格: 将抓取到的价格文本返回。
进阶:数据存储与价格比较
仅仅抓取价格还不够,我们需要将价格数据存储起来,并进行比较,才能知道价格是否发生了变化。这里我们使用JSON文件存储价格数据,你可以根据自己的需求选择其他数据库,如MySQL、MongoDB等。
const fs = require('fs');
// 数据存储文件
const dataFile = 'price_data.json';
async function monitorPrice(url) {
const price = await getPrice(url);
// 读取历史数据
let data = {};
try {
const fileContent = fs.readFileSync(dataFile, 'utf-8');
data = JSON.parse(fileContent);
} catch (error) {
// 文件不存在,忽略错误
}
const lastPrice = data[url];
if (lastPrice && price !== lastPrice) {
console.log(`价格变动!商品:${url},原价:${lastPrice},现价:${price}`);
// 在这里可以添加告警逻辑,例如发送邮件、短信等
} else {
console.log(`价格未变动。商品:${url},价格:${price}`);
}
// 更新数据
data[url] = price;
fs.writeFileSync(dataFile, JSON.stringify(data, null, 2));
}
// 监控频率(毫秒)
const interval = 60 * 60 * 1000; // 1小时
// 定时执行监控任务
setInterval(() => {
monitorPrice(productUrl);
}, interval);
这段代码做了这些事情:
- 读取历史数据: 从JSON文件中读取历史价格数据。如果文件不存在,则创建一个空对象。
- 比较价格: 将当前价格与历史价格进行比较,如果价格发生了变化,则输出价格变动信息,并可以添加告警逻辑,例如发送邮件、短信等。
- 更新数据: 将当前价格更新到JSON文件中。
- 定时执行: 使用
setInterval
函数,定时执行监控任务。这里我们设置监控频率为1小时,你可以根据自己的需求调整监控频率。
异常处理
在实际应用中,可能会遇到各种各样的异常情况,例如网络错误、页面结构变化等。为了保证监控系统的稳定性,我们需要对这些异常情况进行处理。
async function getPrice(url) {
try {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto(url);
await page.waitForSelector('.price', { timeout: 10000 }); // 设置超时时间
const price = await page.$eval('.price', el => el.innerText);
await browser.close();
return price;
} catch (error) {
console.error(`抓取${url}价格失败:`, error);
return null; // 返回null表示抓取失败
}
}
async function monitorPrice(url) {
const price = await getPrice(url);
if (price === null) {
console.log(`跳过${url},抓取价格失败`);
return;
}
// ... 剩余代码
}
这里我们做了两点改进:
- 添加超时时间: 在
page.waitForSelector
方法中,我们添加了timeout
选项,设置超时时间为10秒。如果10秒内价格元素没有加载完成,则会抛出一个异常。 - 捕获异常: 使用
try...catch
语句捕获可能出现的异常,并在catch
块中输出错误信息。如果抓取价格失败,则返回null
,并在monitorPrice
函数中跳过该商品。
告警机制
当价格发生变动时,我们需要及时收到通知。这里我们使用nodemailer发送邮件告警。首先,你需要安装nodemailer:
npm install nodemailer
然后,修改monitorPrice
函数,添加邮件告警逻辑:
const nodemailer = require('nodemailer');
// 邮件配置
const mailConfig = {
host: 'smtp.example.com',
port: 465,
secure: true, // 使用 SSL
auth: {
user: 'your_email@example.com',
pass: 'your_email_password'
}
};
// 创建邮件发送器
const transporter = nodemailer.createTransport(mailConfig);
async function sendEmail(subject, content) {
const mailOptions = {
from: 'your_email@example.com',
to: 'recipient_email@example.com',
subject: subject,
text: content
};
try {
await transporter.sendMail(mailOptions);
console.log('邮件发送成功');
} catch (error) {
console.error('邮件发送失败:', error);
}
}
async function monitorPrice(url) {
const price = await getPrice(url);
if (price === null) {
console.log(`跳过${url},抓取价格失败`);
return;
}
// 读取历史数据
let data = {};
try {
const fileContent = fs.readFileSync(dataFile, 'utf-8');
data = JSON.parse(fileContent);
} catch (error) {
// 文件不存在,忽略错误
}
const lastPrice = data[url];
if (lastPrice && price !== lastPrice) {
const subject = `价格变动!商品:${url}`;
const content = `商品:${url},原价:${lastPrice},现价:${price}`;
console.log(content);
await sendEmail(subject, content);
} else {
console.log(`价格未变动。商品:${url},价格:${price}`);
}
// 更新数据
data[url] = price;
fs.writeFileSync(dataFile, JSON.stringify(data, null, 2));
}
你需要替换mailConfig
中的邮箱配置信息,包括SMTP服务器地址、端口、用户名和密码。然后,在价格发生变动时,就会收到邮件告警。
更上一层楼:数据可视化
为了更直观地了解价格变动情况,我们可以将价格数据可视化。这里我们使用Chart.js绘制价格趋势图。首先,你需要安装Chart.js:
npm install chart.js
然后,创建一个HTML文件,用于显示价格趋势图:
<!DOCTYPE html>
<html>
<head>
<title>价格趋势图</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<canvas id="priceChart"></canvas>
<script>
// 从JSON文件读取价格数据
async function loadData() {
const response = await fetch('price_data.json');
const data = await response.json();
// 准备数据
const labels = Object.keys(data);
const prices = Object.values(data);
// 创建图表
const ctx = document.getElementById('priceChart').getContext('2d');
const chart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: '价格',
data: prices,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
}
}
});
}
loadData();
</script>
</body>
</html>
这段代码会从price_data.json
文件中读取价格数据,并使用Chart.js绘制一个折线图,显示价格趋势。你需要将price_data.json
文件放在与HTML文件相同的目录下,并在浏览器中打开HTML文件,即可看到价格趋势图。
总结
通过以上步骤,我们就搭建了一个简单的电商价格监控系统。你可以根据自己的需求,对系统进行扩展和完善,例如:
- 支持更多电商网站: 修改代码,适配不同的电商网站的页面结构。
- 支持更多商品: 将商品URL存储到数据库中,批量监控多个商品。
- 更智能的告警: 设置更灵活的告警规则,例如价格跌幅超过一定比例时才发送告警。
- 更丰富的数据可视化: 绘制更丰富的数据可视化图表,例如价格分布图、价格波动幅度图等。
希望这篇文章能帮助你搭建自己的电商价格监控系统,提高工作效率,更好地掌握市场动态!记住,自动化才是王道!别再傻傻地手动刷价格啦!