
Wechat Search
- 256 installs
- 316 repo stars
- Updated August 4, 2026
- redfox-data/redfox-community
Searches viral WeChat articles by keyword and ranks results by a three-factor score of relevance, popularity, and recency for topic and inspiration discovery.
About
A WeChat article search tool that finds viral posts by keyword and ranks them with a weighted relevance, heat, and recency score. A content creator uses it to discover hot topics, study viral patterns, and get writing inspiration.
- Three-dimension scoring: relevance, popularity, and recency
- Niche-word detection with 10 sub-direction suggestions and subscription push
Wechat Search by the numbers
- 256 all-time installs (skills.sh)
- +20 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #887 of 1,879 Marketing & SEO skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/redfox-data/redfox-community --skill wechat-searchAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 256 |
|---|---|
| repo stars | ★ 316 |
| Last updated | August 4, 2026 |
| Repository | redfox-data/redfox-community ↗ |
What it does
Searches viral WeChat articles by keyword and ranks results by a three-factor score of relevance, popularity, and recency for topic and inspiration discovery.
Files
公众号热门文章查询
1. 简介
公众号热门爆款文章查询工具,支持按关键词搜索微信公众号爆款文章,并基于相关性、热度、时效三维评分智能排序推荐。专注服务于公众号内容创作者、新媒体运营者和自媒体团队,帮助用户快速发现热门选题、分析爆款规律、获取创作灵感。
2. 功能特性
- 🔍 关键词智能搜索 — 支持关键词精确搜索和多关键词组合查询(逗号分隔),覆盖全品类公众号文章
- 📊 三维评分排序 — 基于相关性(满分10分)、热度(满分3分)、时效(满分2分)加权计算总分(满分15分),智能排序推荐
- ⏱️ 灵活时间范围 — 默认查询最近7天,支持自动拓展时间(1天→7天→30天),数据每日早上7点更新
- 🧠 赛道词识别与拓展 — 自动识别泛化赛道词并推荐10个细分方向,帮助用户精准定位
- 🔥 热门推荐文章 — 结果较少时自动展示近期热门推荐文章和热门话题
- 📩 定时订阅推送 — 支持创建日历订阅任务,到达设定时间自动推送最新爆款文章
- 📄 HTML 报告生成 — 可选生成 HTML 可视化文件,方便独立查看和分享
- 📋 数字智能格式化 — 万级以上阅读数自动转换(如
10.0w),总分字段加粗突出显示
3. 一键安装
鉴权
获取 API Key
请前往 红狐hub 获取API KEY
配置 API Key
方案1: 以OpenClaw为例,将REDFOX_API_KEY添加到~/.openclaw/openclaw.json中:
{ "env": { "REDFOX_API_KEY": "ak_xxxx..." } }方案2: 终端配置
export REDFOX_API_KEY="ak_xxxx..."依赖安装
本 Skill 使用 Python 3.13+ 纯标准库(urllib.request、json、os、sys、argparse、datetime),无需安装任何第三方依赖。
环境变量配置
| 环境变量 | 说明 | 是否必填 | 获取方式 |
|---|---|---|---|
REDFOX_API_KEY | 红狐数据 API Key | 是 | 红狐hub |
4. 使用指南
基础使用(3 步完成查询)
Step 1 — 提取关键词:从用户描述中提取搜索关键词,判断是赛道词还是细分词。
- 赛道词:较大的分类词,如"职场""情感""亲子""美妆"等
- 非赛道词:具体细分词,如"职场沟通技巧""异地恋怎么维持"等
Step 2 — 调用脚本:
python scripts/fetch_gzh_trends.py --keyword <关键词> --start-date <日期>- 有赛道关键词:
python scripts/fetch_gzh_trends.py --keyword <关键词> --start-date <日期> - 无赛道关键词(查询全站热门):
python scripts/fetch_gzh_trends.py --keyword "" --start-date <日期> - 多个关键词用逗号分隔:
python scripts/fetch_gzh_trends.py --keyword "职场沟通,恋爱技巧,亲子教育" --start-date <日期>
⚠️ 防重复调用规则(强制):
- ❌ 禁止先用
head/tail/2>/dev/null | head -5等方式"试运行"或"预览"脚本输出 - ❌ 禁止在同一次查询中对同一参数多次调用脚本
- ✅ 每次查询只执行一次脚本命令,直接读取完整的 stdout 输出
- ✅ 唯一允许多次调用的场景:数据不足时按规定的自动拓展时间(近1天→近7天→近30天),每次使用不同的
--start-date
Step 3 — 查看结果:脚本返回结构化 JSON 数据,按本指南规定的展示策略输出结果。
---
高级使用
赛道词处理流程(仅当识别为赛道词时执行)
第一步:识别并询问用户(⚠️ 仅当用户明确要求时才执行)
我识别到「职场」是较大的分类,已查询近期热门趋势,推荐以下细分方向:
工作、打工人、职场穿搭、职场干货、成长、冷门职业、向上管理、职场焦虑、升职、财务自由
回复「拓展」将同时搜索这10个词,回复「不拓展」将继续搜索「职场」第二步:等待用户回复
- ❌ 禁止:用户未回复时调用脚本
- ❌ 禁止:自动执行拓展搜索(必须等用户明确回复「拓展」)
- ✅ 正确:只等待用户明确回复后再执行
第三步:根据用户明确回复执行
- 用户回复「拓展」 → 调用脚本搜索10个细分词
- 用户回复「不拓展」或「继续」 → 调用脚本搜索原关键词
- 用户未回复或回复其他内容 → 识别对应意图
---
时间范围与数据查询
时间范围:
- 数据库只包含昨天至30天前的数据
- "最近"的默认定义:最近7天(startDate = 今天 - 7天)
- 日期计算(将用户表达转换为 startDate):
- 今天:直接用昨天日期,startDate = 昨天
- 最近/近7天:startDate = 今天 - 7天
- 近N天:startDate = 今天 - N天
- 示例:用户说"近15天" → startDate = 今天 - 15天
数据不足时的自动拓展时间:
- ✅ 当 articles 数量不足时,自动按顺序拓展时间范围:近1天 → 近7天 → 近30天
- ✅ 每次拓展后重新调用脚本查询,直到获取到数据或拓展到30天为止
- ❌ 禁止自动扩展关键词搜索:搜索结果不足10条时,禁止用拓展词/相关词/同义词再次调用接口搜索
- ❌ 禁止自动尝试相关搜索建议
- ✅ 拓展时间后仍无数据,直接返回 articles=0 的结果
超出范围或未更新数据的道歉说明:
- 用户说"今天/今日"时:回答"非常抱歉,今天的数据暂未更新,已为您展示最近可用的数据"
- 用户要求的时间超出30天时:回答"非常抱歉,当前仅支持最近30天的数据,已为您展示最接近的数据"
输出文件:
- JSON数据:输出到标准输出(stdout)
- HTML文件:
{keyword}_趋势数据.html(可选)
---
前置说明(在展示数据前必须告知用户)
- 数据说明:爆款文章范围为阅读数5000+以上的文章,每日早上7点更新昨日数据。文章互动数据截止为入库时间,不是实时数据,入库后互动数据可能持续增长。
- 排序说明(有关键词搜索时):根据相关性(满分10分)、热度(满分3分)、时效(满分2分)三个维度加权计算,总分共15分
- 排序说明(全站热门/无关键词时):按阅读数排序
---
数据展示策略(核心)
⚠️ 强制输出规则:
- ✅ 必须严格按照本步骤规定的格式输出
- ❌ 禁止在输出前添加任何分析或解读
- ❌ 禁止自作主张给建议或方案
- ❌ 禁止询问用户的真实目的或需求
- ✅ 直接读取脚本返回的JSON数据,按照对应策略输出即可
数据字段说明:
- articles:正常文章数据(主要展示内容)
- latestHotArticles:推荐热门文章(辅助内容,默认展示10条,表格不含评分字段)
- hotTopics:热门话题(接口返回,仅供参考,不在对话中展示)
A. articles数量 ≥ 10条
展示内容:
1. 时间范围说明:必须告知用户查询的时间范围,如"📅 查询时间范围:5月8日 - 5月19日" 2. 正常文章数据(按totalScore降序排序) 3. 拓词推荐(relatedSearches)
Markdown表格格式:
⚠️ 表格字段顺序必须严格按以下顺序展示: | 文章标题 | 作者 | 阅读数 | 发布时间 | 相关性 | 热度 | 时效 | 总分 |
注意:总分字段需要加粗显示(使用**分数**格式)
示例: 📅 查询时间范围:5月8日 - 5月19日
| 文章标题 | 作者 | 阅读数 | 发布时间 | 相关性 | 热度 | 时效 | 总分 |
|---|---|---|---|---|---|---|---|
| 职场新人必看:5个让你快速融入团队的技巧 | 职场成长社 | 10.0w | 2026-05-15 | 9.8 | 3.0 | 2.0 | 14.8 |
---
🔤 拓词推荐:职场沟通、职场晋升、打工人
B. articles数量 < 10条但 > 0
展示内容:
1. 时间范围说明:必须告知用户查询的时间范围,如"📅 查询时间范围:5月8日 - 5月19日" 2. 提示信息:"💡当前关键词当前时间段仅找到 X 条结果,您可以尝试拓展词或者拓展时间,我们还为您推荐了近期的热门文章" 3. 正常文章数据 4. 推荐热门文章(latestHotArticles,带"推荐热门文章"标题分区,默认展示10条) 5. 推荐热门话题 6. 拓词推荐(relatedSearches)
Markdown格式示例:
📅 查询时间范围:5月8日 - 5月19日
💡当前关键词当前时间段仅找到 3 条结果,
| 文章标题 | 作者 | 阅读数 | 发布时间 | 相关性 | 热度 | 时效 | 总分 |
|---|---|---|---|---|---|---|---|
| 文章1 | 作者1 | 10.0w | 2026-05-15 | 9.8 | 3.0 | 2.0 | 14.8 |
您可以尝试拓展词或者拓展时间,我们还为您推荐了近期的热门文章供参考:
⚠️ 推荐热门文章表格不需要评分字段,格式为:
| 文章标题 | 作者 | 阅读数 | 发布时间 |
|---|---|---|---|
| 热门文章1 | 作者A | 8.5w | 2026-05-14 |
| 热门文章2 | 作者B | 6.2w | 2026-05-13 |
📈 推荐热门话题:
您可以尝试搜索以下热门赛道: 人文、知识、养生、时尚、美食、生活、旅游、搞笑、情感、体育娱乐、美妆、文摘、民生资讯、财富理财、科技数码、创投商业、汽车、房产楼市、职场、教育考试、学术
C. articles数量 = 0
⚠️ 必须严格按照以下格式输出,禁止自作主张给建议或分析
展示内容:
🔍 抱歉,爆款文章收录原则为阅读数5000+以上的文章,该搜索词在查询时间范围(5月8日 - 5月19日)内太小众,未找到与"XXX"直接相关的内容,你可以尝试用更短/宽泛的关键词重试 。
💡 或者您可以尝试搜索以下热门赛道:
人文、知识、养生、时尚、美食、生活、旅游、搞笑、情感、体育娱乐、美妆、文摘、民生资讯、财富理财、科技数码、创投商业、汽车、房产楼市、职场、教育考试、学术
我们为您推荐近期最热门的文章,您也可以关注~在以上内容之后,展示latestHotArticles数据(如果有),热门推荐表格不需要评分字段:
| 文章标题 | 作者 | 阅读数 | 发布时间 |
|---|---|---|---|
| 热门文章1 | 作者A | 8.5w | 2026-05-14 |
| 热门文章2 | 作者B | 6.2w | 2026-05-13 |
输出规则:
- ✅ 必须直接输出上述格式内容
- ❌ 禁止添加额外的分析或建议
- ❌ 禁止解释为什么搜不到数据
- ❌ 禁止主动提供其他搜索方案
- ❌ 禁止询问用户的真实目的
---
展示逻辑(分页)
当articles数量 > 10条时:
1. 初始默认只展示前10条数据 2. 必须提示用户:
💡 当前共找到 X 条相关文章,已展示前10条。是否需要查看全部?3. 等待用户回复:
- 用户回复"是"/"查看全部"/"全部" → 展示全部数据
- 用户回复"否"/"不用"/"不需要" → 不展示更多
展示全部数据时的格式:
📊 全部结果(共X条):
| 文章标题 | 作者 | 阅读数 | 发布时间 | 相关性 | 热度 | 时效 | **总分** |
|---------|------|--------|----------|--------|------|------|------|
| ...(全部数据)...---
智能筛选热门内容(可选)
⚠️ 此步骤为可选,仅在用户明确要求"筛选"、"推荐"时执行
筛选原则:
- 统一排序:脚本已自动将所有数据按totalScore排序
- 目标数量:最多10条,如实展示实际数据量
---
订阅服务询问(必须执行)
当articles数量 > 0时,结果输出完成后必须询问:
📬 订阅服务
1️⃣ 是否需要订阅当前搜索条件文章,订阅后将定时推送给您?
2️⃣ 暂不需要处理用户回复:
- 用户选择1️⃣ → 使用
calendar_create工具创建日程,订阅当前搜索条件 - 用户选择2️⃣ → 结束当前对话
订阅实现步骤:
1. 告知数据更新时间并询问推送时间:
📅 数据更新时间:每日早上7点更新昨日数据
请告诉我您希望推送的具体时间~2. 用户选择后,调用 `calendar_create` 工具:
- title:
公众号趋势订阅:{关键词} - description:记录当前搜索参数(关键词、时间范围)
- start_time:根据用户选择的时间设置
- remind_type:设置为定期提醒
- 其他参数使用当前查询参数
3. 订阅成功后提示:
✅ 订阅创建成功!
📌 订阅信息:
- 关键词:{关键词}
- 时间范围:{当前时间范围}
- 推送时间:{用户选择的时间}
- 数据更新:每日早上7点更新昨日数据
到达设定时间后,将自动为您推送最新的公众号爆款文章。⚠️ 强制规则:
- ✅ 必须在结果输出完成后立即询问
- ✅ 用户选择订阅时,必须使用
calendar_create工具 - ✅ 参数必须使用当前查询参数(关键词、时间范围等)
- ❌ 禁止跳过此步骤
- ❌ 禁止在展示结果前询问
---
常用命令速查表
| 场景 | 命令 |
|---|---|
| 关键词搜索(默认近7天) | python scripts/fetch_gzh_trends.py --keyword "关键词" --start-date <日期> |
| 全站热门 | python scripts/fetch_gzh_trends.py --keyword "" --start-date <日期> |
| 多关键词搜索 | python scripts/fetch_gzh_trends.py --keyword "词1,词2,词3" --start-date <日期> |
| 指定时间范围 | python scripts/fetch_gzh_trends.py --keyword "关键词" --start-date 2026-05-08 |
| 生成 HTML 报告 | 脚本自动生成 {keyword}_趋势数据.html |
| 订阅创建 | 回复1️⃣后使用 calendar_create 工具创建定时任务 |
5. 使用场景
场景一:公众号创作者寻找选题灵感
- 角色:公众号内容创作者
- 需求:想了解近期"职场"领域有哪些爆款文章,寻找下一篇选题灵感
- 使用方式:输入赛道词「职场」后,系统推荐 10 个细分方向(如"职场穿搭""向上管理"等),回复「拓展」批量搜索
- 预期收益:通过三维评分排序快速锁定高价值选题方向,了解同赛道爆款文章的内容特征
场景二:新媒体运营竞品分析
- 角色:新媒体运营经理
- 需求:需要分析竞品公众号近期发布了哪些爆款文章,了解其内容策略
- 使用方式:搜索竞品公众号名称或相关领域关键词,查看按 totalScore 排序的文章列表
- 预期收益:系统了解竞品的内容选题、标题套路和发布节奏,为自身运营策略提供数据支撑
场景三:自媒体矩阵内容规划
- 角色:MCN 机构内容总监
- 需求:需要一次性查看多个领域(职场、情感、亲子)的近期爆款文章,规划矩阵内容排期
- 使用方式:使用逗号分隔多关键词
--keyword "职场,情感,亲子"进行跨领域查询 - 预期收益:一个命令覆盖多个领域,高效获取跨品类热门趋势,提升内容规划效率
场景四:每日爆文定时推送
- 角色:自媒体博主
- 需求:希望每天上午自动收到特定领域的公众号爆款文章列表
- 使用方式:搜索关键词后选择「1️⃣ 订阅」,设置推送时间,创建日历定时任务
- 预期收益:无需手动重复搜索,每日定时获取最新爆款文章,持续跟踪赛道动态
6. 项目架构
目录结构
wechat-search/
├── SKILL.md # Skill 定义与使用文档(本文件)
├── scripts/
│ └── fetch_gzh_trends.py # 核心搜索脚本,调用红狐 API 获取公众号爆款文章
└── references/
└── gzh_trend_data_format.md # 数据字段格式参考文档技术栈
| 组件 | 技术 | 说明 |
|---|---|---|
| 运行环境 | Python 3.13+ | 纯标准库,无第三方依赖 |
| 标准库 | urllib.request, json, os, sys, argparse, datetime | 用于 HTTP 请求、JSON 处理、参数解析、日期计算 |
| 数据接口 | 红狐 API (Redfox) | 通过 REDFOX_API_KEY 鉴权 |
| 输出格式 | JSON (stdout) + HTML (文件) | JSON 通过 stdout 输出供 AI 解析,HTML 为可选可视化文件 |
| 展示格式 | Markdown 表格 | AI 代理将 JSON 渲染为表格展示 |
核心模块说明
| 模块 | 路径 | 功能 |
|---|---|---|
| 搜索脚本 | scripts/fetch_gzh_trends.py | 调用红狐接口获取公众号爆款文章,支持 --keyword、--start-date、--max-items、--output-format 参数 |
| 数据格式参考 | references/gzh_trend_data_format.md | 详细说明接口返回的数据字段格式和含义 |
| SKILL 定义 | SKILL.md | 定义 Skill 元数据、工作流程、展示策略、订阅逻辑 |
资源索引
- 核心脚本:
scripts/fetch_gzh_trends.py— 调用红狐 API 获取公众号爆款文章数据,参数:--keyword(必需)、--start-date(可选)、--max-items(可选)、--output-format(可选) - 参考文档:
references/gzh_trend_data_format.md— 何时读取:需要了解接口数据格式、字段说明时
7. 常见问答
安装
Q: 需要安装哪些依赖? A: 本工具使用 Python 3.13+ 纯标准库(urllib.request、json、os、sys、argparse、datetime),无需安装任何第三方依赖。确保系统已安装 Python 3.13 或更高版本。
Q: 如何获取 API Key? A: 请访问 红狐hub 注册并获取 API Key,按本文"一键安装"章节配置环境变量。
使用
Q: 赛道词和非赛道词有什么区别? A: 赛道词是较大分类词(如"职场""情感"),识别后会触发拓展策略;非赛道词是具体细分词(如"职场沟通技巧"),直接搜索无需拓展询问。
Q: 数据的时间范围是什么? A: 数据库仅包含昨天至30天前的数据,默认查询最近7天。数据不足时会自动拓展时间范围(1天→7天→30天)。每日早上7点更新昨日数据。
Q: 为什么表格中有些字段有评分、有些没有? A: 有关键词搜索时按 totalScore(相关性+热度+时效)排序,展示评分字段;全站热门按阅读数排序,无评分字段。推荐热门文章表格也不含评分。
Q: 如何查看超过 10 条的完整结果? A: 当结果超过 10 条时,系统会提示「是否查看全部?」。回复「是」「查看全部」或「全部」即可展示完整数据。
故障排除
Q: 脚本执行返回空结果? A: 爆款文章收录原则为阅读数5000+以上。如果关键词太小众或时间范围太短,可能无数据。系统会自动拓展时间范围,若拓展到30天仍无数据则返回空。可尝试更短/更宽泛的关键词。
Q: 提示"今天的数据暂未更新"? A: 数据库每日早上7点更新昨日数据,当天数据尚未入库。系统会自动展示最近可用的数据。
Q: 脚本报错怎么办? A: 常见原因:(1) REDFOX_API_KEY 未配置或已过期;(2) Python 版本 < 3.13;(3) 网络问题。请逐一排查。
安全许可
Q: API Key 如何安全存储? A: 推荐使用方案 1(配置到 openclaw.json 的 env 字段中),避免在终端历史中泄露。请勿将 API Key 硬编码在脚本中或上传到公开仓库。
Q: 数据来源和版权? A: 数据来源于红狐 API 收录的公众号公开文章。文章版权归原作者所有,本工具仅供学习和内容创作参考使用。
WeChat Hot Article Search / wechat-search
Introduction
A WeChat Official Account hot article search tool — quickly find articles with 5,000+ reads, get creative inspiration, and stay on top of content trends.
Core Value
Based on continuously indexed WeChat articles with 5,000+ reads from the past 30 days across the web, updated daily with yesterday's data. Weighted scoring by relevance, heat, and timeliness aggregates viral articles across all domains. Quickly find quality benchmarks in any industry and reference peer hot content ideas — no more hunting for materials across the web, a one-stop solution for daily writing reference.
Who It's For
- 🎯 Content creators — Find topic inspiration and break down viral article structure
- 📦 WeChat operators — Track industry trends and shape content strategy
- 🏢 Brands / business teams — Monitor industry KOL dynamics and evaluate content marketing direction
- 📚 Self-media learners — Learn viral patterns and improve writing skills
Features
Core Capabilities
- Keyword search: Query viral WeChat articles related to any keyword
- Site-wide hot recommendations: View recent hottest articles across WeChat without keywords
- Smart score ranking: Weighted by relevance (10 pts), heat (3 pts), and timeliness (2 pts) — max 15 pts total
- Query expansion: Related sub-topic recommendations in search results to broaden topic ideas
- Subscription push: Subscribe to daily scheduled pushes for keyword queries
---
API Key Acquisition & Security
- This skill requires the environment variable:
REDFOX_API_KEY. REDFOX_API_KEYis provided by RedFoxHub (https://redfox.hk).- Register at RedFoxHub to obtain your
REDFOX_API_KEY. - Configure
REDFOX_API_KEYas a device environment variable before using this skill. - Before providing your key, confirm its source, available scope, validity period, and whether reset/revocation is supported.
- Do not hard-code or expose the key in plaintext in code, prompts, logs, or output files.
---
Usage Guide
Quick phrase reference
| Intent | Example phrase | What you get |
|---|---|---|
| Search viral articles | "Find workplace-related viral articles for me" | Recent hot articles in workplace niche |
| Niche sub-topic | "Search for AI startup articles" | Precisely matched sub-keyword articles |
| Multi-niche query | "Find viral articles in workplace, emotions, and parenting" | Hot articles from three niches at once |
| Site-wide hot | "What are the hottest site-wide articles lately?" | Recent hottest articles across the site |
| View all | "Show all 50 entries" | Full query results |
| Subscribe | "Subscribe to workplace articles, push daily at 9 AM" | Create daily scheduled push task |
Sample output
📅 Query time range: May 14 – May 21
💡 Found 12 related articles; showing first 10. View all?
| Title | Author | Reads | Published | Relevance | Heat | Timeliness | Total |
|---|---|---|---|---|---|---|---|
| Must-read for workplace newcomers: 5 tips to fit in fast | Workplace Growth | 100K | 2026-05-15 | 9.8 | 3.0 | 2.0 | 14.8 |
| Workplace communication: 3 sentences you must never say! | Workplace Tips | 85K | 2026-05-14 | 9.5 | 2.8 | 2.0 | 14.3 |
| Workers must save: 7 secrets to efficient meetings | Workplace Lab | 62K | 2026-05-13 | 9.2 | 2.5 | 1.8 | 13.5 |
| ... | ... | ... | ... | ... | ... | ... | ... |
🔤 Query expansion: work, office workers, workplace outfits, workplace tips, growth, niche careers, managing up, workplace anxiety, promotion, financial freedom
---
📬 Subscription
1️⃣ Subscribe to articles matching your current search? Scheduled pushes after subscription.
2️⃣ Not now
---
Use Cases
| Scenario | Role | Example question | Benefit |
|---|---|---|---|
| Topic inspiration | Content creator | "What hot workplace articles are there lately?" | Quickly get topic direction |
| Viral pattern breakdown | WeChat operator | "Find emotional viral articles and analyze structure" | Learn viral title and content patterns |
| Industry trend analysis | Brand / business | "What's hot in food niche lately?" | Monitor industry KOL dynamics |
| Multi-niche scan | Self-media learner | "Show me site-wide hot articles" | Grasp cross-platform hot directions |
| Scheduled tracking | Content creator | "Push workplace articles to me every morning" | Automated industry trend tracking |
---
Important data notes
Recommended hot niches (22)
Humanities, knowledge, wellness, fashion, food, lifestyle, travel, humor, emotions, sports & entertainment, beauty, digest, civic news, wealth & finance, tech & digital, venture & business, automotive, real estate, career, education & exams, academic
Data notes
- Data scope: Viral articles are those with 5,000+ reads
- Update time: Daily 7:00 AM with yesterday's data
- Data freshness: Engagement cutoff is ingestion time, not real-time; may continue growing after ingestion
- Query range: Currently supports data from the past 30 days
Ranking rules
- Keyword search: Sorted by total score (relevance + heat + timeliness) descending; max 15 pts
- Site-wide hot: Sorted by read count descending
- Relevance: How well the article matches the keyword (max 10 pts)
- Heat: Overall heat performance (max 3 pts)
- Timeliness: Recency weight (max 2 pts)
Query expansion rules
- When a broad category keyword (track keyword) is detected, related sub-directions are recommended automatically
- When your keyword returns no results, it may be too niche — our indexing threshold is 5,000+ reads. Try expanded terms or a wider time range, or explore other hot niches for inspiration
公众号热门文章查询 / wechat-search
简介
公众号热门文章搜索工具,帮你快速找到公众号平台阅读数>5000 的热门文章,获取创作灵感,把握内容趋势。
核心价值
基于公众号全网持续收录近 30 天阅读数>5000 的热门文章,每日更新昨日文章数据。根据相关性、热度、时效性加权评分,汇聚全领域公众号爆款好文。快速查找各行各业优质对标内容,轻松参考同行热门创作思路,不用再四处搜集素材,一站式满足日常写文参考需求。
适用对象
- 🎯 内容创作者 — 寻找选题灵感,拆解爆款文章结构
- 📦 公众号运营 — 追踪行业热点,制定内容策略
- 🏢 品牌方 / 商务 — 了解行业 KOL 动态,评估内容营销方向
- 📚 自媒体学习者 — 学习爆款规律,提升写作技巧 ---
功能特性
核心功能
- 关键词精准搜索:输入任意关键词查询公众号相关爆款文章
- 全站热门推荐:无需关键词即可查看公众号全站近期最热门文章
- 智能评分排序:根据相关性(10 分)、热度(3 分)、时效(2 分)三维加权评分,总分 15 分。
- 拓词推荐:搜索结果提供相关细分方向推荐,拓展选题思路
- 订阅推送:支持订阅关键词每日定时推送
---
密钥获取与安全说明
- 本技能需要使用环境变量:
REDFOX_API_KEY。 REDFOX_API_KEY由 红狐 hub (https://redfox.hk)提供。- 请前往 红狐 hub 注册账号,获取
REDFOX_API_KEY。 - 配置设备环境变量
REDFOX_API_KEY后使用本技能。 - 在提供密钥前,请先确认密钥来源、可用范围、有效期及是否支持重置/撤销。
- 禁止在代码、提示词、日志或输出文件中硬编码/明文暴露密钥。
---
使用指南
常用说法速查
| 意图 | 示例话术 | 效果 |
|---|---|---|
| 查爆款文章 | "帮我查一下职场相关的爆款文章" | 返回职场赛道近期热门文章 |
| 查细分领域 | "查一下 AI 创业的文章" | 精准匹配细分关键词文章 |
| 多领域查询 | "帮我查职场、情感、亲子三个领域的爆款" | 同时返回三领域热门文章 |
| 看全站热门 | "最近全站有什么热门文章" | 展示全站近期最热门文章 |
| 查看全部 | "全部展示 50 条" | 展示完整查询结果 |
| 订阅推送 | "帮我订阅职场相关的文章,每日早上 9 点推送" | 创建每日定时推送任务 |
输出示例
📅 查询时间范围:5 月 14 日 - 5 月 21 日
💡 当前共找到 12 条相关文章,已展示前 10 条。是否需要查看全部?
| 文章标题 | 作者 | 阅读数 | 发布时间 | 相关性 | 热度 | 时效 | 总分 |
|---|---|---|---|---|---|---|---|
| 职场新人必看:5 个让你快速融入团队的技巧 | 职场成长社 | 10.0w | 2026-05-15 | 9.8 | 3.0 | 2.0 | 14.8 |
| 职场沟通:这 3 句话千万别说! | 职场干货铺 | 8.5w | 2026-05-14 | 9.5 | 2.8 | 2.0 | 14.3 |
| 打工人必收藏:高效会议的 7 个秘诀 | 职场研究院 | 6.2w | 2026-05-13 | 9.2 | 2.5 | 1.8 | 13.5 |
| ... | ... | ... | ... | ... | ... | ... | ... |
🔤 拓词推荐:工作、打工人、职场穿搭、职场干货、成长、冷门职业、向上管理、职场焦虑、升职、财务自由
---
📬 订阅服务
1️⃣ 是否需要订阅当前搜索条件文章,订阅后将定时推送给您?
2️⃣ 暂不需要
---
使用场景
| 场景 | 角色 | 示例问法 | 收益 |
|---|---|---|---|
| 寻找选题灵感 | 内容创作者 | "帮我查一下最近有什么热门的职场文章" | 快速获取选题方向 |
| 拆解爆款规律 | 公众号运营 | "查查情感类的爆款文章,分析下结构" | 学习爆款标题和内容套路 |
| 行业趋势分析 | 品牌方 / 商务 | "最近美食赛道有什么热门内容" | 了解行业 KOL 动态 |
| 多领域扫榜 | 自媒体学习者 | "帮我看看全站热门文章有哪些" | 掌握全平台热点方向 |
| 定时追踪 | 内容创作者 | "每天早上给我推送职场相关文章" | 自动化追踪行业热点 |
---
重要数据说明
推荐热门赛道(22 个)
人文、知识、养生、时尚、美食、生活、旅游、搞笑、情感、体育娱乐、美妆、文摘、民生资讯、财富理财、科技数码、创投商业、汽车、房产楼市、职场、教育考试、学术
数据说明
- 数据范围:爆款文章范围为阅读数 5000+以上的文章
- 更新时间:每日早上 7 点更新昨日数据
- 数据时效:文章互动数据截止为入库时间,不是实时数据,入库后互动数据可能持续增长
- 查询范围:当前支持查询最近 30 天内的数据
排序规则
- 关键词搜索:按总分(相关性+热度+时效)降序排序,总分共 15 分
- 全站热门:按阅读数降序排序
- 相关性:文章与关键词的匹配程度(满分 10 分)
- 热度:文章的整体热度表现(满分 3 分)
- 时效:文章的时效性权重(满分 2 分)
拓词规则
- 识别到大分类词(赛道关键词)时,会自动推荐细分方向
- 当未查询到您搜索的关键词时,可能因为该词太冷门,我们的收录原则是阅读数>5000。您可以尝试拓展词或者拓展时间,也可以试试关注其他热门赛道获取灵感
公众号趋势洞察数据格式说明
概览
本文档定义了公众号趋势洞察数据查询脚本 fetch_gzh_trends.py 的输入输出格式规范。
重要说明
数据说明:爆款文章范围为阅读数5000+以上的文章,每日早上7点更新昨日数据。文章互动数据截止为入库时间,不是实时数据,入库后互动数据可能持续增长。
排序说明:有关键词搜索时,根据相关性(满分10分)、热度(满分3分)、时效(满分2分)三个维度加权计算,总分共15分;全站热门/无关键词时,按阅读数排序。
接口信息
请求地址:POST https://redfox.hk/story/api/gzh/search/hotArticle
请求头:
Content-Type: application/json
X-API-Key: ak_c4fc9018ffb14ce4ae35dafd92f466c3输入格式
接口请求参数
{
"keyword": "AIGC,aigc创业",
"startDate": "2026-04-14",
"endDate": "2026-05-15"
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
keyword | string | 是 | 搜索关键词,多个关键词用逗号分隔 |
startDate | string | 是 | 开始日期,格式 yyyy-MM-dd |
endDate | string | 是 | 结束日期,格式 yyyy-MM-dd |
脚本命令行参数
python scripts/fetch_gzh_trends.py --keyword <关键词> [选项]| 参数 | 必填 | 说明 | 默认值 |
|---|---|---|---|
--keyword | 是 | 搜索关键词,多个关键词用逗号分隔 | - |
--start-date | 否 | 开始日期,格式 yyyy-MM-dd | 最近30天 |
--max-items | 否 | 最多展示数量 | 10 |
--output-format | 否 | 输出格式:text、json 或 html | html |
--output-file | 否 | 输出文件路径 | 关键词_趋势数据.html |
--debug | 否 | 调试模式,打印原始API响应 | False |
接口返回格式
返回结构
{
"code": 2000,
"msg": "成功",
"data": {
"articles": [...],
"latestHotArticles": [...],
"hotTopics": [],
"keyword": "AIGC,aigc创业",
"pageNum": 1,
"pageSize": 10,
"relatedSearches": [],
"tips": null,
"total": 67
}
}返回字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
code | int | 状态码,2000表示成功 |
msg | string | 状态消息 |
data | object | 数据对象 |
data.articles | array | 文章列表 |
data.latestHotArticles | array | 最新热门文章列表 |
data.hotTopics | array | 热门话题(接口返回,对话中不展示,使用固定赛道列表替代) |
data.keyword | string | 搜索关键词 |
data.pageNum | int | 当前页码 |
data.pageSize | int | 每页数量 |
data.relatedSearches | array | 相关搜索(暂无数据) |
data.tips | string | 提示信息 |
data.total | int | 总数量 |
文章字段(articles数组元素)
| 字段名 | 类型 | 说明 |
|---|---|---|
id | string | 文章ID(唯一标识) |
title | string | 文章标题 |
summary | string | 文章摘要/正文片段 |
author | string | 公众号名称 |
sourceUsernickname | string | 来源用户昵称(可为null) |
url | string | 文章链接 |
imageUrl | string | 封面图片链接 |
publicTime | string | 发布时间(格式:YYYY-MM-DD HH:MM:SS) |
likeCount | int | 点赞数 |
commentsCount | int | 评论数(可为null) |
watchCount | int | 在看数 |
clicksCount | int | 阅读数 |
popularityScore | float | 热度评分 |
recencyScore | float | 时效评分 |
relevanceScore | float | 相关性评分 |
totalScore | float | 总评分 |
publicTagInfo | string | 标签信息(JSON字符串,可为null) |
脚本输出格式
脚本会对接口返回数据进行标准化处理,输出简化后的字段结构。
JSON 输出示例
{
"keyword": "职场",
"total": 10,
"items": [
{
"photoId": "1234567890",
"title": "这些年我做过最正确的职场决定",
"summary": "相信积累的力量,只要活得久,总会走到想到达的地方。",
"accountId": "每日豆瓣",
"accountName": "每日豆瓣",
"fans": 0,
"publicTime": "2024-05-14 07:59:54",
"noteLink": "https://mp.weixin.qq.com/s?...",
"authorLink": "https://open.weixin.qq.com/qr/code?username=每日豆瓣",
"interactiveCount": 6040,
"likeCount": 5139,
"commentCount": 241,
"watchCount": 660,
"clicksCount": "100001",
"dataScore": 34.53
}
]
}脚本输出字段说明
| 字段名 | 类型 | 说明 |
|---|---|---|
photoId | string | 文章ID |
title | string | 文章标题 |
summary | string | 文章摘要 |
accountId | string | 公众号ID/名称 |
accountName | string | 公众号名称 |
fans | int | 粉丝数(固定为0,接口未返回) |
publicTime | string | 发布时间 |
noteLink | string | 文章链接 |
authorLink | string | 作者二维码链接 |
interactiveCount | int | 互动总数(点赞+评论+在看) |
likeCount | int | 点赞数 |
commentCount | int | 评论数 |
watchCount | int | 在看数 |
clicksCount | string | 阅读数 |
dataScore | float | 数据表现分数(0-100分) |
数据评分规则
脚本对文章进行数据表现评分(0-100分),评分维度:
- 点赞权重 30%
- 评论权重 25%
- 在看权重 25%
- 分享权重 20%
使用对数缩放归一化,避免极值影响。
HTML 输出格式
HTML输出采用卡片式布局,Grid自适应2-4列,每张卡片包含: 1. 序号标签 2. 文章标题(可点击跳转) 3. 作者信息 + 发布日期(作者可点击跳转) 4. 互动数 + 在看数 + 查看文章按钮
多关键词处理
- 支持多个关键词用逗号分隔
- 对每个关键词分别查询接口
- 合并所有查询结果
- 基于photoId去重,避免重复文章
- 按dataScore降序排序
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
公众号趋势洞察数据获取脚本
"""
import argparse
import json
import os
import sys
import urllib.request
import urllib.error
from datetime import datetime, timedelta
def _get_api_key():
"""从当前环境变量获取 REDFOX_API_KEY"""
api_key = os.environ.get("REDFOX_API_KEY")
if not api_key:
print("❌ 未找到 REDFOX_API_KEY,请配置环境变量:export REDFOX_API_KEY=<你的apikey>", file=sys.stderr)
sys.exit(1)
return api_key
def _http_post(url, body_dict, headers):
"""使用 urllib.request 发送 POST JSON 请求,返回解析后的 dict,失败返回 None"""
data = json.dumps(body_dict, ensure_ascii=False).encode("utf-8")
req = urllib.request.Request(url, data=data, headers=headers, method="POST")
try:
with urllib.request.urlopen(req, timeout=30) as resp:
raw = resp.read().decode("utf-8")
return json.loads(raw)
except urllib.error.HTTPError as e:
return {"__http_error__": e.code}
except Exception as e:
return {"__error__": str(e)}
def fetch_gzh_trends(keyword, start_date=None, debug=False, auto_expand=True):
"""调用接口获取公众号趋势数据
auto_expand: 当数据不足时,自动拓展时间范围
- 用户指定了时间:按用户指定时间查询,不自动拓展
- 用户未指定时间:默认近7天;数据不足时拓展至近30天
"""
base_url = "https://redfox.hk/story/api/gzh/search/hotArticle"
api_key = _get_api_key()
default_headers = {
"Content-Type": "application/json",
"X-API-Key": api_key
}
end_date = datetime.now().strftime("%Y-%m-%d")
# 用户指定了时间范围,直接按指定时间查询,不自动拓展
if start_date:
result = _do_fetch(keyword, start_date, end_date, headers=default_headers, base_url=base_url, debug=debug)
# 计算用户指定的时间范围天数
days_diff = (datetime.now() - datetime.strptime(start_date, "%Y-%m-%d")).days
result["expandedDays"] = days_diff
return result
# 用户未指定时间,默认近7天
start_7 = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")
result = _do_fetch(keyword, start_7, end_date, headers=default_headers, base_url=base_url, debug=debug)
articles = result.get("articles", [])
# 近7天数据不足10条且允许自动拓展,拓展至近30天
if len(articles) < 10 and auto_expand:
start_30 = (datetime.now() - timedelta(days=30)).strftime("%Y-%m-%d")
result = _do_fetch(keyword, start_30, end_date, headers=default_headers, base_url=base_url, debug=debug)
result["expandedDays"] = 30
result["expandedHint"] = "近7天数据不足,已自动拓展至近30天"
return result
def _do_fetch(keyword, start_date, end_date, headers, base_url, debug=False):
"""实际执行接口请求"""
# 多关键词处理(支持空关键词,接口会返回全站热门)
if keyword and keyword.strip():
keywords = [k.strip() for k in keyword.split(",") if k.strip()]
else:
keywords = [""] # 空关键词,接口返回全站热门数据
all_articles = []
all_latest_hot = []
all_hot_topics = []
all_related_searches = []
for kw in keywords:
json_body = {
"keyword": kw,
"startDate": start_date,
"endDate": end_date,
"source": "公众号爆款文章洞察-GitHub"
}
if debug:
print(f"正在查询关键词: {kw}")
result = _http_post(base_url, json_body, headers)
if "__http_error__" in result:
if debug:
print(f"HTTP错误: {result['__http_error__']}")
elif "__error__" in result:
if debug:
print(f"请求异常: {result['__error__']}")
else:
if debug:
print(f"状态码: 200")
if result.get("code") == 2000:
data = result.get("data", {})
# 正常文章数据
articles = data.get("articles", [])
all_articles.extend(articles)
# 推荐热门文章
latest_hot = data.get("latestHotArticles", [])
all_latest_hot.extend(latest_hot)
# 热门话题
hot_topics = data.get("hotTopics", [])
all_hot_topics.extend(hot_topics)
# 相关搜索
related = data.get("relatedSearches", [])
all_related_searches.extend(related)
if debug:
print(f"获取到 {len(articles)} 篇正常文章")
print(f"获取到 {len(latest_hot)} 篇相关推荐")
else:
if debug:
print(f"接口返回错误: {result.get('msg')}")
# 去重
seen_ids = set()
unique_articles = []
for article in all_articles:
article_id = article.get('id')
if article_id and article_id not in seen_ids:
seen_ids.add(article_id)
unique_articles.append(article)
unique_latest = []
for article in all_latest_hot:
article_id = article.get('id')
if article_id and article_id not in seen_ids:
seen_ids.add(article_id)
unique_latest.append(article)
seen_topics = set()
unique_topics = []
for topic in all_hot_topics:
topic_name = topic.get('name', '') or topic.get('topic', '')
if topic_name and topic_name not in seen_topics:
seen_topics.add(topic_name)
unique_topics.append(topic)
return {
"keyword": keyword,
"articles": unique_articles,
"latestHotArticles": unique_latest,
"hotTopics": unique_topics[:10],
"relatedSearches": all_related_searches[:10],
}
def sort_articles(articles):
"""按总分降序排序文章"""
return sorted(articles, key=lambda x: x.get('totalScore') or 0, reverse=True)
def format_num(n):
"""格式化数字"""
if n >= 10000:
return f"{n/10000:.1f}w"
return str(n)
def generate_recommend_reason(item):
"""生成推荐理由"""
title = item.get('title', '')
relevance = item.get('relevanceScore') or 0
clicks = item.get('clicksCount', 0) or 0
reasons = []
if relevance >= 7:
reasons.append("与关键词高度相关")
elif relevance >= 5:
reasons.append("与关键词较为相关")
if clicks >= 100000:
reasons.append("阅读量10w+")
elif clicks >= 50000:
reasons.append("阅读量较高")
if '技巧' in title or '方法' in title:
reasons.append("实用性强")
elif '误区' in title or '陷阱' in title:
reasons.append("避坑指南")
return ";".join(reasons) if reasons else "综合推荐"
def get_card_html(item):
"""生成单张卡片HTML"""
title = item.get('title', '') or item.get('summary', '')[:50]
author = item.get('author', '') or '-'
pub_time = item.get('publicTime', '')[:10]
note_link = item.get('url', '')
clicks_count = item.get('clicksCount', 0) or 0
watch_count = item.get('watchCount', 0) or 0
relevance = item.get('relevanceScore', 0) or 0
popularity = item.get('popularityScore', 0) or 0
recency = item.get('recencyScore', 0) or 0
total = item.get('totalScore', 0) or 0
reason = generate_recommend_reason(item)
# 截取摘要前100字
summary = item.get('summary', '')[:100] if item.get('summary') else ''
card = f'''
<div class="card">
<div class="card-content">
<div class="card-header">
<h3 class="card-title">
<a href="{note_link}" target="_blank">{title}</a>
</h3>
<div class="card-scores">
<span class="score-tag relevance">相关性 {relevance:.1f}</span>
<span class="score-tag popularity">热度 {popularity:.1f}</span>
<span class="score-tag recency">时效 {recency:.1f}</span>
<span class="score-tag total">总分 {total:.1f}</span>
</div>
</div>
<div class="card-meta">
<span class="author">👤 {author}</span>
<span class="date">📅 {pub_time}</span>
<span class="clicks">👁 阅读 {format_num(clicks_count)}</span>
<span class="watch">👀 在看 {format_num(watch_count)}</span>
</div>
<div class="card-summary">{summary}...</div>
<div class="card-footer">
<span class="reason">💡 {reason}</span>
<a href="{note_link}" target="_blank" class="read-more">查看文章 →</a>
</div>
</div>
</div>
'''
return card
def get_empty_html(keyword, hot_topics):
"""生成空结果HTML"""
# 分类建议
categories = ["AI 前沿", "副业赚钱", "自媒体运营", "工具推荐", "行业案例", "流量增长"]
category_btns = " ".join([f'<span class="category-btn">{cat}</span>' for cat in categories])
# 热门话题列表
topics_html = ""
if hot_topics:
topics_html = '<div class="topics-box">\n<h4>📈 热门话题</h4>\n<ul class="topics-list">\n'
for topic in hot_topics[:6]:
topic_name = topic.get('name', '') or topic.get('topic', '')
count = topic.get('count', 0) or topic.get('articleCount', 0)
topics_html += f'<li>· {topic_name}({count} 篇)</li>\n'
topics_html += '</ul>\n</div>'
html = f'''
<div class="empty-result">
<div class="empty-icon">🔍</div>
<h3 class="empty-title">抱歉,未找到与"{keyword}"直接相关的内容</h3>
<div class="empty-tips">
<h4>💡 你可以试试:</h4>
{topics_html}
<div class="categories-box">
<h4>📂 按分类浏览:</h4>
<div class="categories-list">{category_btns}</div>
</div>
<p class="retry-tip">✏️ 或使用更短/宽泛的关键词重试</p>
</div>
</div>
'''
return html
def get_recommend_section_html(articles):
"""生成相关推荐区域HTML"""
if not articles:
return ""
cards = []
for item in articles[:6]: # 最多展示6条
cards.append(get_card_html(item))
section = f'''
<div class="recommend-section">
<h3 class="section-title">📌 相关推荐</h3>
<div class="recommend-cards">
{"".join(cards)}
</div>
</div>
'''
return section
def get_topics_section_html(hot_topics):
"""生成热门话题区域HTML"""
if not hot_topics:
return ""
topics_html = '<div class="topics-section"><h3>📈 热门话题推荐</h3><div class="topics-grid">'
for topic in hot_topics[:6]:
topic_name = topic.get('name', '') or topic.get('topic', '')
count = topic.get('count', 0) or topic.get('articleCount', 0)
topics_html += f'<div class="topic-item"><div class="topic-name">{topic_name}</div><div class="topic-count">{count} 篇文章</div></div>'
topics_html += '</div></div>'
return topics_html
def generate_html(keyword, articles, latest_hot, hot_topics, result_status):
"""生成HTML页面"""
html_template = '''<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>公众号趋势洞察 - {keyword}</title>
<style>
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
body {{
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}}
.container {{
max-width: 900px;
margin: 0 auto;
}}
.header {{
text-align: center;
padding: 30px 0;
color: white;
}}
.header h1 {{
font-size: 2.5em;
margin-bottom: 10px;
}}
.header .subtitle {{
font-size: 1.1em;
opacity: 0.9;
}}
.partial-tip {{
background: #fff3cd;
border: 1px solid #ffc107;
border-radius: 8px;
padding: 15px;
margin-bottom: 20px;
color: #856404;
}}
.partial-tip strong {{
color: #d63031;
}}
.card {{
background: white;
border-radius: 12px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}}
.card:hover {{
transform: translateY(-5px);
box-shadow: 0 8px 15px rgba(0, 0, 0, 0.2);
}}
.card-content {{
padding: 20px;
}}
.card-header {{
margin-bottom: 15px;
}}
.card-title {{
font-size: 1.2em;
margin-bottom: 10px;
}}
.card-title a {{
color: #2d3436;
text-decoration: none;
}}
.card-title a:hover {{
color: #6c5ce7;
}}
.card-scores {{
display: flex;
gap: 8px;
flex-wrap: wrap;
}}
.score-tag {{
padding: 4px 12px;
border-radius: 12px;
font-size: 0.85em;
font-weight: 500;
}}
.score-tag.relevance {{
background: #e3f2fd;
color: #1976d2;
}}
.score-tag.popularity {{
background: #fff3e0;
color: #f57c00;
}}
.score-tag.recency {{
background: #e8f5e9;
color: #388e3c;
}}
.score-tag.total {{
background: #fce4ec;
color: #c2185b;
}}
.card-meta {{
display: flex;
gap: 15px;
color: #636e72;
font-size: 0.9em;
margin-bottom: 10px;
}}
.card-summary {{
color: #2d3436;
line-height: 1.6;
margin-bottom: 15px;
}}
.card-footer {{
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid #dfe6e9;
padding-top: 10px;
}}
.reason {{
color: #636e72;
font-size: 0.9em;
}}
.read-more {{
color: #6c5ce7;
text-decoration: none;
font-weight: 500;
}}
.read-more:hover {{
text-decoration: underline;
}}
.empty-result {{
background: white;
border-radius: 12px;
padding: 40px;
text-align: center;
}}
.empty-icon {{
font-size: 4em;
margin-bottom: 20px;
}}
.empty-title {{
color: #2d3436;
margin-bottom: 30px;
}}
.empty-tips {{
text-align: left;
}}
.empty-tips h4 {{
color: #6c5ce7;
margin-bottom: 15px;
}}
.topics-box {{
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
}}
.topics-list {{
list-style: none;
}}
.topics-list li {{
padding: 8px 0;
color: #2d3436;
}}
.categories-box {{
background: #f8f9fa;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
}}
.categories-list {{
display: flex;
flex-wrap: wrap;
gap: 10px;
}}
.category-btn {{
background: #6c5ce7;
color: white;
padding: 8px 16px;
border-radius: 20px;
font-size: 0.9em;
cursor: pointer;
transition: background 0.3s;
}}
.category-btn:hover {{
background: #5f27cd;
}}
.retry-tip {{
color: #636e72;
font-style: italic;
margin-top: 15px;
}}
.topics-section {{
background: white;
border-radius: 12px;
padding: 20px;
margin-top: 20px;
}}
.topics-section h3 {{
color: #6c5ce7;
margin-bottom: 15px;
}}
.topics-grid {{
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
}}
.topic-item {{
background: #f8f9fa;
padding: 12px;
border-radius: 8px;
transition: background 0.3s;
}}
.topic-item:hover {{
background: #e9ecef;
}}
.topic-name {{
font-weight: 500;
color: #2d3436;
}}
.topic-count {{
color: #636e72;
font-size: 0.9em;
}}
.recommend-section {{
margin-top: 30px;
}}
.section-title {{
color: white;
font-size: 1.5em;
text-align: center;
margin-bottom: 20px;
padding: 15px;
background: rgba(255, 255, 255, 0.2);
border-radius: 12px;
}}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>📊 公众号趋势洞察</h1>
<p class="subtitle">关键词: {keyword} | 查询结果: {total} 篇文章</p>
</div>
{content}
</div>
</body>
</html>
'''
total = len(articles)
if result_status == "empty":
# articles为0,展示推荐热门文章
content_parts = [get_empty_html(keyword, hot_topics)]
if latest_hot:
content_parts.append(get_recommend_section_html(latest_hot))
content = "\n".join(content_parts)
elif result_status == "partial":
# articles < 10,展示提示 + 文章 + 热门话题 + 推荐热门文章
content_parts = [f'<div class="partial-tip"><strong>💡 仅找到 {total} 条结果</strong>,以下内容可能也对你有帮助:</div>']
for item in articles:
content_parts.append(get_card_html(item))
if hot_topics:
content_parts.append(get_topics_section_html(hot_topics))
if latest_hot:
content_parts.append(get_recommend_section_html(latest_hot))
content = "\n".join(content_parts)
else:
# articles >= 10,正常展示 + 推荐热门文章
content_parts = []
for item in articles:
content_parts.append(get_card_html(item))
if latest_hot:
content_parts.append(get_recommend_section_html(latest_hot))
content = "\n".join(content_parts)
return html_template.format(keyword=keyword, total=total, content=content)
def output_json(keyword, articles, latest_hot, hot_topics, related_searches, result_status, expanded_days=None, expanded_hint=None):
"""输出JSON结果"""
output = {
"keyword": keyword,
"total": len(articles),
"resultStatus": result_status,
"articles": articles,
}
# 根据不同状态附加不同数据
if result_status == "normal":
# articles >= 10,附加推荐热门文章
if latest_hot:
output["latestHotArticles"] = latest_hot
elif result_status == "partial":
# articles < 10,附加热门话题和推荐热门文章
if hot_topics:
output["hotTopics"] = hot_topics
if latest_hot:
output["latestHotArticles"] = latest_hot
elif result_status == "empty":
# articles为0,附加推荐热门文章、热门话题、相关搜索
if latest_hot:
output["latestHotArticles"] = latest_hot
if hot_topics:
output["hotTopics"] = hot_topics
if related_searches:
output["relatedSearches"] = related_searches
output["suggestion"] = "建议使用更短或更宽泛的关键词重试"
# 拓展时间信息
if expanded_days and expanded_hint:
output["expandedDays"] = expanded_days
output["expandedHint"] = expanded_hint
print(json.dumps(output, ensure_ascii=False, indent=2))
def main():
parser = argparse.ArgumentParser(description="获取公众号趋势数据")
parser.add_argument("--keyword", required=True, help="搜索关键词,多个用逗号分隔")
parser.add_argument("--start-date", help="开始日期 (YYYY-MM-DD)")
parser.add_argument("--max-items", type=int, default=50, help="最大返回数量")
parser.add_argument("--output-format", choices=["json", "html"], default="json", help="输出格式")
parser.add_argument("--debug", action="store_true", help="调试模式")
args = parser.parse_args()
# 获取数据
data = fetch_gzh_trends(args.keyword, args.start_date, args.debug)
# 按总分排序
sorted_articles = sort_articles(data["articles"])
sorted_latest = sort_articles(data["latestHotArticles"])
# 限制数量
sorted_articles = sorted_articles[:args.max_items]
sorted_latest = sorted_latest[:10]
# 判断结果状态(基于articles数量)
total_count = len(data["articles"])
if total_count == 0:
result_status = "empty"
elif total_count < 10:
result_status = "partial"
else:
result_status = "normal"
# 输出
if args.output_format == "json":
output_json(
data["keyword"],
sorted_articles,
sorted_latest,
data["hotTopics"],
data["relatedSearches"],
result_status,
data.get("expandedDays"),
data.get("expandedHint")
)
else:
html = generate_html(
data["keyword"],
sorted_articles,
sorted_latest,
data["hotTopics"],
result_status
)
safe_keyword = args.keyword.replace("/", "_").replace("\\", "_")
filename = f"{safe_keyword}_趋势数据.html"
with open(filename, "w", encoding="utf-8") as f:
f.write(html)
print(f"HTML文件已生成: {filename}")
if __name__ == "__main__":
main()