
Wechat Cover
- 227 installs
- 316 repo stars
- Updated August 4, 2026
- redfox-data/redfox-community
Use wechat-cover for development tasks
About
wechat-cover: A skill for development. This provides functionality for development workflows.
- wechat-cover
Wechat Cover by the numbers
- 227 all-time installs (skills.sh)
- +16 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #1,745 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-coverAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 227 |
|---|---|
| repo stars | ★ 316 |
| Last updated | August 4, 2026 |
| Repository | redfox-data/redfox-community ↗ |
What it does
Use wechat-cover for development tasks
Files
公众号封面图制作
📋 概述
基于全网每日收录的爆款文章数据,获取同赛道爆款封面的视觉元素,通过AI分析总结高转化视觉规律,生成贴合文章内容、符合平台流量审美的封面设计方案(含案例+生图提示词)。仅在主Agent中执行,不派发给子Agent。
🎯 触发规则
| 场景 | 处理方式 |
|---|---|
| 用户提供内容主题/赛道 | 执行任务流程 |
| 用户要求生成封面方案 | 执行任务流程 |
| 用户上传文案或图片要求分析 | 执行任务流程 |
| 用户询问技能功能/用法 | 仅介绍技能 |
| 用户未提供明确创作主题 | 仅介绍技能 |
📝 术语规范
统一使用"爆款封面",禁止使用:爆炸封面→爆款封面、爆炸数据→爆款数据、抓取数据→获取/查询数据、抓取封面→获取封面。
🔒 数据来源
所有爆款数据必须来自接口,禁止联网搜索、使用其他数据源或脑补数据。数据不足时明确告知用户。
🔑 鉴权
获取 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..."⚙️ 前置准备
- 依赖:
requests(pip install requests) - 凭证:环境变量
REDFOX_API_KEY(详见鉴权章节) - 数据范围:仅含昨天至30天前的数据,默认查询近30天
🔄 操作流程
步骤1:意图解析
结构化解析用户需求,提取4个维度:
| 维度 | 说明 | 示例 |
|---|---|---|
| 内容主题 | 优先领域词 | 护肤、穿搭、美食、职场 |
| 内容类型 | 内容形式 | 干货、测评、种草、教程 |
| 风格偏好 | 视觉/调性 | 专业、吸引点击、情绪、极简 |
| 核心关键词 | 搜索关键词 | 秋冬、美白、护肤、干皮 |
提取2-5个核心关键词(逗号分隔),优先细分领域词,结合风格偏好补充场景词。
步骤2:爆款数据查询
# 有赛道关键词
python3 scripts/fetch_explosive_covers.py --keyword <关键词1,关键词2,关键词3>
# 无赛道关键词
python3 scripts/fetch_explosive_covers.py --keyword ""- 最多5个关键词,总长度≤200字符
- 默认近30天(不传 startDate);用户指定"近N天"时 startDate = 今天 - (N-1)天
步骤3:智能匹配筛选
| 数据量 | 处理 |
|---|---|
| ≥20条 | 直接使用 |
| <20条 | 扩展关键词(如:美白→美白、护肤、美白祛斑),重新查询,合并数据 |
筛选规则:按阅读数从高到低排序,取前20条。关键词扩展最多1-2次,每次2-3个相似词。
步骤4:AI图像分析与特征提取
1. 解析脚本返回的JSON数据(含 low_fan_explosive、ten_w_reading、original_rank 三个数组) 2. 提取 coverUrl 字段合并为封面候选池——直接使用原始值,不做任何修改 3. 按互动量从高到低取前20条 4. 逐张分析封面图(使用原生图片理解能力,直接访问coverUrl)
7维度分析:
| 维度 | 分析内容 |
|---|---|
| 文字内容 | 是否有文字、内容、字体大小、位置、颜色、醒目程度 |
| 主体元素 | 人物/产品/场景/图案等主要视觉元素 |
| 色彩特征 | 主色调、配色方案、对比度、冷暖色调 |
| 构图布局 | 画面结构、元素分布、主体位置、留白处理 |
| 视觉风格 | 实拍/插画/拼贴/极简/炫酷等风格类型 |
| 点击吸引力 | 痛点/好奇/美感/实用——为什么吸引点击 |
| 尺寸检测 | 宽x高,是否合格(≥10px) |
图片过滤规则:
- 空白图片(纯色块、无内容):标注"需过滤",后续所有环节排除
- 小尺寸图片(宽或高 <10px):全部过滤
- 输出前二次检查:确保无空白/小尺寸图片混入
分类汇总:将相似风格的封面归为同一类,统计特征规律(分类前先过滤空白图片)。
步骤5:输出HTML分析报告与设计方案
必须使用 references/report_template.md 模板,禁止自行编写HTML。
1. 读取模板 → 填充数据 → 写入 ./爆款封面分析报告_{关键词}.html 2. 生成后必须立即读取并展示HTML内容
| 要求 | 说明 |
|---|---|
| 模板 | 读取 references/report_template.md |
| 结构 | 分析报告+设计方案合并在同一个HTML文件中 |
| 防盗链 | <meta name="referrer" content="no-referrer"> |
| 封面展示 | 按风格类型分类,每类最多5张 |
| 案例参考 | coverUrl原始值 + 标题(oriUrl链接) + 作者 + 仅阅读数 |
| 样式 | 所有样式内联,禁止hover效果 |
| 生图提示词 | 严格遵循 2.35:1 横版比例 |
步骤6:用户选择方案并生成封面图
⚠️ 先询问用户,等回复后再生成——不要在用户选择前就生成封面图!
第一阶段(输出报告后立即执行):HTML模板末尾已包含方案选择区域,展示报告后停止,等待用户回复。
第二阶段(用户回复后执行): 1. 确认用户选择的方案(1/2/3)及其生图提示词 2. 如用户上传了图片,用原生图片理解能力分析 3. 使用原生图像生成能力生成封面图(2.35:1,900x383像素) 4. 直接展示图片,不需要HTML包裹
步骤7:输出前自检
| 检查项 | 内容 |
|---|---|
| 风格类型 | 每类有:名称、频次、核心视觉、关键特征、封面示例 |
| 三个方案 | 各有风格名称、核心视觉、案例参考(不重复)、生图提示词 |
| 封面图链接 | coverUrl使用原始值 |
| 图片过滤 | 无空白图片、无小尺寸图片 |
| 用户交互 | 已询问方案选择并等待回复 |
⚠️ 注意事项
- 封面图容器比例 2.35:1 (900x383),使用
object-fit: cover+object-position: center自适应截取 - HTML添加防盗链 meta 标签
<meta name="referrer" content="no-referrer"> - 案例参考仅保留阅读数(clicksCount),删除点赞和在看
- 封面图用
<a>标签包裹可点击跳转大图,方案标题用 oriUrl 链接 - 图像分析使用原生图片理解能力,直接访问封面URL,逐张分析
WeChat Cover Design / wechat-cover
---
Introduction
Based on daily collected 100K+ article data from across the web, this tool retrieves visual elements from explosive covers in the same niche, analyzes high-conversion visual patterns through AI, and generates cover design proposals that match your content and fit the platform's traffic aesthetics.
Core Value
- Massive Sample Alignment: Continuously collects explosive article covers daily, ensuring design proposals are data-driven rather than imagined.
- Analyze First, Design Later: Completes explosive cover style analysis and classification before outputting design proposals, making patterns clear and easy to choose.
- Proposal + Image Generation All-in-One: Each proposal includes image generation prompts; after selection, a 2.35:1 cover image can be generated directly.
Target Users
- ✍️ WeChat Official Account Creators — Stop struggling with cover design, use explosive patterns to boost article click rates.
- 📊 Content Operators — Quickly produce multiple cover proposals by niche keywords for efficient A/B testing.
- 🏢 MCN / New Media Teams — Batch propose covers for the same niche, building reusable visual templates.
---
Features
Core Features
- Keyword-Driven: Enter a niche or content keyword to automatically retrieve explosive cover data for that field.
- 7-Dimension Cover Analysis: Analyzes each cover image across text content, main elements, color characteristics, composition layout, visual style, click appeal, and dimensions for deep pattern extraction.
- Style Classification Summary: Groups similar-style covers into categories, displaying representative covers and characteristic patterns by type.
- 3 Design Proposals: Generates 3 differentiated cover design proposals based on analysis results, each with core visuals, case references, and image generation prompts.
- One-Click Image Generation: After selecting a proposal, directly generates a 2.35:1 (900×383) cover image; supports uploading reference images.
---
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 an account and obtain
REDFOX_API_KEY. - Configure the environment variable
REDFOX_API_KEYon 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 niche, content topic, or cover needs in natural language — no commands to memorize.
Quick Reference
| Intent | Example Phrase | Result |
|---|---|---|
| Design by niche | "Design a beauty tutorial cover for me" | Retrieves beauty niche explosive cover data, analyzes styles, generates 3 proposals |
| Design by content topic | "Autumn whitening skincare tips, want a professional-looking cover" | Parses content intent, matches professional-style cover patterns |
| Upload reference image | "Design a cover referencing this image" + upload | Analyzes reference image style, combines with explosive data to generate proposals |
| Select proposal to generate | Reply "Choose proposal 1" | Generates 900×383 cover image per the proposal prompt |
Output Example
After analysis, you'll receive a visual cover analysis report (HTML page) containing:
- Style Classification Display: Representative covers and characteristic patterns for each style type
- 3 Design Proposals: Each with style name, core visuals, case references, and image generation prompts
- Proposal Selection Area: Select a proposal to generate the cover image
---
Use Cases
| Scenario | Role | Example Question | Benefit |
|---|---|---|---|
| New article cover | WeChat creator | "Publishing skincare tips today, help me design a cover" | Generate professional cover proposals based on explosive data |
| Niche daily updates | Content operator | "Workplace fashion niche, need a set of cover proposals" | Quickly produce multiple style proposals for A/B testing |
| Custom with reference | Designer | "Design a cover referencing this image" + upload | Combine reference image with explosive patterns |
| Trend-chasing covers | Media editor | "See what covers are hot in the beauty niche lately" | Get recent explosive cover styles, stay on trend |
---
Important Data Notes
- The database only contains data from yesterday to 30 days ago
- Default time range is the last 30 days
公众号封面图制作 / wechat-cover
---
简介
基于全网每日持续收录的 10w+ 文章数据,获取同赛道爆款封面的视觉元素,通过 AI 分析总结高转化视觉规律,生成贴合文章内容、符合平台流量审美的封面设计方案。
核心价值
- 海量样本对齐:每日持续收录爆款文章封面,设计方案有据可依,避免凭空臆造。
- 先析后做:先完成爆款封面风格分析与分类,再输出设计方案,规律清晰、便于选用。
- 方案+生图一体:每个方案附带生图提示词,选中后可直接生成 2.35:1 封面图。
适用对象
- ✍️ 公众号创作者 — 告别封面设计纠结,用爆款规律提升文章点击率。
- 📊 内容运营 — 按赛道关键词快速产出多组封面方案,A/B 测试更高效。
- 🏢 MCN / 新媒体团队 — 同赛道批量提案封面,沉淀可复用的视觉套路。
---
功能特性
核心功能
- 关键词驱动:输入赛道或内容关键词,自动获取同领域爆款封面数据。
- 7 维度封面分析:逐张分析封面图的文字内容、主体元素、色彩特征、构图布局、视觉风格、点击吸引力、尺寸,深度拆解爆款视觉规律。
- 风格分类汇总:将相似风格的封面归为同一类,按类型展示代表性封面与特征规律。
- 3 套设计方案:基于分析结果生成 3 套差异化封面设计方案,各含核心视觉、案例参考与生图提示词。
- 一键生图:用户选择方案后,直接生成 2.35:1(900×383)封面图,支持上传参考图片。
---
密钥获取与安全说明
- 本技能需要使用环境变量:
REDFOX_API_KEY。 REDFOX_API_KEY由 红狐 hub (https://redfox.hk)提供。- 请前往 红狐 hub 注册账号,获取
REDFOX_API_KEY。 - 配置设备环境变量
REDFOX_API_KEY后使用本技能。 - 在提供密钥前,请先确认密钥来源、可用范围、有效期及是否支持重置/撤销。
- 禁止在代码、提示词、日志或输出文件中硬编码/明文暴露密钥。
---
使用指南
直接用自然语言说出你的赛道、内容主题或封面需求即可,无需记忆固定命令。
常用说法速查
| 意图 | 示例话术 | 效果 |
|---|---|---|
| 按赛道设计封面 | 「帮我设计美妆教程封面」 | 获取美妆赛道爆款封面数据,分析风格后生成 3 套方案 |
| 按内容主题设计 | 「秋冬美白护肤心得,想要专业感的封面」 | 解析内容意图,匹配专业风格封面规律 |
| 上传参考图 | 「帮我参考这张图设计封面」 + 上传图片 | 分析参考图风格,结合爆款数据生成方案 |
| 选择方案生图 | 回复「选方案 1」 | 按方案提示词生成 900×383 封面图 |
输出示例
完成分析后,你将收到一份可视化封面分析报告(HTML 页面),包含:
- 风格分类展示:每类风格的代表性封面图与特征规律
- 3 套设计方案:各含风格名称、核心视觉、案例参考与生图提示词
- 方案选择区域:选择后即可生成封面图
---
使用场景
| 场景 | 角色 | 示例问法 | 收益 |
|---|---|---|---|
| 新文配封面 | 公众号创作者 | 「今天发护肤干货,帮我设计封面」 | 基于爆款数据生成专业封面方案 |
| 赛道日常更新 | 内容运营 | 「职场穿搭赛道,需要一组封面方案」 | 快速产出多组风格方案,A/B 测试 |
| 参考图定制 | 设计师 | 「参考这张图帮我出封面」+ 上传图片 | 结合参考图与爆款规律生成方案 |
| 热点追封面 | 新媒体编辑 | 「看看最近美妆赛道什么封面火」 | 获取近期爆款封面风格,紧跟热点 |
---
重要数据说明
- 数据库仅包含昨天至 30 天前的数据
- 默认时间范围为最近 30 天
公众号爆款数据格式说明
概览
本文档定义了公众号爆款数据查询脚本 fetch_gzh_trends.py 的输入输出格式规范。
输入格式
脚本参数
python scripts/fetch_gzh_trends.py --keyword <关键词> [选项]| 参数 | 必填 | 说明 | 默认值 |
|---|---|---|---|
--keyword | 是 | 搜索关键词(支持多个关键词,逗号分隔,最多5个,总长度不超过200字符) | - |
--start-date | 否 | 开始日期,格式 yyyy-MM-dd | 最近30天 |
--max-items | 否 | 每类内容最多展示数量 | 10 |
--output-format | 否 | 输出格式:text、json 或 html | html |
--output-file | 否 | 输出文件路径 | 关键词_爆款数据.html |
--debug | 否 | 调试模式,打印原始API响应 | False |
输出格式
文章数据字段(完整)
每篇文章包含以下字段:
文章基本信息
| 字段名 | 类型 | 说明 |
|---|---|---|
photoId | string | 文章ID(唯一标识) |
title | string | 文章标题(可能为空,需从summary提取) |
summary | string | 文章摘要/正文片段 |
publicTime | string | 发布时间(格式:YYYY-MM-DD HH:MM:SS) |
作者信息
| 字段名 | 类型 | 说明 |
|---|---|---|
accountId | string | 公众号ID(格式:gh_xxxx 或自定义ID) |
userName | string | 公众号名称 |
userHeadUrl | string | 作者头像地址(可能为NULL) |
fans | string | 粉丝数(可能为"100w+"格式) |
作者二维码链接拼接规则:
https://open.weixin.qq.com/qr/code?username={accountId}点击后会弹出公众号二维码,用户可扫码关注。
作品链接:
- 直接使用
oriUrl字段(完整文章链接) - 无备用方案
互动数据
| 字段名 | 类型 | 说明 |
|---|---|---|
likeCount | int/string | 点赞数 |
commentCount | int/string | 评论数 |
shareCount | int/string | 分享数 |
interactiveCount | int/string | 互动总数 |
clicksCount | string | 阅读数(如"10w+") |
watchCount | string | 在看数 |
图片链接
| 字段名 | 类型 | 说明 |
|---|---|---|
coverUrl | string | 封面图URL |
其他字段
| 字段名 | 类型 | 说明 |
|---|---|---|
oriUrl | string | 文章原始链接(完整URL) |
orderNum | int | 排序序号(0=头条,1=次条) |
originalFlag | int | 原创标识(1=原创) |
type | string | 内容类型(如"文摘") |
thumbnail | string | 缩略图URL |
JSON 输出示例
{
"keyword": "职场",
"low_fan_explosive": [
{
"accountId": "gh_e6580d8dcccb",
"clicksCount": "5w+",
"commentCount": "9",
"coverUrl": "https://mmbiz.qpic.cn/mmbiz_jpg/...",
"fans": "100w+",
"interactiveCount": "988",
"likeCount": "124",
"orderNum": 0,
"originalFlag": 1,
"photoId": "8CF6280D97686E92F91445054AF9AAF9",
"publicTime": "2026-03-19 20:06:58",
"shareCount": "834",
"summary": "蓝箭航天的朱雀2..."
}
],
"ten_w_reading": [
{
"accountId": "YJwujian",
"clicksCount": "10w+",
"commentCount": "29",
"coverUrl": "https://mmbiz.qpic.cn/mmbiz_jpg/...",
"fans": "100w+",
"interactiveCount": "4747",
"likeCount": "706",
"orderNum": 0,
"originalFlag": 1,
"photoId": "319359512EA49A0D6774CEBAEDA8E134",
"publicTime": "2026-03-05 22:09:00",
"shareCount": "3854",
"summary": "这下再也不用担心我团战打..."
}
],
"original_rank": [
{
"accountId": "beitaishuoche",
"clicksCount": "9w+",
"commentCount": "27",
"coverUrl": "https://mmbiz.qpic.cn/mmbiz_jpg/...",
"fans": "100w+",
"interactiveCount": "852",
"likeCount": "352",
"orderNum": 0,
"originalFlag": 1,
"photoId": "9D8E75E91E08C147BE9F3F9BF23A691C",
"publicTime": "2026-03-05 17:30:05",
"shareCount": "398",
"summary": "遇到刹车失灵,撞墙会是最安..."
}
]
}HTML 输出格式(卡片形式)
HTML 输出采用响应式卡片布局,结构清晰,便于阅读:
<div class="card">
<div class="card-title-row">
<span class="card-index">1.</span>
<a href="https://mp.weixin.qq.com/s/{photoId}" class="card-title" target="_blank">文章标题</a>
</div>
<div class="card-meta">
<a href="https://open.weixin.qq.com/qr/code?username={accountId}"
class="author-link" target="_blank">公众号名称</a>
<span class="meta-divider">·</span>
<span class="pub-time">发布日期:3月15日</span>
</div>
<div class="card-stats">
<span class="read-count">📖 10w+阅读</span>
<span class="category-tag">低粉高阅读</span>
<a href="https://mp.weixin.qq.com/s/{photoId}" class="view-note-btn" target="_blank">查看作品 ↗</a>
</div>
</div>卡片字段说明
| 字段 | 说明 |
|---|---|
| 序号 | 从1开始编号,格式为"1."、"2."等 |
| 标题 | 文章标题(可点击跳转文章详情) |
| 作者 | 公众号名称(可点击弹出二维码) |
| 发布日期 | 文章发布日期(月日格式) |
| 阅读数 | 文章阅读量 |
| 分类标签 | 低粉高阅读/阅读靠前/原创靠前 |
| 查看作品 | 跳转文章详情的链接 |
三大榜单说明
1. 低粉高阅读(lowPowderExplosiveArticle)
- 定位:小号爆款文章,粉丝数较少但阅读数据优秀
- 价值:小号也能出爆款,参考价值高
- 特点:粉丝数通常在10万以下,阅读数据突出
2. 阅读靠前(tenWReadingRank)
- 定位:阅读量排名靠前的高传播文章
- 价值:高传播力内容,适合学习爆款逻辑
- 特点:阅读量高,传播广度强
3. 原创靠前(originalRank)
- 定位:原创优质内容排名靠前
- 价值:原创保护,内容质量高
- 特点:originalFlag=1,内容原创性强
使用注意事项
数据获取原则
1. 必须调用脚本查询:不能使用其他方式查询或直接搜索网络资讯 2. 必须等待脚本执行完成:获取返回结果后才能进行后续步骤 3. 必须展示完整数据列表:不能跳过或询问用户
数据展示原则
1. 展示所有字段:每篇文章展示完整信息,包括封面图、作者链接、互动数据等 2. 三类爆款内容全部展示:低粉高阅读、阅读靠前、原创靠前
字段说明
1. 标题提取:如果title字段为空,从summary字段提取前30个字符作为标题 2. 作者名称:公众号没有userName字段,使用accountId代替 3. 粉丝数格式:可能是"100w+"、"5.2万"等格式,直接展示原值 4. 阅读数格式:可能是"10w+"、"5w+"等格式,直接展示原值
爆款封面分析报告 HTML 模板
文件说明
本文件为爆款封面分析报告与设计方案的 HTML 模板,技能执行时直接读取本模板填充数据。
文件路径:references/report_template.md
⚠️ 重要:按风格类型分类展示封面,不要逐张输出分析结果!
---
完整HTML模板
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="referrer" content="no-referrer">
<title>爆款封面分析报告 - {关键词}主题</title>
</head>
<body style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;line-height:1.6;color:#333;background:#f5f5f5;padding:20px">
<div style="max-width:1200px;margin:0 auto;background:#fff;border-radius:12px;padding:30px;box-shadow:0 2px 12px rgba(0,0,0,0.08)">
<!-- 报告标题 -->
<h1 style="color:#1a1a1a;margin-bottom:30px;font-size:28px;border-bottom:3px solid #1890ff;padding-bottom:15px">📊 爆款封面分析报告</h1>
<!-- 数据来源信息 -->
<div style="background:#e6f7ff;padding:12px 16px;border-radius:8px;margin-bottom:20px">
<strong>关键词:</strong>{关键词} | <strong>数据来源:</strong>公众号爆款雷达接口 | <strong>分析数量:</strong>{分析数量}张封面
</div>
<!-- ========== 风格类型分类展示区域 ========== -->
{风格类型分类列表}
<!-- ========== 设计方案区域 ========== -->
<hr style="border-top:2px dashed #e8e8e8;margin:40px 0">
<h1 style="color:#1a1a1a;margin-bottom:30px;font-size:28px;border-bottom:3px solid #1890ff;padding-bottom:15px">🎯 爆款封面设计方案</h1>
{设计方案列表}
<!-- ========== 方案选择询问区域 ========== -->
<hr style="border-top:2px dashed #e8e8e8;margin:40px 0">
<div style="background:#fafafa;border-radius:12px;padding:24px;margin:20px 0;border:1px solid #e8e8e8">
<h2 style="margin:0 0 16px;font-size:20px;color:#1890ff">🎯 请选择您想要的封面设计方案</h2>
<div style="font-size:15px;line-height:2;color:#333">
<div style="margin-bottom:8px"><strong>方案一:</strong>{方案一风格名称} - {方案一核心视觉}</div>
<div style="margin-bottom:8px"><strong>方案二:</strong>{方案二风格名称} - {方案二核心视觉}</div>
<div style="margin-bottom:16px"><strong>方案三:</strong>{方案三风格名称} - {方案三核心视觉}</div>
<div style="color:#666">
<strong>💡 请选择:</strong><br>
A. 回复"方案1"、"方案2"或"方案3"直接选择方案<br>
B. 如果您有产品图、人物图或场景图想作为参考,可以和方案编号一起发送<br>
<span style="margin-left:24px">例如:直接发送图片 + "方案1"</span>
</div>
</div>
</div>
</div>
</body>
</html>---
模板填充规范
1. 风格类型分类列表填充格式(核心展示区域)
⚠️ 重要:按风格类型分类展示封面,每个风格类型包含风格描述和代表性封面图
每种风格类型的HTML结构:
<div style="background:#fafafa;border-radius:12px;padding:24px;margin:20px 0;border:1px solid #e8e8e8">
<div style="font-size:20px;font-weight:600;color:#1890ff;margin-bottom:8px">{风格名称}</div>
<span style="display:inline-block;background:#e6f7ff;padding:4px 12px;border-radius:4px;font-size:14px;color:#1890ff;margin-bottom:12px">出现频次:{出现次数}/{总分析数}</span>
<div style="color:#52c41a;font-weight:500;margin:12px 0">核心视觉:{核心视觉描述}</div>
<div style="color:#666;font-size:15px;line-height:1.8;margin-bottom:16px">关键特征:{关键特征描述}</div>
<!-- 该风格的代表性封面图(最多5张,横向排列) -->
<div style="display:flex;flex-wrap:wrap;gap:12px;margin-top:16px">
<a href="{coverUrl}" target="_blank" style="width:180px;height:77px;border-radius:6px;overflow:hidden;display:block">
<img src="{coverUrl}" style="width:100%;height:100%;object-fit:cover;object-position:center" alt="封面示例">
</a>
<!-- 更多封面图... -->
</div>
</div>注意:
- 每个风格类型最多展示5张代表性封面图
- 过滤掉尺寸过小(宽或高<10px)和空白图片
- 封面图容器比例固定为2.35:1
2. 设计方案列表填充格式
每个方案的HTML结构:
<!-- 方案{N} -->
<div style="background:#fafafa;border-radius:12px;padding:24px;margin:25px 0;border:2px solid #1890ff">
<h2 style="font-size:20px;font-weight:600;color:#1890ff;margin-bottom:12px">方案{N}:{风格名称}</h2>
<div style="color:#52c41a;font-weight:500;margin:10px 0;font-size:16px">核心视觉:{核心视觉描述}</div>
<h3 style="color:#333;margin:20px 0 15px;font-size:18px">案例参考</h3>
<div style="background:#fff;border:1px solid #e8e8e8;border-radius:8px;padding:20px;margin:15px 0;display:flex;gap:20px;align-items:flex-start">
<a href="{coverUrl}" target="_blank" style="width:300px;height:128px;border-radius:8px;overflow:hidden;box-shadow:0 2px 8px rgba(0,0,0,0.1);display:block;flex-shrink:0">
<img src="{coverUrl}" style="width:100%;height:100%;object-fit:cover;object-position:center;display:block" alt="封面图">
</a>
<div style="flex:1">
<div style="font-size:18px;font-weight:500;margin-bottom:10px">
<a href="{oriUrl}" target="_blank" style="color:#1890ff;text-decoration:none;font-weight:500">{标题}</a>
</div>
<div style="color:#666;font-size:14px;margin:8px 0">作者:{作者名}</div>
<span style="display:inline-block;background:#fff7e6;color:#fa8c16;padding:4px 12px;border-radius:4px;font-size:13px;font-weight:500">阅读:{阅读数}</span>
</div>
</div>
<h3 style="color:#333;margin:20px 0 15px;font-size:18px">生图提示词</h3>
<div style="background:#f6ffed;border:1px solid #b7eb8f;border-radius:8px;padding:16px;margin:20px 0">
<div style="color:#52c41a;font-weight:600;margin-bottom:8px">公众号封面图</div>
<div style="color:#333;font-size:14px;line-height:1.8;background:#fff;padding:12px;border-radius:4px;word-break:break-all">
2.35:1横版比例(900x383像素)。参考封面:{coverUrl}。{风格描述}。
</div>
</div>
</div>---
字段说明
| 占位符 | 说明 | 数据来源 |
|---|---|---|
{关键词} | 用户输入的主题关键词 | 用户输入 |
{分析数量} | 实际分析的封面图数量 | 接口返回数据(过滤后) |
{风格类型分类列表} | 按风格类型分类的封面展示HTML | 分析归类后生成 |
{风格名称} | 风格类型名称 | 分析归类 |
{出现次数} | 该风格出现的次数 | 统计 |
{总分析数} | 总分析封面数量 | 统计 |
{核心视觉描述} | 该风格的核心视觉特征 | 分析总结 |
{关键特征描述} | 该风格的关键特征 | 分析总结 |
{设计方案列表} | 3个设计方案的HTML | 分析后生成 |
{方案一风格名称} | 方案一的风格名称 | 分析总结 |
{方案一核心视觉} | 方案一的核心视觉描述 | 分析总结 |
{方案二风格名称} | 方案二的风格名称 | 分析总结 |
{方案二核心视觉} | 方案二的核心视觉描述 | 分析总结 |
{方案三风格名称} | 方案三的风格名称 | 分析总结 |
{方案三核心视觉} | 方案三的核心视觉描述 | 分析总结 |
{coverUrl} | 封面图URL | 接口返回的 coverUrl 字段 |
{oriUrl} | 原文链接URL | 接口返回的 oriUrl 字段 |
{标题} | 文章标题 | 接口返回的 title 字段 |
{作者名} | 作者名称 | 接口返回的 userName 字段 |
{阅读数} | 阅读量 | 接口返回的 clicksCount 字段 |
---
样式规范
| 元素 | 样式规则 |
|---|---|
| 封面图容器比例 | 2.35:1 (180x77px 或 300x128px) |
| 封面图适配 | object-fit: cover, object-position: center |
| 内联样式 | 所有样式必须内联,禁止使用class |
| 禁止hover | 不添加任何hover效果 |
| 防盗链 | 必须包含 meta referrer 标签 |
---
输出文件命名
生成HTML报告时,文件名格式:
爆款封面分析报告_{关键词}.html保存路径:当前工作目录(使用相对路径 ./)
#!/usr/bin/env python3
"""
公众号爆款封面数据查询脚本
"""
import os
import sys
import argparse
import json
import requests
def fetch_wx_covers(keyword: str, debug: bool = False, max_retries: int = 3, start_date: str = None):
"""
调用接口获取公众号爆款封面数据
Args:
keyword: 搜索关键词(多个关键词用逗号分隔)
debug: 是否打印调试信息
max_retries: 最大重试次数
start_date: 开始日期,格式 yyyy-MM-dd
Returns:
dict: 包含3类爆款数据
Raises:
Exception: 当API调用失败时抛出异常
"""
# 从环境变量获取 API Key
api_key = os.getenv("REDFOX_API_KEY")
if not api_key:
raise ValueError("缺少 API Key 配置,请设置环境变量 REDFOX_API_KEY。获取方式:前往 https://redfox.hk/settings/api-keys?source=github 申请,然后执行 export REDFOX_API_KEY=\"ak_xxxx...\"")
url = "https://redfox.hk/story/api/cozeSkill/getWxCozeSkillData"
params = {
"keyword": keyword,
"source": "公众号爆款封面生成-GitHub"
}
# 添加开始日期参数
if start_date:
params["startDate"] = start_date
headers = {
"X-API-KEY": api_key,
"Content-Type": "application/json",
"Accept": "application/json",
}
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}", file=sys.stderr)
response = requests.get(url, params=params, headers=headers, timeout=30)
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}, {response.text[:200]}")
data = response.json()
if "data" not in data:
error_msg = data.get("msg", "未知错误")
raise Exception(f"API 错误: {error_msg}")
result_data = data.get("data", {})
if debug:
print("=== DEBUG: API 返回的 data 字段键 ===", file=sys.stderr)
print(json.dumps(list(result_data.keys()), ensure_ascii=False, indent=2), file=sys.stderr)
return {
"keyword": keyword,
"low_fan_explosive": result_data.get("lowPowderExplosiveArticle", []),
"ten_w_reading": result_data.get("tenWReadingRank", []),
"original_rank": result_data.get("originalRank", [])
}
except requests.exceptions.RequestException as e:
last_error = f"请求失败: {str(e)}"
if debug:
print(f" 错误: {type(e).__name__}: {str(e)[:100]}", file=sys.stderr)
import time
if attempt < max_retries - 1:
time.sleep(2 ** attempt)
continue
except Exception as e:
last_error = str(e)
if debug:
print(f" 错误: {type(e).__name__}: {str(e)[:100]}", file=sys.stderr)
import time
if attempt < max_retries - 1:
time.sleep(2 ** attempt)
continue
raise Exception(f"{last_error}(已尝试 {max_retries} 次)")
def get_cover_urls(data, max_per_category=5):
"""提取所有封面图URL"""
urls = []
categories = [
('low_fan_explosive', '低粉爆文榜'),
('ten_w_reading', '10w+阅读榜'),
('original_rank', '原创榜')
]
for key, name in categories:
items = data.get(key, [])[:max_per_category]
for item in items:
cover_url = item.get('coverUrl', '')
photo_id = item.get('photoId', '')
title = item.get('title', '')[:20]
if cover_url and photo_id:
urls.append({
'category': name,
'title': title,
'photo_id': photo_id,
'cover_url': cover_url,
'link': f"https://mp.weixin.qq.com/s/{photo_id}"
})
return urls
def format_output(data: dict, max_items: int = None, start_date: str = None):
"""
格式化输出爆款数据(表格形式)
Args:
data: 原始数据
max_items: 每类爆款数据最多展示数量,None 表示展示所有数据
start_date: 开始日期,格式 yyyy-MM-dd,用于计算统计时间范围
"""
from datetime import datetime, timedelta
# 计算统计时间范围
def get_time_range(start_date):
if start_date:
try:
start = datetime.strptime(start_date, '%Y-%m-%d')
end = datetime.now()
days = (end - start).days
if days <= 1:
return "近1天"
elif days <= 7:
return f"近{days}天"
else:
return f"近{days}天"
except:
return "近30天"
return "近30天"
time_range = get_time_range(start_date)
def process_title(item):
"""处理标题:转义特殊字符,空标题使用summary替代"""
title = item.get('title', '')
# 如果标题为空,尝试使用 summary 字段
if not title or title.strip() == '':
summary = item.get('summary', '')
if summary:
# 移除 summary 中的换行符并截取前30个字符
title = summary.replace('\n', ' ').replace('\r', ' ').strip()[:30]
if len(summary) > 30:
title = title + '...'
if not title or title.strip() == '':
title = '无标题'
# 转义 Markdown 表格特殊字符(|)
title = title.replace('|', '\\|')
# 移除换行符
title = title.replace('\n', ' ').replace('\r', ' ')
# 移除多余空格
title = ' '.join(title.split())
# 截断过长标题
if len(title) > 30:
title = title[:30] + "..."
return title
def format_time(item):
"""格式化发布时间为 X月X日"""
pub_time = item.get('publicTime', '')
if pub_time:
# publicTime 格式: "2026-03-06 13:03:56"
try:
month = int(pub_time[5:7])
day = int(pub_time[8:10])
return f"{month}月{day}日"
except:
pass
return '--'
def get_latest_date(data):
"""获取数据中最新的发布日期"""
all_items = []
for key in ['low_fan_explosive', 'ten_w_reading', 'original_rank']:
all_items.extend(data.get(key, []))
latest_date = None
for item in all_items:
pub_time = item.get('publicTime', '')
if pub_time:
try:
date_str = pub_time[:10] # 取 "YYYY-MM-DD" 部分
if latest_date is None or date_str > latest_date:
latest_date = date_str
except:
pass
return latest_date
output = []
# 检查数据日期
latest_date = get_latest_date(data)
# 按 photoId 去重(API 返回数据可能有重复)
def dedup_items(items):
seen = set()
result = []
for item in items:
photo_id = item.get('photoId', '')
if photo_id and photo_id not in seen:
seen.add(photo_id)
result.append(item)
return result
# 检查是否有任何数据
low_fan_items = dedup_items(data.get("low_fan_explosive", []))
ten_w_items = dedup_items(data.get("ten_w_reading", []))
original_items = dedup_items(data.get("original_rank", []))
total_count = len(low_fan_items) + len(ten_w_items) + len(original_items)
# 如果所有类型都没有数据,输出友好提示
if total_count == 0:
keyword = data.get("keyword", "")
output.append(f"# 公众号爆款数据分析报告\n\n**关键词**:{keyword}\n\n")
output.append("---\n\n")
output.append("## 暂无相关爆款数据\n\n")
output.append(f"很抱歉,当前关键词 **「{keyword}」** 尚未有足够的爆款文章数据。\n\n")
output.append("### 可能原因\n\n")
output.append("- 该关键词相对小众或新兴,爆款内容积累较少\n")
output.append("- 近期该赛道热度较低,暂无突出爆款文章\n")
output.append("- 关键词表述方式可以更加具体或热门\n\n")
output.append("### 建议操作\n\n")
output.append("- 更换为更热门的关键词,如:**\"职场成长\"**、**\"美食\"**、**\"情感故事\"** 等\n")
output.append("- 尝试更细分的长尾关键词\n")
output.append("- 输入其他感兴趣的领域或赛道进行追踪\n\n")
output.append("---\n\n")
output.append("*数据来源:公众号爆款雷达,每日更新最新热门内容*\n")
return "\n".join(output)
# 1. 低粉爆文榜
items = low_fan_items
if max_items is not None:
items = items[:max_items]
output.append(f"\n### - **低粉爆文榜**(粉丝量较少的账号中爆款文章)")
output.append("\n")
if not items:
output.append("(无数据)\n")
else:
output.append("| 封面 | 序号 | 发布时间 | 标题 | 作者 | 阅读数 | 点赞数 | 在看数 |")
output.append("|------|------|----------|------|------|--------|--------|--------|")
for idx, item in enumerate(items, 1):
user_name = item.get('userName', '未知')
fans = item.get('fans', '未知')
# 封面缩略图
cover_url = item.get('coverUrl', '')
if cover_url:
cover_str = f""
else:
cover_str = "--"
# 作者信息
author_str = f"{user_name}(粉丝:{fans})"
# 标题添加链接
title = process_title(item)
ori_url = item.get('oriUrl', '')
if ori_url:
title_with_link = f"[{title}]({ori_url})"
else:
title_with_link = title
pub_time = format_time(item)
# 获取互动数据(字符串类型)
clicks = item.get('clicksCount', '--')
likes = item.get('likeCount', '--')
watches = item.get('watchCount', '--')
output.append(f"| {cover_str} | {idx} | {pub_time} | {title_with_link} | {author_str} | {clicks} | {likes} | {watches} |")
# 2. 10w+阅读榜
items = ten_w_items
if max_items is not None:
items = items[:max_items]
output.append(f"\n### - **10w+阅读榜**(阅读量超过10万的爆款文章)")
output.append("\n")
if not items:
output.append("(无数据)\n")
else:
output.append("| 封面 | 序号 | 发布时间 | 标题 | 作者 | 阅读数 | 点赞数 | 在看数 |")
output.append("|------|------|----------|------|------|--------|--------|--------|")
for idx, item in enumerate(items, 1):
user_name = item.get('userName', '未知')
fans = item.get('fans', '未知')
# 封面缩略图
cover_url = item.get('coverUrl', '')
if cover_url:
cover_str = f""
else:
cover_str = "--"
# 作者信息
author_str = f"{user_name}(粉丝:{fans})"
# 标题添加链接
title = process_title(item)
ori_url = item.get('oriUrl', '')
if ori_url:
title_with_link = f"[{title}]({ori_url})"
else:
title_with_link = title
pub_time = format_time(item)
# 获取互动数据(字符串类型)
clicks = item.get('clicksCount', '--')
likes = item.get('likeCount', '--')
watches = item.get('watchCount', '--')
output.append(f"| {cover_str} | {idx} | {pub_time} | {title_with_link} | {author_str} | {clicks} | {likes} | {watches} |")
# 3. 原创榜
items = original_items
if max_items is not None:
items = items[:max_items]
output.append(f"\n### - **原创榜**(优质原创爆款文章)")
output.append("\n")
if not items:
output.append("(无数据)\n")
else:
output.append("| 封面 | 序号 | 发布时间 | 标题 | 作者 | 阅读数 | 点赞数 | 在看数 |")
output.append("|------|------|----------|------|------|--------|--------|--------|")
for idx, item in enumerate(items, 1):
user_name = item.get('userName', '未知')
fans = item.get('fans', '未知')
# 封面缩略图
cover_url = item.get('coverUrl', '')
if cover_url:
cover_str = f""
else:
cover_str = "--"
# 作者信息
author_str = f"{user_name}(粉丝:{fans})"
# 标题添加链接
title = process_title(item)
ori_url = item.get('oriUrl', '')
if ori_url:
title_with_link = f"[{title}]({ori_url})"
else:
title_with_link = title
pub_time = format_time(item)
# 获取互动数据(字符串类型)
clicks = item.get('clicksCount', '--')
likes = item.get('likeCount', '--')
watches = item.get('watchCount', '--')
output.append(f"| {cover_str} | {idx} | {pub_time} | {title_with_link} | {author_str} | {clicks} | {likes} | {watches} |")
return "\n".join(output)
def main():
"""主函数"""
parser = argparse.ArgumentParser(description='公众号爆款封面数据查询工具')
parser.add_argument('--keyword', required=True, help='搜索关键词')
parser.add_argument('--max-items', type=int, default=10,
help='每类爆款内容最多展示数量(默认10条)')
parser.add_argument('--output-format', choices=['text', 'json', 'markdown'],
default='json', help='输出格式:text(文本表格)、json(JSON格式,默认)或 markdown(Markdown格式)')
parser.add_argument('--output-file', type=str, default=None,
help='输出文件路径')
parser.add_argument('--start-date', type=str, default=None,
help='开始日期,格式 yyyy-MM-dd(默认最近30天)')
parser.add_argument('--debug', action='store_true', help='启用调试模式')
parser.add_argument('--max-retries', type=int, default=3,
help='最大重试次数(默认3次)')
args = parser.parse_args()
try:
data = fetch_wx_covers(args.keyword, debug=args.debug, max_retries=args.max_retries, start_date=args.start_date)
# 生成输出内容
if args.output_format == 'json':
output_content = json.dumps(data, ensure_ascii=False, indent=2)
elif args.output_format == 'markdown':
# Markdown 格式添加标题
markdown_header = f"# 公众号爆款数据分析报告\n\n**关键词**:{args.keyword}\n\n"
output_content = markdown_header + format_output(data, max_items=args.max_items, start_date=args.start_date)
else:
output_content = format_output(data, max_items=args.max_items, start_date=args.start_date)
# 确定输出文件路径(默认不输出文件,只输出到控制台)
output_file = args.output_file
# 输出到文件或控制台
if output_file:
with open(output_file, 'w', encoding='utf-8') as f:
f.write(output_content)
print(f"✓ 结果已保存到: {output_file}", file=sys.stderr)
print(f"✓ 关键词: {args.keyword}", file=sys.stderr)
# 统计数据
total_items = (
len(data.get('low_fan_explosive', [])) +
len(data.get('ten_w_reading', [])) +
len(data.get('original_rank', []))
)
print(f"✓ 总计: {total_items} 条数据", file=sys.stderr)
# 显示每类数据量
print(f" - 低粉爆文榜: {len(data.get('low_fan_explosive', []))} 条", file=sys.stderr)
print(f" - 10w+阅读榜: {len(data.get('ten_w_reading', []))} 条", file=sys.stderr)
print(f" - 原创榜: {len(data.get('original_rank', []))} 条", file=sys.stderr)
# 输出封面图URL供后续分析
cover_urls = get_cover_urls(data, max_per_category=3)
if cover_urls:
print(f"\n=== 封面图URL(用于风格分析)===", file=sys.stderr)
for i, item in enumerate(cover_urls, 1):
print(f"{i}. [{item['category']}] {item['title']}: {item['cover_url']}", file=sys.stderr)
else:
print(output_content)
# 统计数据输出到 stderr
print(f"\n✓ 关键词: {args.keyword}", file=sys.stderr)
except Exception as e:
print(f"❌ 错误: {str(e)}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()