🥳加入无抓取社区领取您的免费试用,访问我们强大的网页抓取工具包!
返回博客

谷歌趋势自动报告系统(Pipedream + Scrapeless + Discord)

Emily Chen
Emily Chen

Advanced Data Extraction Specialist

05-Jun-2025

在数字营销、搜索引擎优化和新兴趋势分析领域,保持对Google Trends的变化的最新了解至关重要。然而,手动检查和整理关键词趋势数据既耗时,又容易出错,效率低下。为了解决这个问题,我们构建了一个自动化报告系统,集成了Pipedream、Scrapeless API和Discord Webhook,以简化整个过程——从关键词收集和数据处理到结果交付。

本篇文章将详细介绍该自动化系统的组件和实现。

主要功能

  • 自动化关键词趋势分析:使用Scrapeless获取过去一个月的趋势数据。

  • 智能评分与处理:自动计算每个关键词的平均热度和趋势波动。

  • 视觉分析报告:生成结构化的带视觉效果的报告,并直接发送到Discord。


前提条件

  1. **在Scrapeless上注册**并获取你的API密钥。
  2. 找到你的API令牌并复制以备后用。
找到你的API令牌

⚠️ **注意:**保持你的API令牌安全,不要与他人分享


  1. 登录Pipedream
  2. 点击“+ 新工作流”以创建新的工作流。
+ 新工作流

如何创建一个Google Trends自动化报告系统(Pipedream + Scrapeless + Discord)

工作流结构

步骤名称 类型 功能
trigger Schedule 定时触发工作流(例如,每小时触发一次)
http Node.js代码 向Scrapeless提交抓取任务并获取结果
code_step Node.js代码 解析和处理抓取的数据
discord_notify Node.js代码 通过Webhook将分析结果发送到Discord

步骤1:计划触发器

选择触发器类型为“定时”,并将触发时间设置为每周日UTC时间16:00自动执行此工作流。

选择触发器类型

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

http(请求Scrapeless抓取关键词趋势)
  1. 添加一个Node.js代码步骤。以下是集成Scrapeless API调用逻辑的代码示例:
