mcpField
T
TrendFlow

TrendFlow

远程服务
trendflow.mory.dev数据与分析27 周前更新

关于 TrendFlow

TrendFlow 是用于查询和导出 Google Trends 数据的 JavaScript/TypeScript 库,并提供配套 MCP 服务,供 Agent 研究搜索趋势。它支持地区与时间维度的热度、相关查询、主题和实时趋势。

主要功能

  1. 01按时间和地区查询热度
  2. 02查询相关词与主题建议
  3. 03查看趋势搜索的增长率和搜索量
  4. 04导出 CSV 和 JSON
  5. 05轮换代理池

适用场景

  1. 01比较不同地区和时段的搜索热度
  2. 02查找某个主题的相关查询
  3. 03跟踪增长迅速和搜索量高的词条

MCP 相关

独立的 `trendflow-mcp` 包提供六种工具,涵盖主题搜索、热度数据、相关查询、趋势搜索和趋势研究,并提供两个资源。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://trendflow.mory.dev/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

8
参数类型必填说明
countryany否国家/地区代码,例如 "US"、"GB"、"TH";下级区域,例如 "US-CA";或美国都市圈代码,例如 "807"。空字符串表示全球。

详细介绍

Trendflow JS 标志

Trendflow JS

npm version CI docs trendflow-js MCP server

一个类型安全的 JavaScript/TypeScript 库,用于查询和导出 Google Trends 数据。 trendflow-py 的 JavaScript 移植版。

📖 文档:trendflow.mory.dev/docs/js — 两个库的使用指南, 以及一个可供 ChatGPT、Claude 和 Cursor 使用的托管 MCP 服务。

安装

npm install trendflow

需要 Node.js 18+(使用全局 fetch)。提供 ESM 和 CommonJS,并附带捆绑的类型声明。

用法

import { Client, Region, Timeframe, Resolution, SearchProperty, ExportFormat } from "trendflow";

// Initialize client (optional config)
const tf = new Client({ language: "en", timeout: 10_000 });

// --- Const objects for type safety ---
// Region.US, Region.GB, Region.DE ...           (or any code: "US-CA", "807")
// Timeframe.PAST_HOUR ... PAST_5_YEARS, ALL_TIME (or "2023-01-01 2023-06-30")
// Resolution.COUNTRY, Resolution.REGION, Resolution.CITY
// SearchProperty.WEB, IMAGES, NEWS, YOUTUBE, SHOPPING

// Fetch interest over time
const data = await tf.interestOverTime(
  ["Python", "JavaScript", "Rust"],
  Timeframe.PAST_YEAR,
  Region.US,
);

console.log(data.keywords);    // ["Python", "JavaScript", "Rust"]
console.log(data.granularity); // "weekly"
console.log(data.points);      // TrendPoint[] — { date: Date, scores: Record<string, number> }

// Regional breakdown (region defaults to Region.US)
const regional = await tf.interestByRegion("Python", Resolution.COUNTRY);
for (const row of regional.rows) {
  console.log(row.label, row.value);
}

// Trending searches right now (any country code, or omit for worldwide)
const trending = await tf.trendingNow(Region.US);
for (const item of trending.results) {
  console.log(item.title, item.growth, item.volume, item.traffic);
  // "fifa world cup 2026"  3650  6  "+3,650%"
}

// Related queries (region defaults to worldwide)
const related = await tf.relatedQueries("machine learning", { region: Region.GB });
for (const query of related.top) console.log(query.term, query.value);
for (const query of related.rising) console.log(query.term, query.breakout);

// --- Narrowing a query ---
// Every query method takes an optional category and search property, and any of them
// accepts a custom date range and a sub-region or metro code in place of the named values.

// "jaguar" the car, on YouTube, in California, over the first half of 2023
const jaguar = await tf.interestOverTime(["jaguar"], "2023-01-01 2023-06-30", "US-CA", {
  category: 47, // Autos & Vehicles — disambiguates without needing a topic id
  searchProperty: SearchProperty.YOUTUBE,
});

