如何在 Pipedream 上实现 Google Trends 跟踪器?

Advanced Data Extraction Specialist
在数字营销、SEO 和新兴趋势分析领域,随时掌握 Google 趋势的变化至关重要。然而,手动检查和整理关键字趋势数据既耗时又容易出错且效率低下。为了解决这个问题,我们构建了一个自动化报告系统,集成了 Pipedream、Scrapeless API 和 Discord Webhook,以简化整个过程——从关键字收集和数据处理到结果交付。
本文将详细介绍这一自动化系统的组成部分和实施过程。
主要特点
-
自动化关键字趋势分析:使用 Scrapeless 获取过去一个月的趋势数据。
-
智能评分与处理:自动计算每个关键字的平均受欢迎程度和趋势波动。
-
可视化分析报告:生成结构化报告并带有可视化效果,直接发送到 Discord。
前提条件
- 注册 Scrapeless 并获取您的 API 密钥。
- 找到您的 API 令牌 并复制以备后用。

⚠️ 注意: 保持您的 API 令牌安全,并不要与他人分享。
- 登录 Pipedream
- 点击 “+ 新工作流” 来创建一个新的工作流。

如何创建 Google 趋势自动化报告系统(Pipedream + Scrapeless + Discord)
工作流结构
步骤名称 | 类型 | 功能 |
---|---|---|
trigger |
调度 | 根据调度触发工作流(例如,每小时) |
http |
Node.js 代码 | 向 Scrapeless 提交抓取任务并获取结果 |
code_step |
Node.js 代码 | 解析和处理抓取的数据 |
discord_notify |
Node.js 代码 | 通过 webhook 将分析结果发送到 Discord |
步骤 1:定时触发器
选择触发器类型为“调度”,并设置触发时间以自动执行该工作流,每周日 UTC 时间 16:00。

步骤 2 - http(请求 Scrapeless 抓取关键字趋势)

