
Wechat Title
- 231 installs
- 316 repo stars
- Updated August 4, 2026
- redfox-data/redfox-community
Use wechat-title for development tasks
About
wechat-title: A skill for development. This provides functionality for development workflows.
- wechat-title
Wechat Title by the numbers
- 231 all-time installs (skills.sh)
- +15 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,709 of 4,347 Backend & APIs 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-titleAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 231 |
|---|---|
| repo stars | ★ 316 |
| Last updated | August 4, 2026 |
| Repository | redfox-data/redfox-community ↗ |
What it does
Use wechat-title for development tasks
Files
公众号标题生成与评分
📋 概述
两大核心功能: 1. 标题生成:基于热门数据生成具有传播力的公众号标题,提供参考爆款文章和分析 2. 标题评分:对用户输入的标题进行多维度评测打分,提供优化建议
功能判断:
| 用户输入 | 使用功能 |
|---|---|
| 主题/关键词/赛道/分类 | 标题生成 |
| 标题 + 评分/优化意图 | 标题评分 |
数据说明:
- 阅读数据截止入库时间,非实时数据,入库后可能持续增长
- 数据库仅包含昨天至30天前的数据
- 默认查询最近7天(startDate = 今天 - 6天)
启动欢迎语(技能打开时必须自动输出):
👋 欢迎使用公众号标题生成与评分!
>
1️⃣ 标题生成 — 输入主题、关键词、赛道、分类,基于热门数据生成公众号爆款标题
>
2️⃣ 标题评分 — 输入一个标题,测评打分并提供优化建议
🔐 鉴权
获取 API Key
请前往 红狐hub 获取API KEY
配置 API Key
方案1: 写入 ~/.openclaw/openclaw.json:
{ "env": { "REDFOX_API_KEY": "ak_xxxx..." } }方案2: 终端配置:
export REDFOX_API_KEY="ak_xxxx..."⚠️ 核心规则
数据来源
- 唯一数据来源:通过
scripts/fetch_official_account_trends.py脚本调用 API 接口 - 禁止:联网搜索、使用其他数据源
- API 接口:
https://redfox.hk/story/api/cozeSkill/getWxCozeSkillData
用词规范
- ❌ 禁止"爬取"、"抓取" → ✅ 统一用"获取"
执行顺序
- 标题生成:必须先分析爆款标题,再生成新标题,不可颠倒
- 泛化词:输出细分词推荐后,必须等待用户回复「拓展」或「不拓展」再调用脚本
关键词分类处理
| 关键词类型 | 示例 | 处理方式 |
|---|---|---|
| 细分词/垂直赛道 | 职场穿搭、减脂餐、小个子穿搭 | 直接查询 |
| 具体内容词 | 防晒霜、情感故事、职场干货 | 直接查询 |
| 泛化词/大分类 | 穿搭、美食、情感 | 执行泛化词拓展策略 |
数据不足处理
不足5条时,按顺序自动扩展时间:近1天 → 近3天 → 近7天 → 近30天
每次扩展提示:"该关键词近X天数据不足5条,已自动扩展时间范围至近Y天"
- ❌ 禁止因数据不足更换关键词、推荐其他词或触发泛化词拓展
- 最终兜底:扩展到30天仍不足5条,如实展示并提示数据不足
- 数据为0时:扩展到30天后仍为0,执行泛化词拓展策略
📊 交互流程
用户输入的任何内容都理解为要生成公众号爆款标题或进行标题评分。
第一步:理解用户输入并提取关键词
精准原则:用户输入什么就查询什么,不随意扩展到相关但不同的内容。
1. 从用户输入中提取核心主题和关键词 2. 按关键词类型处理(见核心规则→关键词分类处理)
示例:
- 用户输入:"我想写关于护肤的内容" → 关键词:护肤 → 标题生成
- 用户输入:"帮我评分这个标题:XXX" → 关键词:从标题提取 → 标题评分
第二步:泛化词拓展策略(仅泛化词执行,细分词跳过直接查询)
1. 生成细分词:查询近7天相关公众号热点,生成10个细分词(趋势词、人群词、场景词、意图词各2-3个) 2. 等待用户回复:禁止用户未回复时调用脚本 3. 根据回复执行:
- 回复「拓展」→ 搜索10个细分词
- 回复「不拓展」→ 搜索原关键词
输出示例:
我识别到「情感」是较大的分类,已查询近期热门趋势,推荐以下细分方向:
恋爱技巧、婚姻经营、婆媳关系、原生家庭、职场人际、社交恐惧、高情商沟通、情绪管理、心理疗愈、分手挽回
回复「拓展」将同时搜索这10个词,回复「不拓展」将继续搜索「情感」第三步:时间范围与数据查询
时间范围:
- 数据范围:昨天至30天前
- 默认:最近7天(startDate = 今天 - 6天)
- 近N天:startDate = 今天 - (N-1)天
执行命令:
# 有关键词
python3 scripts/fetch_official_account_trends.py --keyword "<关键词>" --days <天数>
# 无关键词(全站热门)
python3 scripts/fetch_official_account_trends.py --keyword "" --days <天数>--days 默认7,最大30,脚本自动计算开始日期。
超范围处理:
| 用户请求 | 回复 |
|---|---|
| 今天/今日的数据 | "今天的数据暂未更新,已展示最近可用数据" |
| 超过30天 | "仅支持最近30天的数据,已展示最接近数据" |
第四步:读取爆款数据(内部执行,不输出)
执行命令后,读取生成的 Markdown 文件(关键词_爆款数据.md)。
第五步:分析爆款标题并生成新标题
必须先分析再生成,顺序不可颠倒。
1. 分析爆款标题(内部执行,不输出):提取爆款标题的结构、关键词、情绪、目标人群特征 2. 生成10个新爆款标题:基于分析结果创新创作(非直接采用参考标题),每个标题包含:
- 标题内容(≤30字)
- 匹配指数(8.0-10.0,保留一位小数,同一值最多出现2次)
- 参考的爆款(含文章链接和阅读数,多个用顿号分隔)
- 推荐理由(自然口语化表达,禁止"采用XX结构"、"目标人群为"等AI化句式)
输出格式示例:
基于本次分析,为您生成以下10个爆款标题:
**标题1:这款护肤品真的太好用了**
📈匹配指数:9.8
🔥参考的爆款:[爆款标题A](https://mp.weixin.qq.com/s/xxx)(阅读:XXX)、[爆款标题B](https://mp.weixin.qq.com/s/xxx)(阅读:YYY)
👍推荐理由:用"真的太好用了"这种真实的感受开篇,特别适合分享类文章,读者会忍不住点进去看看具体哪里好。
---
**标题2:新手必看的护肤技巧**
📈匹配指数:9.5
🔥参考的爆款:[爆款标题C](https://mp.weixin.qq.com/s/xxx)(阅读:XXX)
👍推荐理由:"新手必看"四个字就能筛选出精准读者,想学护肤技巧的人会毫不犹豫点进来。
---
(共10个标题,格式同上)使用建议: 1. 先测试匹配指数较高的2-3个标题,观察实际数据表现 2. 根据测试结果调整关键词和表达方式 3. 结合内容特点个性化修改
第六步:格式验证
输出前逐项检查:
| 检查项 | 要求 |
|---|---|
| 标题格式 | **标题X:[内容]**,≤30字 |
| 匹配指数 | 📈匹配指数:[数值],8.0-10.0,一位小数,同值≤2次 |
| 参考爆款 | 🔥参考的爆款:[标题](链接)(阅读:XXX),多个用顿号分隔 |
| 推荐理由 | 👍推荐理由:[理由],自然口语化,禁止AI化表达 |
| 分隔线 | 每个标题块之间 --- |
| 完整性 | 10个标题,每个4行内容 |
📝 标题评分
触发条件
用户直接输入标题并表达评分/优化意图(如"帮我看看这个标题怎么样")
执行流程
1. 理解标题:提取关键词、主题、目标人群 2. 查询数据:
python3 scripts/fetch_official_account_trends.py --keyword "<关键词>" --days 303. 多维度评分(总分100分,所有评分必须基于接口返回的真实数据):
| 维度 | 满分 | 评分要点 |
|---|---|---|
| 赛道匹配度 | 15 | 命中≥3核心词→15分;1-2个→8分;0个→0分。赛道不匹配标注「定位偏离,建议调整」 |
| 点击诱因强度 | 35 | 明确利益/痛点(18分):清晰收益→18,模糊→9,无→0;情绪/好奇心钩子(12分):有→12,通顺无钩→6,平铺直叙→0;稀缺/专属感(5分):有→5,无→0 |
| 结构合规性 | 15 | 字数适配(8分):15-25字→8,过短/过长→4,严重偏离→0;结构偏好(7分):符合10w+→7,普通→4,无逻辑→0;违规扣3-8分 |
| 爆文潜质匹配度 | 35 | 近期热点匹配(20分):命中7天热点→20,泛热点→10,无→0;10w+语义相似度(15分):≥60%→15,30%-60%→8,<30%→0 |
4. 输出评分结果:
## 标题评分结果
**原标题**:[用户输入的标题]
**综合评分**:85分/100分
**各维度评分明细**:
**a. 赛道匹配度(15分)**
- 所属赛道:[自动识别的赛道]
- 命中核心词:[词1]、[词2]、[词3]
- 得分:15分
**b. 点击诱因强度(35分)**
- 明确利益/痛点:18分(有清晰的用户收益)
- 情绪/好奇心钩子:12分(有悬念感)
- 稀缺/专属感:5分(有稀缺暗示)
- 得分:35分
**c. 结构合规性(15分)**
- 字数适配:8分(18字,处于最优区间)
- 结构符合10w+偏好:7分(使用数字+利益结构)
- 无违规/负向感知:不扣分
- 得分:15分
**d. 爆文潜质匹配度(35分)**
- 近期热点匹配:20分(命中热点词XXX)
- 10w+语义相似度:15分(相似度75%)
- 得分:35分
**优势分析**:[自然语言描述标题优点]
**优化建议**:[自然语言描述改进建议]
**参考爆款标题**:
1. [爆款标题1](链接) - 阅读数:XXX
2. [爆款标题2](链接) - 阅读数:XXX- 评分必须客观,基于实际数据和平台特性
- 优化建议必须具体可执行
- 参考爆款标题必须来自查询到的真实数据
📁 资源索引
- 数据查询脚本:scripts/fetch_official_account_trends.py
WeChat Official Account Title Generator & Scorer / wechat-title
---
Introduction
Generate viral WeChat Official Account titles based on trending data, or get multi-dimensional scoring and optimization suggestions for your existing titles.
Core Value
- Analyze Before Creating: First analyze viral title patterns, then output new titles — clear logic, easy to pick from.
- Dual-Mode Delivery: Title generation gives 10 formatted candidates at once; title scoring provides four-dimension grading with optimization direction.
- Data-Aligned: All title creation and scoring are based on real WeChat viral article data — no guesswork.
Who It's For
- 📝 WeChat Account Owners — Stop struggling with titles. Use data patterns to boost click-through rates and readership.
- 📊 Content Operators / Editors — Quickly produce multiple title candidates for A/B testing with confidence.
- 🏢 MCNs / Brands — Batch-propose titles within the same niche, building reusable title formulas.
---
Features
Core Features
- Title Generation: Enter a topic, keyword, or niche — the tool first analyzes viral title patterns, then creates 10 new titles, each with a match score, reference viral article link, and recommendation reason.
- Title Scoring: Enter an existing title — get a four-dimension evaluation (niche match, click incentive, structure compliance, viral potential) scored out of 100, with optimization suggestions and reference viral titles.
- Smart Keyword Handling: Broad category terms trigger a sub-direction recommendation for you to confirm first; specific terms go straight to data matching.
- Auto Time Expansion: When data is insufficient, the query time range is automatically expanded — your core keyword is never changed without your consent.
---
API Key Acquisition & Security
- This skill requires the environment variable:
REDFOX_API_KEY. REDFOX_API_KEYis provided by RedFoxHub (https://redfox.hk).- Please visit RedFoxHub to register and obtain
REDFOX_API_KEY. - Configure the
REDFOX_API_KEYenvironment variable on your device before using this skill. - Before providing a key, please confirm its source, scope of use, validity period, and whether it supports reset/revocation.
- Never hard-code or expose keys in plain text within code, prompts, logs, or output files.
---
Usage Guide
Simply describe your needs in natural language — no commands to memorize.
Quick Reference
| Intent | Example Prompt | Result |
|---|---|---|
| Generate titles for a topic | "I want to write about skincare, help me come up with some titles" | Matches viral samples by keyword, analyzes first, then outputs 10 candidates |
| Daily niche update | "Career niche, want to post about promotion strategies, give me some titles" | Pulls niche viral patterns, generates matching new titles |
| Refine a broad category | "I want to do food content, but haven't decided on a direction" | Recommends sub-directions first, then queries and generates after your confirmation |
| Catch trending topics | "What titles are trending on WeChat? Help me create a few" | Generates viral titles based on sitewide trending data |
| Score a title | "Help me evaluate this title: XXX" | Four-dimension scoring with optimization suggestions |
Output Example
After Title Generation, you'll receive 10 titles in the following format (illustrative):
Title 1: This Is the Right Way to Do Skincare
📈 Match Score: 9.5 🔥 Reference Viral: Viral title summary (Reads: 100k+) 👍 Reason: "This is" carries a corrective tone, making readers wonder "Have I been doing it wrong?" — perfect for how-to and science articles.
---
(10 titles total, each separated by a divider for easy copying.)
After Title Scoring, you'll receive a four-dimension score breakdown, strength analysis, optimization suggestions, and reference viral titles.
---
Use Cases
| Scenario | Role | Example Prompt | Benefit |
|---|---|---|---|
| Title for a new post | Account owner | "New product launch, help me write a title highlighting cost-effectiveness" | Quickly get multiple publishable candidates, boost CTR |
| Daily account update | Content operator | "Career niche, posting about promotion strategies this week, give me 10 titles" | Follow niche viral patterns, reduce topic ideation overhead |
| Exploring a broad category | New creator | "I want to do relationship content, but only know the broad category" | Sub-direction refinement before generation, lower trial-and-error cost |
| Title optimization | Editor / Director | "Score this title for me: XXX, how can I improve it" | Diagnose bottlenecks across four dimensions, optimize precisely |
| Adapt trending content | Content strategist | "What titles are trending sitewide? Help me adapt a few" | Apply trending patterns to your specific topics |
---
Important Data Notes
- Read counts reflect the time of database entry, not real-time data. Counts may continue to grow after entry.
- The database only contains data from yesterday to 30 days ago. Same-day and 30+ day lookbacks are not currently supported.
公众号标题生成与评分 / wechat-title
---
简介
基于公众号热门数据,帮你生成具有传播力的爆款标题,或对已有标题进行多维度评分与优化建议。
核心价值
- 先析后写:先完成爆款标题分析,再输出新标题,规律清晰、便于选用。
- 双模式交付:标题生成一次给出 10 条统一版式备选;标题评分给出四维度打分与优化方向。
- 数据对齐:所有标题创作与评分均基于公众号真实爆款数据,避免凭空臆造。
适用对象
- 📝 公众号号主 — 告别标题纠结,用数据规律提升文章点击率与阅读量。
- 📊 内容运营 / 新媒体编辑 — 快速产出多组备选标题,A/B 测试更有底气。
- 🏢 MCN / 品牌方 — 同赛道批量提案,沉淀可复用的标题套路。
---
功能特性
核心功能
- 标题生成:输入主题、关键词或赛道,基于公众号热门数据先分析爆款规律,再创作 10 条新标题,每条附带匹配指数、参考爆款链接与推荐理由。
- 标题评分:输入一个已有标题,从赛道匹配度、点击诱因强度、结构合规性、爆文潜质四个维度评测打分(满分 100),并给出优化建议与参考爆款。
- 智能关键词处理:输入大类词时先推荐细分方向,由你确认后再查询;输入具体词则直接匹配数据。
- 自动时间扩展:数据不足时自动扩大查询时间范围,不擅自更换你的核心关键词。
---
密钥获取与安全说明
- 本技能需要使用环境变量:
REDFOX_API_KEY。 REDFOX_API_KEY由 红狐 hub (https://redfox.hk)提供。- 请前往 红狐 hub 注册账号,获取
REDFOX_API_KEY。 - 配置设备环境变量
REDFOX_API_KEY后使用本技能。 - 在提供密钥前,请先确认密钥来源、可用范围、有效期及是否支持重置/撤销。
- 禁止在代码、提示词、日志或输出文件中硬编码/明文暴露密钥。
---
使用指南
直接用自然语言描述你的需求即可,无需记忆固定命令。
常用说法速查
| 意图 | 示例话术 | 效果 |
|---|---|---|
| 为选题起标题 | 「我想写关于护肤的内容,帮我起几个标题」 | 按关键词对齐爆款样本,先分析再出 10 条备选 |
| 赛道日常更新 | 「职场赛道,最近想发晋升攻略,来一组标题」 | 拉取同赛道爆款规律,生成匹配的新标题 |
| 大类先细分 | 「想做美食方向的内容,但方向还没定」 | 先推荐细分方向,你确认后再查询与生成 |
| 追全站热点 | 「最近公众号什么标题火,帮我编几条」 | 基于全站热门数据生成爆款标题 |
| 标题评分 | 「帮我看看这个标题怎么样:XXX」 | 四维度评测打分,给出优化建议 |
输出示例
标题生成完成后,你将收到 10 条标题,每条大致如下(示意):
标题1:这才是正确的护肤方法
📈 匹配指数:9.5 🔥 参考的爆款:原爆款标题摘要(阅读:10w+) 👍 推荐理由:"这才是"三个字带着点纠正的味道,让人好奇"我之前做错了吗?"特别适合方法类、科普类文章。
---
(共 10 条,条与条之间以分隔线区分,便于复制选用。)
标题评分完成后,你将收到四维度评分明细、优势分析、优化建议与参考爆款标题。
---
使用场景
| 场景 | 角色 | 示例问法 | 收益 |
|---|---|---|---|
| 新文起标题 | 公众号号主 | 「新品上市,帮我写公众号标题,突出性价比」 | 快速得到多组可发布备选,提升点击率 |
| 账号日常更新 | 内容运营 | 「职场赛道,这周想发晋升攻略,来 10 个标题」 | 延续赛道爆款规律,减少选题空转 |
| 大类试水 | 新手创作者 | 「想做情感内容,但只知道大类」 | 先细分方向再生成,降低盲目试错成本 |
| 标题优化 | 编辑 / 编导 | 「帮我评分这个标题:XXX,看看怎么改更好」 | 四维度诊断瓶颈,精准优化 |
| 追热点改编 | 内容策划 | 「最近全站什么标题火?帮我改编几条」 | 把热门规律落到自己的具体选题 |
---
重要数据说明
- 阅读数据截止为入库时间,非实时数据,入库后阅读量可能持续增长。
- 数据库仅包含昨天至 30 天前的数据,暂不支持当天与 30 天以上回溯。
#!/usr/bin/env python3
"""
公众号标题生成与评分数据查询脚本
"""
import sys
import os
import argparse
import json
from datetime import datetime, timedelta
try:
import requests
except ImportError:
print("错误: 缺少 requests 库,请运行 pip install requests 安装", file=sys.stderr)
sys.exit(1)
def fetch_official_account_trends(keyword: str, debug: bool = False, max_retries: int = 3, days: int = 7):
"""
调用接口获取公众号爆款标题数据
Args:
keyword: 搜索关键词(多个关键词用逗号分隔,最多5个,总长度不超过200)
debug: 是否打印调试信息
max_retries: 最大重试次数
days: 查询最近几天的数据,默认7天,最大30天
Returns:
dict: 包含3类爆款数据
Raises:
Exception: 当API调用失败时抛出异常
"""
# 确保天数不超过30天
days = min(days, 30)
# 计算开始日期(今天 - (days-1) 天)
end_date = datetime.now()
start_date_obj = end_date - timedelta(days=days-1)
start_date_str = start_date_obj.strftime('%Y-%m-%d')
if debug:
print(f"DEBUG: 查询最近 {days} 天数据,开始日期: {start_date_str}", file=sys.stderr)
# 接口地址
url = "https://redfox.hk/story/api/cozeSkill/getWxCozeSkillData"
# 请求参数
params = {
"keyword": keyword,
"source": "公众号爆款标题生成-GitHub",
"startDate": start_date_str
}
# 从环境变量获取API Key
api_key = os.environ.get("REDFOX_API_KEY")
if not api_key:
raise Exception("缺少 REDFOX_API_KEY 环境变量,请先配置 API Key。获取地址:https://redfox.hk/settings/api-keys?source=github")
# 请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "application/json, text/plain, */*",
"Accept-Language": "zh-CN,zh;q=0.9",
"X-API-Key": api_key
}
last_error = None
for attempt in range(max_retries):
try:
if debug:
print(f"\n=== DEBUG: 第 {attempt + 1} 次尝试 ===", file=sys.stderr)
print(f"URL: {url}", file=sys.stderr)
print(f"Params: {params}", file=sys.stderr)
print(f"Headers: {headers}", file=sys.stderr)
# 发送请求
response = requests.get(url, params=params, headers=headers, timeout=60)
if debug:
print(f"状态码: {response.status_code}", file=sys.stderr)
print(f"响应长度: {len(response.text)} 字节", file=sys.stderr)
if response.status_code >= 400:
raise Exception(f"HTTP请求失败: 状态码 {response.status_code}")
data = response.json()
if debug:
print("=== DEBUG: 完整 API 响应 ===", file=sys.stderr)
print(json.dumps(data, ensure_ascii=False, indent=2), file=sys.stderr)
# 检查业务错误码
code = data.get("code", 0)
if code != 2000: # 2000 表示成功
error_msg = data.get("msg", "未知错误")
raise Exception(f"API 错误: {error_msg}")
if "data" not in data or data["data"] is None:
raise Exception("API 返回数据为空")
result_data = data.get("data", {})
# 提取两类榜单数据
one_w_reading = result_data.get("oneWReadingRank", [])
original = result_data.get("originalRank", [])
return {
"oneWReadingRank": one_w_reading,
"originalRank": original
}
except Exception as e:
last_error = e
if debug:
print(f"DEBUG: 第 {attempt + 1} 次请求失败: {e}", file=sys.stderr)
if attempt < max_retries - 1:
import time
time.sleep(1)
raise Exception(f"API调用失败,已重试{max_retries}次: {last_error}")
def format_article_link(article: dict) -> str:
"""
格式化文章链接,优先使用oriUrl
Args:
article: 文章数据字典
Returns:
str: 格式化的文章链接
"""
# 优先使用 oriUrl
if "oriUrl" in article and article["oriUrl"]:
return article["oriUrl"]
# 回退使用 photoId
photo_id = article.get("photoId", "")
if photo_id:
return f"https://mp.weixin.qq.com/s/{photo_id}"
return "无链接"
def get_cover_urls(articles: list) -> list:
"""
提取文章封面图链接
Args:
articles: 文章列表
Returns:
list: 封面图链接列表
"""
cover_urls = []
for article in articles:
cover_url = article.get("coverUrl", "")
if cover_url:
# 优先使用oriUrl作为文章链接
article_link = format_article_link(article)
cover_urls.append({
"cover_url": cover_url,
"title": article.get("title", "无标题"),
"link": article_link
})
return cover_urls
def deduplicate_articles(articles: list) -> list:
"""
去重文章列表(基于标题)
Args:
articles: 文章列表
Returns:
list: 去重后的文章列表
"""
seen_titles = set()
unique_articles = []
for article in articles:
title = article.get("title", "")
if title and title not in seen_titles:
seen_titles.add(title)
unique_articles.append(article)
return unique_articles
def parse_number(num_str):
"""
解析数字字符串(如"9w+"转换为数字90000)
Args:
num_str: 数字字符串或数字
Returns:
int: 解析后的数字
"""
if isinstance(num_str, (int, float)):
return int(num_str)
if not num_str or not isinstance(num_str, str):
return 0
# 处理 "9w+" 格式
num_str = str(num_str).strip()
if 'w+' in num_str.lower() or '万+' in num_str:
# 提取数字部分
num_part = num_str.replace('w+', '').replace('W+', '').replace('万+', '')
try:
return int(float(num_part) * 10000)
except:
return 0
elif 'w' in num_str.lower() or '万' in num_str:
num_part = num_str.replace('w', '').replace('W', '').replace('万', '')
try:
return int(float(num_part) * 10000)
except:
return 0
# 处理普通数字
try:
return int(float(num_str))
except:
return 0
def sort_by_reads(articles: list) -> list:
"""
按阅读数排序文章
Args:
articles: 文章列表
Returns:
list: 排序后的文章列表
"""
return sorted(articles, key=lambda x: parse_number(x.get("clicksCount", 0)), reverse=True)
def format_number(num) -> str:
"""
格式化数字显示(如果是字符串如"9w+"则直接返回,大于10000显示为X万+)
Args:
num: 数字或字符串
Returns:
str: 格式化的数字字符串
"""
# 如果已经是字符串格式(如"9w+"),直接返回
if isinstance(num, str):
return num
if isinstance(num, (int, float)):
if num >= 10000:
return f"{int(num // 10000)}万+"
return str(int(num))
return str(num)
def generate_markdown_output(keyword: str, data: dict, output_file: str = None) -> str:
"""
生成Markdown格式的输出
Args:
keyword: 搜索关键词
data: 数据字典
output_file: 输出文件路径(可选)
Returns:
str: Markdown格式的输出内容
"""
one_w_reading = data.get("oneWReadingRank", [])
original = data.get("originalRank", [])
# 去重和排序
one_w_reading = sort_by_reads(deduplicate_articles(one_w_reading))
original = sort_by_reads(deduplicate_articles(original))
# 统计总数
total_count = len(one_w_reading) + len(original)
# 构建Markdown内容
lines = []
lines.append(f"**关键词**:{keyword}")
lines.append(f"**查询时间范围**:近7天")
lines.append(f"**数据总量**:{total_count}条爆款文章")
lines.append("")
# 1w+阅读榜
if one_w_reading:
lines.append("## 1w+阅读榜")
lines.append("")
lines.append("| 标题 | 作者 | 阅读数 | 在看数 | 点赞数 | 评论数 | 分享数 | 阅读总数 | 发布时间 |")
lines.append("|------|------|--------|--------|--------|--------|--------|----------|----------|")
for article in one_w_reading[:50]: # 最多显示50条
title = article.get("title", "无标题")
link = format_article_link(article)
author = article.get("userName", "未知")
reads = format_number(article.get("clicksCount", 0))
watch = format_number(article.get("watchCount", 0))
likes = format_number(article.get("likeCount", 0))
comments = format_number(article.get("commentCount", 0))
shares = format_number(article.get("shareCount", 0))
total_reads = format_number(article.get("interactiveCount", 0))
pub_time = article.get("publicTime", "未知")
lines.append(f"| [{title}]({link}) | {author} | {reads} | {watch} | {likes} | {comments} | {shares} | {total_reads} | {pub_time} |")
lines.append("")
# 原创榜
if original:
lines.append("## 原创榜")
lines.append("")
lines.append("| 标题 | 作者 | 阅读数 | 在看数 | 点赞数 | 评论数 | 分享数 | 阅读总数 | 发布时间 |")
lines.append("|------|------|--------|--------|--------|--------|--------|----------|----------|")
for article in original[:50]: # 最多显示50条
title = article.get("title", "无标题")
link = format_article_link(article)
author = article.get("userName", "未知")
reads = format_number(article.get("clicksCount", 0))
watch = format_number(article.get("watchCount", 0))
likes = format_number(article.get("likeCount", 0))
comments = format_number(article.get("commentCount", 0))
shares = format_number(article.get("shareCount", 0))
total_reads = format_number(article.get("interactiveCount", 0))
pub_time = article.get("publicTime", "未知")
lines.append(f"| [{title}]({link}) | {author} | {reads} | {watch} | {likes} | {comments} | {shares} | {total_reads} | {pub_time} |")
lines.append("")
# 如果没有任何数据
if total_count == 0:
lines.append("⚠️ **提示**:查询结果为空,可能原因:")
lines.append("1. 该关键词近7天无爆款文章")
lines.append("2. 关键词过于生僻或专业")
lines.append("3. 建议使用更通用的关键词或扩大时间范围")
content = "\n".join(lines)
# 如果指定了输出文件,保存到文件
if output_file:
with open(output_file, 'w', encoding='utf-8') as f:
f.write(content)
return content
def main():
"""主函数"""
parser = argparse.ArgumentParser(description="公众号标题生成与评分数据查询")
parser.add_argument("--keyword", required=True, help="搜索关键词")
parser.add_argument("--days", type=int, default=7, help="查询最近几天的数据,默认7天,最大30天")
parser.add_argument("--output", help="输出文件路径(可选)")
parser.add_argument("--debug", action="store_true", help="打印调试信息")
args = parser.parse_args()
try:
# 获取数据
data = fetch_official_account_trends(
keyword=args.keyword,
debug=args.debug,
days=args.days
)
# 生成输出
output_file = args.output if args.output else f"{args.keyword}_爆款数据.md"
content = generate_markdown_output(args.keyword, data, output_file)
# 输出JSON结果
result = {
"status": "success",
"keyword": args.keyword,
"days": args.days,
"total_count": len(data.get("tenWReadingRank", [])) +
len(data.get("originalRank", [])),
"output_file": output_file,
"message": f"成功获取{args.keyword}的爆款数据,已保存到{output_file}"
}
print(json.dumps(result, ensure_ascii=False))
except Exception as e:
error_result = {
"status": "error",
"keyword": args.keyword,
"error": str(e)
}
print(json.dumps(error_result, ensure_ascii=False))
sys.exit(1)
if __name__ == "__main__":
main()