// --- Exports ---
data.toArray();  // [{ date: Date, Python: 80, ... }] — plain objects, the JS answer to DataFrames
data.toJSON();   // same rows with ISO 8601 date strings (also drives JSON.stringify)
data.toCSV();    // CSV text

// Node.js only — writes UTF-8 to disk
await data.export(ExportFormat.CSV, "trends.csv");
await data.export(ExportFormat.JSON, "trends.json");
错误

请求失败时会抛出 ResponseError;HTTP 429 时则会抛出其子类 TooManyRequestsError。 两者都包含 .status 和原始 .response。

import { TooManyRequestsError } from "trendflow";

try {
  await tf.interestOverTime(["Python"], Timeframe.PAST_YEAR, Region.US);
} catch (error) {
  if (error instanceof TooManyRequestsError) {
    // Google is rate-limiting this IP — back off and retry later.
  }
}
热门趋势后端:RPC 和 RSS

Google 通过两种方式公开热门搜索趋势。两者不可互换,因此可以通过 backend 进行选择:

"rpc"(batchexecute)"rss"(信息流)
条目数5010
数据载荷约 2 KB JSON约 21 KB XML
增长率和搜索量✅❌ — 以 "2000+" 等区间表示
新闻文章❌✅
window 选择✅Google 会忽略
全球范围✅❌ 仅限国家/地区
const rss = await tf.trendingNow(Region.US, { backend: "rss" });
rss.source; // "rss"
rss.results[0].articles;
// [{ title: "...", url: "https://...", source: "Buffalo News", picture: "https://..." }]

"auto"(默认值)会先尝试 RPC,失败时再回退到信息流。特意将 RPC 放在首位: 它返回的条目数是信息流的五倍,并提供实际增长数据;因此,默认使用 RSS 会悄然降低结果质量。 需要文章时,请选用 "rss" —— 这是 RPC 唯一无法提供的内容;如果 RPC ID 过期,也可以用它作为第二种参考。

请注意,信息流虽然是信息流,但并不是更轻量的路径;Google 还会忽略其上的 hours、 sort 和 count:它始终返回相同的 10 条记录。

主题和搜索建议

Google 区分搜索词(字面字符串)和主题(实体,涵盖所有拼写和语言)。 suggestions() 用于查找主题;所有查询方法都已支持主题——在通常传入关键字的位置传入 mid 即可。

const topics = await tf.suggestions("artificial intelligence");
// [{ mid: "/m/0mkz", title: "Artificial intelligence", type: "Professional field" }]

const data = await tf.interestOverTime(
  [topics[0].mid, "artificial intelligence"],
  Timeframe.PAST_YEAR,
  Region.US,
);
// { "/m/0mkz": 62, "artificial intelligence": 1 }

差距正是关键:主题的得分为 62,而字面短语的得分为 1,因为主题会汇总人们实际搜索的各种说法和翻译。

suggestions() 无需 Cookie 或代理——与 trendingNow() 一样,它可以通过那些会被 widgetdata 端点以 429 拒绝的 IP 进行响应。type 用于区分同名实体("Nike" 会同时返回公司和女神),如果 Google 未提供该值,则为 null。

速率限制

Google Trends 会严格限制数据中心和共享 IP 的访问,因此即使当天只发送了第一个请求,也经常会遇到 429。有两点需要注意:

  1. User-Agent。 无论请求次数有多么少,Google 都会对 Node HTTP 客户端发送的默认 Agent 字符串返回 429。正因如此,该库默认使用浏览器的 User-Agent——如果你覆盖了 headers,请保留一个看起来真实的值。
  2. IP 信誉。 一旦某个 IP 被标记,无论请求头是什么,所有请求都会收到 429。通过住宅代理转发请求即可恢复。
使用代理池

传入代理 URL 列表,客户端会自动轮换使用;每当查询遭拒时,就切换到下一个代理:

import { Client, Region, Timeframe } from "trendflow";

const tf = new Client({
  proxies: [
    "http://user:[email protected]:7000",
    "http://user:[email protected]:7000",
  ],
  maxProxyAttempts: 3, // defaults to the pool size, capped at 5
  onProxyRotate: ({ attempt, error }) => console.warn(`rotated after ${attempt}:`, error),
});

const data = await tf.interestOverTime(["Python"], Timeframe.PAST_YEAR, Region.US);
console.log(tf.currentProxy); // the proxy that answered

代理支持需要 undici,这是一个可选的 peer 依赖——npm install undici。列表项都是 URL,因此代理池可以混用不同提供商的代理。重复使用同一个轮换网关也可行:每个列表项都会建立独立连接,因此会分配到新的出口 IP。

轮换按查询进行,而不是按请求进行——这一点很重要。 Google 会将 NID Cookie 和 widget 令牌绑定到发起请求的 IP,因此单次查询必须使用同一个出口 IP 完成;如果后续的 widgetdata 调用使用了不同 IP,就会立即收到 429。代理池会为整个查询固定使用一个代理,仅在失败时才切换,并且每次都会重新初始化 Cookie 存储。出于同样的原因,如果提供商支持,请选择粘性会话,而不是按请求轮换的端点。

对于其他 IP 无法解决的错误,例如 404,或 Google 重命名 batchexecute RPC ID 时引发的 UnknownRpcError,不会进行轮换。

代理获取渠道

住宅代理才能真正解决 Google 的 429。以下代理已通过该库验证:

Decodo

提供商备注端点格式
Decodo(前身为 Smartproxy)入门套餐价格最低;支持按使用量付费。该库的实时测试使用此服务进行验证。http://user:[email protected]:7000
const tf = new Client({
  proxies: ["http://user:[email protected]:7000"],
});

注册时请申请粘性会话——按请求轮换的端点会破坏上文所述的 Cookie/令牌绑定。请注意,共享住宅代理池可能专门用于 Google Trends 的 IP 已耗尽,此时即使是有效代理也会返回 429;这正是 maxProxyAttempts 的用途。

使用自己的客户端

如需日志记录、缓存或自定义路由,可改为传入 fetch(不能与 proxies 同时使用——如果两者都传入,该库会提示你):

import { ProxyAgent, fetch as undiciFetch } from "undici";

const agent = new ProxyAgent("http://user:[email protected]:7000");
const tf = new Client({
  fetch: ((input, init = {}) =>
    undiciFetch(input, { ...init, dispatcher: agent })) as typeof globalThis.fetch,
});
浏览器 / Next.js

除 export() 外,所有方法都可在支持 fetch 的环境中运行,但 Google Trends 不会发送 CORS 请求头——来自浏览器 JavaScript 的调用会被阻止。请在服务端使用该库(Route Handlers、Server Actions、API routes),并将结果传给客户端。

MCP 服务

该库附带 MCP 服务 trendflow-mcp,供 Agent 直接查询 Google Trends。它是一个独立的软件包——该库本身保持零运行时依赖。

claude mcp add trendflow -- npx -y trendflow-mcp

包含六个工具(search_topics、get_interest_over_time、get_interest_by_region、get_related_queries、get_trending_now、research_trend)和两个资源。请参阅 mcp/README.md。

功能对等

当前版本:trendflow-py 0.2.0 · trendflow 0.1.0。两个版本线相互独立;各自的变更日志都会交叉引用另一个版本线的发布。