- 添加一个 Node.js 代码步骤。以下是集成 Scrapeless API 调用逻辑的代码示例
import { axios } from "@pipedream/platform"
export default defineComponent({
async run({ steps, $ }) {
const keywords = ["AI", "Machine Learning", "Data Science"];
const allResults = {};
for (const keyword of keywords) {
console.log(`正在处理关键字: ${keyword}`);
const payload = {
actor: "scraper.google.trends",
input: {
q: keyword,
date: "today 1-m",
data_type: "interest_over_time",
hl: "en",
tz: "420",
geo: "",
cat: "",
property: "",
},
proxy: {
country: "",
}
};
try {
const response = await axios($, {
method: 'POST',
url: 'https://api.scrapeless.com/api/v1/scraper/request',
headers: {
'Content-Type': 'application/json',
'x-api-token': 'Scrapeless API KEY'
},
data: payload
});
console.log(`关键字 ${keyword} 的响应:`, response);
if (response.job_id) {
console.log(`为 ${keyword} 创建了任务,ID: ${response.job_id}`);
let attempts = 0;
const maxAttempts = 12;
let jobResult = null;
while (attempts < maxAttempts) {
await new Promise(resolve => setTimeout(resolve, 10000));
attempts++;
try {
const resultResponse = await axios($, {
method: 'GET',
url: `https://api.scrapeless.com/api/v1/scraper/result/${response.job_id}`,
headers: {
'x-api-token': 'Scrapeless API KEY'
}
});
console.log(`第 ${attempts} 次尝试 ${keyword}:`, resultResponse);
if (resultResponse.status === 'completed') {
jobResult = resultResponse.result;
```javascript
console.log(`工作完成,关键词为 ${keyword}:`, jobResult);
break;
} else if (resultResponse.status === 'failed') {
console.error(`工作失败,关键词为 ${keyword}:`, resultResponse);
break;
} else {
console.log(`工作仍在进行中,关键词为 ${keyword}, 状态: ${resultResponse.status}`);
}
} catch (error) {
console.error(`检查关键词 ${keyword} 的工作状态时出错:`, error);
}
}
if (jobResult) {
allResults[keyword] = jobResult;
} else {
allResults[keyword] = {
error: `工作超时或在 ${attempts} 次尝试后失败`,
job_id: response.job_id
};
}
} else {
allResults[keyword] = response;
}
} catch (error) {
console.error(`关键词 ${keyword} 出错:`, error);
allResults[keyword] = {
error: `请求失败: ${error.message}`
};
}
}
console.log("最终结果:", JSON.stringify(allResults, null, 2));
return allResults;
},
})
注意:
- 此步骤使用 Scrapeless 的
scraper.google.trends
角色来获取每个关键词的 "interest_over_time" 数据。 - 默认关键词为:
["AI", "机器学习", "数据科学"]
。您可以根据需要替换它们。 - 将
YOUR_API_TOKEN
替换为您的实际 API 令牌。
步骤 3 - 代码步骤 (处理爬取的数据)

- 添加另一个 Node.js 代码步骤。以下是代码示例
export default defineComponent({
async run({ steps, $ }) {
const httpData = steps.http.$return_value;
console.log("接收到的 HTTP 数据:", JSON.stringify(httpData, null, 2));
const processedData = {};
const timestamp = new Date().toISOString();
for (const [keyword, data] of Object.entries(httpData)) {
console.log(`处理 ${keyword}:`, data);
let timelineData = null;
let isPartial = false;
if (data?.interest_over_time?.timeline_data) {
timelineData = data.interest_over_time.timeline_data;
isPartial = data.interest_over_time.isPartial || false;
} else if (data?.timeline_data) {
timelineData = data.timeline_data;
} else if (data?.interest_over_time && Array.isArray(data.interest_over_time)) {
timelineData = data.interest_over_time;
}
if (timelineData && Array.isArray(timelineData) && timelineData.length > 0) {
console.log(`找到 ${keyword} 的 ${timelineData.length} 个数据点`);
const values = timelineData.map(item => {
const value = item.value || item.interest || item.score || item.y || 0;
return parseInt(value) || 0;
});
const validValues = values.filter(v => v >= 0);
if (validValues.length > 0) {
const average = Math.round(validValues.reduce((sum, val) => sum + val, 0) / validValues.length);
const trend = validValues.length >= 2 ? validValues[validValues.length - 1] - validValues[0] : 0;
const max = Math.max(...validValues);
const min = Math.min(...validValues);
const recentValues = validValues.slice(-7);
const earlyValues = validValues.slice(0, 7);
const recentAvg = recentValues.length > 0 ? recentValues.reduce((a, b) => a + b, 0) / recentValues.length : 0;
const earlyAvg = earlyValues.length > 0 ? earlyValues.reduce((a, b) => a + b, 0) / earlyValues.length : 0;
const weeklyTrend = Math.round(recentAvg - earlyAvg);
processedData[keyword] = {
keyword,
average,
trend,
weeklyTrend,
values: validValues,
max,
min,
dataPoints: validValues.length,
isPartial,
timestamps: timelineData.map(item => item.time || item.date || item.timestamp),
lastValue: validValues[validValues.length - 1],
firstValue: validValues[0],
volatility: Math.round(Math.sqrt(validValues.map(x => Math.pow(x - average, 2)).reduce((a, b) => a + b, 0) / validValues.length)),
status: '成功'
};
} else {
processedData[keyword] = {
keyword,
average: 0,
trend: 0,
weeklyTrend: 0,
values: [],
max: 0,
min: 0,
dataPoints: 0,
isPartial: false,
error: "时间线数据中未找到有效值",
status: '错误',
rawTimelineLength: timelineData.length
};
}
} else {
processedData[keyword] = {
关键字,
平均值:0,
趋势:0,
每周趋势:0,
值:[],
最大值:0,
最小值:0,
数据点:0,
部分数据:false,
错误: "未找到时间线数据",
状态:'错误',
可用键:数据 ? Object.keys(data) : []
};
}
}
const summary = {
时间戳,
总关键字:Object.keys(processedData).length,
成功关键字:Object.values(processedData).filter(d => d.status === 'success').length,
周期:"今天 1-m",
数据:processedData
};
console.log("最终处理的数据:", JSON.stringify(summary, null, 2));
return summary;
},
})
---
它将根据 Scrapeless 返回的数据计算以下指标:
* **平均值**
* **每周趋势变化**(过去 7 天与前 7 天)
* **最大/最小值**
* **波动性**
**注意:**
* 每个关键字将生成一个详细分析对象,便于可视化和进一步通知。
### 第 4 步 - discord_notify(将分析报告推送到 Discord)

1. 添加最后一个 Node.js 步骤,以下是代码示例
import { axios } from "@pipedream/platform"
export default defineComponent({
async run({ steps, $ }) {
const processedData = steps.Code_step.$return_value;
const discordWebhookUrl = "https://discord.com/api/webhooks/1380448411299614821/MXzmQ14TOPK912lWhle_7qna2VQJBjWrdCkmHjdEloHKhYXw0fpBrp-0FS4MDpDB8tGh";
console.log("处理 Discord 数据:", JSON.stringify(processedData, null, 2));
const currentDate = new Date().toLocaleString('zh-CN');
const keywords = Object.values(processedData.data);
const successful = keywords.filter(k => k.status === 'success');
let bestPerformer = null;
let worstPerformer = null;
let strongestTrend = null;
if (successful.length > 0) {
bestPerformer = successful.reduce((max, curr) => curr.average > max.average ? curr : max);
worstPerformer = successful.reduce((min, curr) => curr.average < min.average ? curr : min);
strongestTrend = successful.reduce((max, curr) => Math.abs(curr.weeklyTrend) > Math.abs(max.weeklyTrend) ? curr : max);
}
const discordMessage = {
content: `📊 **谷歌趋势报告** - ${currentDate}`,
embeds: [
{
title: "🔍 趋势分析",
color: 3447003,
timestamp: new Date().toISOString(),
fields: [
{
name: "📈 概要",
value: `**周期:** 上个月\n**分析的关键字:** ${processedData.totalKeywords}\n**成功:** ${processedData.successfulKeywords}/${processedData.totalKeywords}`,
inline: false
}
]
}
]
};
if (successful.length > 0) {
const keywordDetails = successful.map(data => {
const trendIcon = data.weeklyTrend > 5 ? '🚀' :
data.weeklyTrend > 0 ? '📈' :
data.weeklyTrend < -5 ? '📉' :
data.weeklyTrend < 0 ? '⬇️' : '➡️';
const performanceIcon = data.average > 70 ? '🔥' :
data.average > 40 ? '✅' :
data.average > 20 ? '🟡' : '🔴';
return {
name: `${performanceIcon} ${data.keyword}`,
value: `**得分:** ${data.average}/100\n**趋势:** ${trendIcon} ${data.weeklyTrend > 0 ? '+' : ''}${data.weeklyTrend}\n**范围:** ${data.min}-${data.max}`,
inline: true
};
});
discordMessage.embeds[0].fields.push(...keywordDetails);
}
if (bestPerformer && successful.length > 1) {
discordMessage.embeds.push({
title: "🏆 关键亮点",
color: 15844367,
fields: [
{
name: "🥇 最佳表现者",
value: `**${bestPerformer.keyword}** (${bestPerformer.average}/100)`,
inline: true
},
{
name: "📊 最低得分",
value: `**${worstPerformer.keyword}** (${worstPerformer.average}/100)`,
inline: true
},
{
name: "⚡ 最强趋势",
value: `**${strongestTrend.keyword}** (${strongestTrend.weeklyTrend > 0 ? '+' : ''}${strongestTrend.weeklyTrend})`,
inline: true
}
]
});
}
const failed = keywords.filter(k => k.status === 'error');
if (failed.length > 0) {
discordMessage.embeds.push({
title: "❌ 错误",
color: 15158332,
fields: failed.map(data => ({
name: data.keyword,
value: data.error || "未知错误",
inline: true
}))
});
zh
console.log("要发送的Discord消息:", JSON.stringify(discordMessage, null, 2));
try {
const response = await axios($, {
method: 'POST',
url: discordWebhookUrl,
headers: {
'Content-Type': 'application/json'
},
data: discordMessage
});
console.log("Discord webhook响应:", response);
return {
webhook_sent: true,
platform: "discord",
message_sent: true,
keywords_analyzed: processedData.totalKeywords,
successful_keywords: processedData.successfulKeywords,
timestamp: currentDate,
discord_response: response
};
} catch (error) {
console.error("Discord webhook错误:", error);
const simpleMessage = {
content: `📊 **Google Trends报告 - ${currentDate}**\n\n` +
`📈 **结果 (${processedData.successfulKeywords}/${processedData.totalKeywords}):**\n` +
successful.map(data =>
`• **${data.keyword}**: ${data.average}/100 (${data.weeklyTrend > 0 ? '+' : ''}${data.weeklyTrend})`
).join('\n') +
(failed.length > 0 ? `\n\n❌ **错误:** ${failed.map(d => d.keyword).join(', ')}` : '')
};
try {
const fallbackResponse = await axios($, {
method: 'POST',
url: discordWebhookUrl,
headers: {
'Content-Type': 'application/json'
},
data: simpleMessage
});
return {
webhook_sent: true,
platform: "discord",
message_sent: true,
fallback_used: true,
discord_response: fallbackResponse
};
} catch (fallbackError) {
console.error("Discord备用错误:", fallbackError);
return {
webhook_sent: false,
platform: "discord",
error: error.message,
fallback_error: fallbackError.message,
data_summary: {
keywords: processedData.totalKeywords,
successful: processedData.successfulKeywords,
best_performer: bestPerformer?.keyword,
best_score: bestPerformer?.average
}
};
}
},
2. 将“YOUR DISCORD WEBHOOK URL”替换为您自己的Webhook地址
3. 单击“部署”以运行您的工作流程并获取实时信息。
### 第5步 - 接收实时Google Trends信息
您可以直接在Discord中接收检查关键词的数据:

**以下是完整的链接图:**

> **✅ 现在可用:Scrapeless在Pipedream的官方集成**
>
> Scrapeless现在在Pipedream的集成中心正式上线!只需几次点击,您就可以直接从Pipedream工作流程中调用我们强大的Google Trends API——无需设置,无需服务器。
>
> 无论您是在构建实时仪表板、自动化市场情报,还是为自定义分析提供支持,这个集成为您提供了最快的通往生产级趋势监控的路径。
>
> 👉 立即开始构建: **pipedream.com/apps/scrapeless**
拖放并部署您的下一个趋势驱动工作流程——今天就开始。
非常适合需要快速获得可操作性洞察的开发人员、分析师和增长团队。
## 总结
通过Pipedream、Scrapeless API和Discord的强大结合,我们构建了一个不需要人工干预、每天自动执行的Google Trends报告系统。这不仅大大提高了工作效率,还使营销决策更具数据基础。
如果您也需要构建类似的数据自动化分析系统,不妨尝试这种技术组合!
---
Scrapeless完全遵守适用法律法规,仅依据平台服务条款访问公开可用数据。此解决方案旨在用于合法的商业智能和研究目的。
在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。