一图胜千言:OpenClaw + ECharts 自动抓取多平台数据,每日可视化报表直达手机
从"爬数据"到"看报表",全自动化,无需人工干预
作为电商运营或数据分析师,你是否每天早晨都要重复同样的工作:打开淘宝、京东、拼多多的商家后台,手动复制销售额、访客数,然后黏贴到Excel里,再生成折线图发给老板?这不仅枯燥,而且容易出错,更占用了宝贵的思考时间。
如果能有一个助手,每天定时自动登录各平台,抓取数据,生成漂亮的图表,然后准时推送到你的飞书或邮箱,那该多好?
本文将带你利用 OpenClaw 这个强大的自动化网关,结合 ECharts 数据可视化库,打造一套完全自动化的多平台数据日报系统。你只需每天早上醒来,打开手机就能看到昨天店铺的经营趋势图。
1. 引言:从"数据抓取"到"可视化输出"的端到端自动化
在数据驱动的今天,获取数据只是第一步,如何让数据"说话"才是关键。传统的流程是:抓取数据 → 清洗整理 → 手动制图 → 发送报告。这个过程每一步都需要人工参与。
而借助 OpenClaw 的 Skill(技能) 机制,我们可以将这一系列操作封装成一个自动化任务:
- 定时触发:由系统的Cron任务按设定时间启动。
- 数据抓取:Skill 调用各平台API或模拟登录爬取数据。
- 数据处理:清洗、标准化、合并。
- 可视化生成:利用 ECharts 在服务端生成 HTML 图表。
- 多渠道分发:通过飞书机器人、邮件等推送到用户手中。
- 数据归档:将历史数据存入 SQLite,支持趋势查询。
整个过程无需人工干预,真正实现"数据报表,每天自动送到眼前"。
2. 实战案例:电商店铺数据日报(淘宝 + 京东 + 拼多多)
假设你经营一家小型电商团队,需要每天监控三个主流平台的店铺数据。我们希望每日上午9点自动生成一份包含以下内容的日报:
- 各平台昨日销售额、访客数、转化率。
- 对比前一日的变化百分比。
- 近7日销售额趋势图(折线图)。
最终效果:在飞书上收到一张精美的卡片,点击可以查看完整HTML报表。
3. 步骤1:开发数据抓取 Skill
任何自动化都始于数据的获取。OpenClaw 的 Skill 是一个可执行模块,可以用 Python、Node.js 等编写。这里我们以 Node.js 为例,因为它能无缝集成 ECharts 的 Node 版本。
3.1 核心代码:调用电商平台 API / 爬虫
电商平台数据获取通常有两种方式:
- 官方API:如淘宝开放平台、京东宙斯、拼多多多多客。优点是稳定,但需要申请权限且可能有调用限额。
- 模拟登录爬虫:对于没有API权限的账号,可以使用 Puppeteer 模拟浏览器登录后台抓取数据。优点是门槛低,但容易被反爬。
示例:淘宝API调用(需申请)
javascript
// skill/taobao_fetcher.js
const axios = require('axios');
const crypto = require('crypto');
async function fetchTaobaoData(date) {
const appKey = 'your_app_key';
const appSecret = 'your_app_secret';
const sessionKey = 'your_session_key';
const method = 'taobao.tbk.shop.get'; // 假设是获取店铺信息的API
const params = {
method,
app_key: appKey,
timestamp: new Date().toISOString().replace(/[^0-9\-T:\.]/g, '').substring(0,19),
format: 'json',
v: '2.0',
sign_method: 'hmac',
session: sessionKey,
fields: 'shop_title,seller_nick,pic_url,created',
q: '女装' // 查询条件
};
// 计算签名(省略具体实现)
const sign = generateSign(params, appSecret);
params.sign = sign;
const response = await axios.get('https://eco.taobao.com/router/rest', { params });
return response.data;
}
示例:Puppeteer模拟登录拼多多商家后台
javascript
// skill/pinduoduo_fetcher.js
const puppeteer = require('puppeteer');
async function fetchPinduoduoData(date) {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
// 设置UA
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...');
// 登录流程(假设已保存Cookie)
await page.goto('https://mms.pinduoduo.com/');
await page.setCookie(...); // 设置登录态Cookie
// 跳转到数据页面
await page.goto('https://mms.pinduoduo.com/statistic/overview');
// 等待数据加载
await page.waitForSelector('.sales-amount');
// 提取数据
const sales = await page.$eval('.sales-amount', el => el.textContent);
const visitors = await page.$eval('.visitor-count', el => el.textContent);
await browser.close();
return {
platform: '拼多多',
date: date,
sales: parseFloat(sales.replace(/[^0-9\.]/g, '')),
visitors: parseInt(visitors)
};
}
3.2 数据标准化:统一输出JSON格式
为了让后续处理统一,无论从哪个平台获取的数据,Skill 都应输出标准格式的 JSON 数组:
json
{
"date": "2023-10-26",
"platform": "淘宝",
"sales": 12345.67,
"visitors": 890,
"orders": 120
}
我们可以在主调度 Skill 中并发调用三个平台的抓取函数,然后将结果合并为一个数组。
4. 步骤2:集成 ECharts 生成可视化
有了数据,接下来就是生成图表。ECharts 提供了 Node.js 版本 echarts,可以在服务端渲染出 SVG 或 HTML。
4.1 Skill 中调用 ECharts Node.js 版,生成 HTML 报表
首先安装依赖:
bash
npm install echarts
然后编写一个函数,接收合并后的数据,生成包含图表的完整 HTML。
javascript
// skill/generate_report.js
const echarts = require('echarts');
function generateHTMLReport(dataArray) {
// 按日期分组,准备折线图数据
const dates = [...new Set(dataArray.map(d => d.date))].sort();
const platforms = ['淘宝', '京东', '拼多多'];
const series = platforms.map(platform => {
const platformData = dataArray.filter(d => d.platform === platform);
return {
name: platform,
type: 'line',
data: dates.map(date => {
const record = platformData.find(d => d.date === date);
return record ? record.sales : null;
})
};
});
// 生成 ECharts 配置
const option = {
title: { text: '近7日各平台销售额趋势' },
tooltip: { trigger: 'axis' },
legend: { data: platforms },
xAxis: { type: 'category', data: dates },
yAxis: { type: 'value' },
series: series
};
// 使用 ECharts 生成 HTML
const echartsScript = require('echarts/dist/echarts.min.js'); // 或者从CDN引入
const html = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>电商数据日报</title>
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<style>
body { font-family: sans-serif; margin: 20px; }
.chart-container { width: 100%; height: 400px; margin-bottom: 30px; }
.summary-table { border-collapse: collapse; width: 100%; }
.summary-table th, .summary-table td { border: 1px solid #ddd; padding: 8px; text-align: center; }
.summary-table th { background-color: #f2f2f2; }
@media (max-width: 600px) { .chart-container { height: 300px; } }
</style>
</head>
<body>
<h1>电商数据日报 - ${new Date().toLocaleDateString()}</h1>
<div id="main" class="chart-container"></div>
<script>
var myChart = echarts.init(document.getElementById('main'));
var option = ${JSON.stringify(option)};
myChart.setOption(option);
</script>
<h2>详细数据</h2>
<table class="summary-table">
<thead><tr><th>日期</th><th>平台</th><th>销售额</th><th>访客数</th><th>订单数</th></tr></thead>
<tbody>
${dataArray.map(row => `<tr><td>${row.date}</td><td>${row.platform}</td><td>${row.sales}</td><td>${row.visitors}</td><td>${row.orders || '-'}</td></tr>`).join('')}
</tbody>
</table>
</body>
</html>
`;
return html;
}
4.2 自定义样式:适配不同终端(PC/手机)
上面的 HTML 中已经包含了简单的媒体查询,当在手机端查看时,图表高度会自动调整为 300px,以保证显示效果。你也可以进一步优化,比如使用 Viewport 设置,或者针对飞书卡片的内嵌浏览器做适配。
5. 步骤3:自动化分发
报表生成后,需要推送到用户手中。OpenClaw 内置了多种渠道的发送能力。
5.1 定时生成(Cron)+ 飞书/邮件推送
在 OpenClaw 中,我们可以创建一个定时任务,每天上午9点执行。
bash
# 在 OpenClaw 中创建定时任务
openclaw schedule add daily-report "0 9 * * *" "skill:ecommerce_report"
这里的 skill:ecommerce_report 是我们编写的主 Skill,它依次调用抓取、生成报表、发送的流程。
发送到飞书
飞书机器人支持发送富文本消息,我们可以将生成的 HTML 上传为临时文件,然后发送一个包含链接的消息卡片。
javascript
// skill/send_to_feishu.js
const axios = require('axios');
async function sendFeishuMessage(htmlContent, webhookUrl) {
// 可以将HTML上传到临时存储,获得链接
const fileUrl = await uploadToTempStorage(htmlContent, 'report.html');
const message = {
msg_type: 'interactive',
card: {
elements: [
{
tag: 'div',
text: { content: `您的电商数据日报已生成,[点击查看](${fileUrl})` }
}
]
}
};
await axios.post(webhookUrl, message);
}
发送邮件
使用 Node.js 的 nodemailer 发送 HTML 邮件。
javascript
const nodemailer = require('nodemailer');
async function sendEmail(htmlContent, to) {
const transporter = nodemailer.createTransport({
host: 'smtp.example.com',
port: 587,
secure: false,
auth: { user: 'user@example.com', pass: 'password' }
});
await transporter.sendMail({
from: 'report@example.com',
to: to,
subject: '电商数据日报',
html: htmlContent
});
}
5.2 历史数据归档:SQLite 存储,支持趋势分析
为了支持"近7日趋势"等查询,我们需要将每天抓取的数据存储起来。使用 SQLite 轻量级数据库非常适合。
javascript
// skill/db_helper.js
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database('/path/to/data.db');
// 创建表
db.run(`CREATE TABLE IF NOT EXISTS daily_stats (
date TEXT,
platform TEXT,
sales REAL,
visitors INTEGER,
orders INTEGER,
PRIMARY KEY (date, platform)
)`);
// 插入或替换数据
function upsertData(record) {
const stmt = db.prepare(`REPLACE INTO daily_stats (date, platform, sales, visitors, orders) VALUES (?, ?, ?, ?, ?)`);
stmt.run(record.date, record.platform, record.sales, record.visitors, record.orders);
stmt.finalize();
}
// 查询最近7天数据
function getLast7Days() {
return new Promise((resolve, reject) => {
const today = new Date().toISOString().slice(0,10);
const sevenDaysAgo = new Date(Date.now() - 6*24*60*60*1000).toISOString().slice(0,10);
db.all(`SELECT * FROM daily_stats WHERE date BETWEEN ? AND ? ORDER BY date, platform`, [sevenDaysAgo, today], (err, rows) => {
if (err) reject(err);
else resolve(rows);
});
});
}
这样,每次生成报表前,我们可以先从数据库读取历史数据,再加上当天新抓取的数据,一起生成趋势图。
6. 优化点
在实际部署中,会遇到各种问题,以下是一些常见优化策略。
6.1 反爬机制应对
对于使用 Puppeteer 的爬虫,平台往往有反爬措施:
- UA伪装:使用常见的浏览器 User-Agent。
- 请求间隔:在页面跳转或操作之间加入随机延时,避免频率过高。
- Cookie池:维护多个账号的 Cookie,随机切换,降低单个账号被风控的风险。
- 代理IP:对于严格的反爬,可以接入代理IP池,每次请求使用不同IP。
示例:在 Puppeteer 中添加随机延时
javascript
await page.waitForTimeout(Math.random() * 2000 + 1000); // 1-3秒随机
6.2 数据异常处理
抓取的数据可能不完整或存在异常值,需要进行清洗。
- 缺失值填充:如果某天某个平台数据缺失(比如API调用失败),可以用前一天的数值填充,或者标记为null并在图表中显示断点。
- 异常值过滤:比如销售额突然暴增10倍,可能是数据错误,可以设置阈值,超过阈值则告警并人工介入。
javascript
function cleanData(records) {
return records.map(r => {
// 如果销售额为0或null,尝试用前一天填充(需要跨记录逻辑)
if (!r.sales || r.sales < 0) {
// 这里简化处理,直接设为null
r.sales = null;
}
// 过滤异常大的销售额(假设不超过前一天的两倍)
// 这需要更复杂的上下文,这里省略
return r;
});
}
7. 完整的报表生成 Skill 核心逻辑
下面是一个整合了以上所有步骤的主 Skill 代码框架(Node.js):
javascript
// skill/ecommerce_report.js
const { fetchTaobao } = require('./taobao_fetcher');
const { fetchJD } = require('./jd_fetcher');
const { fetchPinduoduo } = require('./pinduoduo_fetcher');
const { generateHTMLReport } = require('./generate_report');
const { sendFeishu } = require('./send_to_feishu');
const { upsertData, getLast7Days } = require('./db_helper');
async function main() {
try {
const today = new Date().toISOString().slice(0,10);
// 并发抓取三大平台数据
const [taobaoData, jdData, pddData] = await Promise.allSettled([
fetchTaobao(today),
fetchJD(today),
fetchPinduoduo(today)
]);
const records = [];
if (taobaoData.status === 'fulfilled') records.push(taobaoData.value);
else console.error('淘宝抓取失败', taobaoData.reason);
if (jdData.status === 'fulfilled') records.push(jdData.value);
else console.error('京东抓取失败', jdData.reason);
if (pddData.status === 'fulfilled') records.push(pddData.value);
else console.error('拼多多抓取失败', pddData.reason);
// 存入数据库
records.forEach(r => upsertData(r));
// 获取近7天数据用于图表
const history = await getLast7Days();
// 生成HTML报表
const html = generateHTMLReport(history);
// 发送到飞书
await sendFeishu(html, 'https://open.feishu.cn/open-apis/bot/v2/hook/xxxx');
// 可选:发送邮件
// await sendEmail(html, 'boss@example.com');
console.log('日报生成并发送成功');
} catch (error) {
console.error('执行失败', error);
// 可以发送告警
}
}
// 如果是直接运行则执行
if (require.main === module) {
main();
}
总结
通过 OpenClaw + ECharts 的组合,我们将原本繁琐的手工日报工作完全自动化。从数据抓取、清洗、可视化到分发,全部由代码完成。这不仅解放了人力,还减少了出错的可能,让数据决策变得更加及时和高效。
你可以根据自身需求扩展这个框架,比如接入更多数据源(抖音、快手),或者增加更复杂的分析(同比、环比)。希望本文能给你带来启发,打造属于自己的数据自动化系统。
你在数据可视化自动化中遇到过哪些难题?欢迎留言交流!