功能Python — trendflow-pyJS — trendflow
随时间变化的搜索热度✅✅
按地区查看搜索热度✅✅
当前热门趋势✅✅
趋势增长百分比和搜索量✅✅
支持任意国家/地区代码的趋势✅✅
热门趋势新闻文章(RSS)✅✅
可选的趋势后端✅✅
相关查询✅✅
搜索建议✅ suggestions()✅ suggestions()
按主题(实体 mid)查询✅✅
导出 CSV / JSON✅✅
轮换代理池✅✅
默认使用浏览器 User-Agent✅✅
完整地理层级✅ geo_list()✅ geoList()
可覆盖 RPC ID✅✅
pandas DataFrame✅ to_dataframe()❌ 不适用
普通对象行❌ 不适用✅ toArray()
ESM + CommonJS + 类型❌ 不适用✅
MCP 服务🔜 计划中✅ trendflow-mcp
CLI✅🔜 计划中
当前热门趋势

Google 已弃用 hottrends/visualize/internal/data 端点,以及 api/dailytrends 和 api/realtimetrends;这三个端点现在都会返回 HTTP 404。本库改为 调用 trends.google.com 自身使用的 batchexecute RPC——trendflow-py 从 0.2.0 版本起也采用此方式——返回的数据 比旧端点更多:

const trending = await tf.trendingNow(Region.US);
// { title: "fifa world cup 2026", growth: 3650, volume: 6, traffic: "+3,650%", articles: [] }

与旧端点相比,有三个实际优势:

  • 包含增长幅度和搜索量,不只是标题。growth 是该时间窗口内的涨幅百分比, volume 是相对搜索量指数。
  • 支持任意国家/地区代码,而非旧端点要求的 16 个硬编码名称;还支持全球范围, 旧端点不支持。
  • 无需 Cookie,且速率限制宽松得多。 即使来自会被 widgetdata 端点返回 429 的 IP,此 RPC 也能响应,因此 trendingNow() 通常无需代理即可使用。

此后端的 articles 为空,因为该 RPC 不包含文章链接。传入 { backend: "rss" },即可获取每个趋势对应的新闻文章。

可通过 TrendingWindow 选择时间窗口:

import { TrendingWindow } from "trendflow";

await tf.trendingNow(Region.US, { window: TrendingWindow.RISING }); // default: fastest-growing
await tf.trendingNow(Region.US, { window: TrendingWindow.TOP });    // highest-volume

window 是 Google 未公开文档的参数。只有以下两个值值得命名;介于 4 和 12 之间的其他整数 也会返回数据,所覆盖的时间范围各不相同,你可以直接传入原始数字。

尚未实现:需要验证码的 RPC

同一个 batchexecute 端点还提供更高精度的时间序列(浮点值,而非公开 API 返回的四舍五入后的 0–100 值) 和关键词范围的相关查询。这两项功能都需要 reCAPTCHA Enterprise 令牌,没有令牌时会返回空数据, 因此本库未实现这些功能——仍可通过 interestOverTime() 和 relatedQueries() 获取相应数据, 这两个方法使用有文档说明的 widgetdata 端点。

API 对照
PythonJavaScript
interest_over_time()interestOverTime()
interest_by_region()interestByRegion()
trending_now()trendingNow()
related_queries()relatedQueries()
to_dataframe()toArray()
export(fmt, path)export(fmt, path) — 仅 Node,另有 toCSV() / toJSON()

显著差异:

  • 所有操作都是异步的。 四个查询方法都会返回 Promise。
  • timeout 的单位是毫秒(JS 惯例),而不是秒。
  • 枚举是 as const 对象,因此 Region.US 是字符串 "US";在需要该类型的地方,也接受任何有效的 字符串字面量。
  • 结果是带类型的普通对象。 只有 InterestOverTimeResult 是类,因为它提供了转换方法;其余均为接口。

开发

git clone [email protected]:dariomory/trendflow-js.git
cd trendflow-js
npm install

npm test        # vitest — 60 tests, fully offline against a stubbed fetch
npm run qa      # typecheck + test + build

单元测试不会访问网络。要检查真实端点:

npm run build && npm run smoke
TRENDFLOW_PROXY_URL=http://user:pass@host:7000 npm run smoke   # via a proxy

作者

Trendflow JS 由 Dario Mory 于 2026 年创建。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。