Copy
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(`关键词${keyword}的第${attempts}次尝试:`, resultResponse);
              
              if (resultResponse.status === 'completed') {
                jobResult = resultResponse.result;
```zh
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", "机器学习", "数据科学"]。您可以根据需要替换它们。
  • 用您的实际 API 令牌替换 YOUR_API_TOKEN

第 3 步 - 代码步骤(处理爬取的数据)

  1. 添加另一个 Node.js 代码步骤。以下是代码示例
Copy
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(数据) : []
        };
      }
    }
    
    const 摘要 = {
      时间戳,
      总关键词: Object.keys(processedData).length,
      成功关键词: Object.values(processedData).filter(d => d.status === '成功').length,
      期间: "今天 1-m",
      数据: processedData
    };
    
    console.log("最终处理的数据:", JSON.stringify(摘要, null, 2));
    return 摘要;
  },
})

它将根据 Scrapeless 返回的数据计算以下指标:

  • 平均值
  • 每周趋势变化(过去 7 天与之前 7 天比较)
  • 最大值 / 最小值
  • 波动性

注意:

  • 每个关键词将生成一个详细的分析对象,便于可视化和进一步通知。

第 4 步 - discord_notify (将分析报告推送到 Discord)

  1. 添加最后的 Node.js 步骤,下面是代码示例
Copy
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 当前日期 = new Date().toLocaleString('en-US');
    
    const 关键字 = Object.values(processedData.data);
    const 成功的 = 关键字.filter(k => k.status === '成功');
    
    let 最佳表现者 = null;
    let 最差表现者 = null;
    let 最强趋势 = null;
    
    if (成功的.length > 0) {
      最佳表现者 = 成功的.reduce((max, curr) => curr.average > max.average ? curr : max);
      最差表现者 = 成功的.reduce((min, curr) => curr.average < min.average ? curr : min);
      最强趋势 = 成功的.reduce((max, curr) => Math.abs(curr.weeklyTrend) > Math.abs(max.weeklyTrend) ? curr : max);
    }
    
    const discordMessage = {
      content: `📊 **Google 趋势报告** - ${当前日期}`,
      embeds: [
        {
          title: "🔍 趋势分析",
          color: 3447003,
          timestamp: new Date().toISOString(),
          fields: [
            {
              name: "📈 摘要",
              value: `**期间:** 上个月\n**分析的关键字:** ${processedData.totalKeywords}\n**成功:** ${processedData.successfulKeywords}/${processedData.totalKeywords}`,
              inline: false
            }
          ]
        }
      ]
    };
    
    if (成功的.length > 0) {
      const 关键字详情 = 成功的.map(data => {
        const 趋势图标 = data.weeklyTrend > 5 ? '🚀' : 
                         data.weeklyTrend > 0 ? '📈' : 
                         data.weeklyTrend < -5 ? '📉' : 
                         data.weeklyTrend < 0 ? '⬇️' : '➡️';
        
        const 表现图标 = data.average > 70 ? '🔥' : 
                               data.average > 40 ? '✅' : 
                               data.average > 20 ? '🟡' : '🔴';
        
        return {
          name: `${表现图标} ${data.keyword}`,
          value: `**分数:** ${data.average}/100\n**趋势:** ${趋势图标} ${data.weeklyTrend > 0 ? '+' : ''}${data.weeklyTrend}\n**范围:** ${data.min}-${data.max}`,
          inline: true
        };
      });
      
      discordMessage.embeds[0].fields.push(...关键字详情);
    }
    
    if (最佳表现者 && 成功的.length > 1) {
      discordMessage.embeds.push({
        title: "🏆 关键亮点",
        color: 15844367,
        fields: [
          {
            name: "🥇 最佳表现者",
            value: `**${最佳表现者.keyword}** (${最佳表现者.average}/100)`,
            inline: true
          },
          {
            name: "📊 最低分数",
            value: `**${最差表现者.keyword}** (${最差表现者.average}/100)`,
            inline: true
          },
          {
            name: "⚡ 最强趋势",
            value: `**${最强趋势.keyword}** (${最强趋势.weeklyTrend > 0 ? '+' : ''}${最强趋势.weeklyTrend})`,
            inline: true
          }
        ]
      });
    }
    
    const 失败的 = 关键字.filter(k => k.status === '错误');
    if (失败的.length > 0) {
      discordMessage.embeds.push({
        title: "❌ 错误",
        color: 15158332,
        fields: 失败的.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
      }
    };
  }
}
},
  1. 用您自己的Webhook地址替换“YOUR DISCORD WEBHOOK URL”
  2. 点击“部署”以运行您的工作流并获取实时信息。

第5步 - 接收实时Google Trends信息

您可以直接在Discord中接收检查关键词的数据:

第5步 - 接收实时Google Trends信息

以下是完整的链接图:

以下是完整的链接图

✅ 正式推出:Scrapeless在Pipedream上的官方集成

Scrapeless现在在Pipedream的集成中心正式上线!只需几次点击,您就可以直接从Pipedream工作流中调用我们强大的Google Trends API - 无需设置,无需服务器。

无论您是在构建实时仪表板、自动化市场情报还是驱动自定义分析,此集成都为您提供了快速的生产级趋势监控路径。

👉 立即开始构建: pipedream.com/apps/scrapeless
拖放并部署您下一个趋势驱动的工作流。

非常适合需要快速可行动见解的开发人员、分析师和增长团队。

摘要

通过Pipedream、Scrapeless API和Discord的强大组合,我们构建了一个无需人工干预、每天自动执行的Google Trends报告系统。这不仅大大提高了工作效率,还使市场决策更加数据化。

如果您也需要构建类似的数据自动化分析系统,不妨尝试这种技术组合!


Scrapeless全面遵守适用法律法规,仅根据平台服务条款访问公开可用数据。该解决方案旨在用于合法的商业智能和研究目的。

在Scrapeless,我们仅访问公开可用的数据,并严格遵循适用的法律、法规和网站隐私政策。本博客中的内容仅供演示之用,不涉及任何非法或侵权活动。我们对使用本博客或第三方链接中的信息不做任何保证,并免除所有责任。在进行任何抓取活动之前,请咨询您的法律顾问,并审查目标网站的服务条款或获取必要的许可。

最受欢迎的文章

目录