
Douyin Similar Account
- 225 installs
- 316 repo stars
- Updated August 4, 2026
- redfox-data/redfox-community
Takes a Douyin account name or ID and returns its data plus similar and top benchmark accounts, with analysis of commonalities, differences, and optimization advice.
About
A Douyin competitor-matching tool that recommends benchmark and top accounts for a given account using the Redfox index. A creator uses it to find accounts to model, identify competitors, or plan account strategy.
- Recommends 5 nearest-index peers plus top-5 accounts in the same category
- Deep analysis of commonalities, differences, and optimization advice
Douyin Similar Account by the numbers
- 225 all-time installs (skills.sh)
- +15 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #935 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 douyin-similar-accountAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 225 |
|---|---|
| repo stars | ★ 316 |
| Last updated | August 4, 2026 |
| Repository | redfox-data/redfox-community ↗ |
What it does
Takes a Douyin account name or ID and returns its data plus similar and top benchmark accounts, with analysis of commonalities, differences, and optimization advice.
Files
抖音相似账号推荐
简介
抖音相似账号推荐是一款专为抖音创作者设计的智能对标匹配工具,帮助用户快速找到可参考的对标账号和可追赶的头部标杆。
通过简单的名称或ID输入,你可以:
- 📊 查询账号基本信息 + 红狐指数 + 近期作品数据
- 🎯 匹配对标账号(红狐指数向上最近最近5个账号,可直接复制玩法)
- 🚀 推荐头部账号(同分类红狐指数Top5,模式成熟可追赶)
- 🔍 深度分析共通点、差异点和优化建议
适用于抖音创作者、内容运营、账号投放决策等需要对标参考的场景。基于 红狐Hub 数据平台提供支持。
功能特性
🎯 核心功能
- 🔍 智能查询:支持按抖音昵称、抖音号两种方式查询(自动识别昵称和抖音号)
- 📊 账号数据:展示查询账号的基本信息、红狐指数、播放数据及近期作品
- 🎯 对标账号:推荐红狐指数向上最近的5个同赛道账号,可直接复制运营玩法
- 🚀 头部账号:推荐同分类红狐指数倒序前5的成熟账号,模式可参考追赶
- 🔍 深度分析:总结共通点、差异点,提供可落地的优化建议
- 📬 订阅推送:查询结果末尾支持订阅相似账号最新信息推送,可自定义推送频率和时间
✨ 特色亮点
- 📈 红狐指数:每个对标/头部账号均展示红狐指数和指数差距,量化对标差距
- 💡 推荐理由:每个对标账号附带多维度推荐理由,涵盖红狐指数对比、爆品标题引用、更新节奏、互动率等
- 📊 表格列顺序:账号名称 | 粉丝数 | 总获赞 | 近7天互动 | 红狐指数 | 指数差距 | 推荐理由
- 📱 多输入方式:名称/ID灵活查询,昵称自动识别
一键安装
前置条件
- Python 3.x 运行环境
- RedFox API Key(前往 红狐Hub 官网 注册获取,新用户赠送免费积分)
获取 API Key
1. 访问 红狐Hub 官网 了解服务详情 2. 前往 注册页面 注册账号 3. 新注册用户将获赠免费积分,可立即开始使用 API 服务 4. 注册登录后,在个人中心获取 API Key,格式为 ak_xxxxxxxx
配置 API Key
REDFOX_API_KEY从环境变量获取,格式ak_xxxxxxxx- 若未设置,提示用户自行配置:
export REDFOX_API_KEY=<你的apikey>;若用户不会配置,Agent应主动帮用户设置: - macOS/Linux:将
export REDFOX_API_KEY=<值>追加到~/.zshrc(zsh)或~/.bashrc(bash),然后source对应文件使其全局生效 - Windows:使用
[Environment]::SetEnvironmentVariable("REDFOX_API_KEY", "<值>", "User")设置用户级永久环境变量(需重启终端生效) - 配置完成后应验证:
echo $REDFOX_API_KEY(macOS/Linux)或echo %REDFOX_API_KEY%(Windows),确保换一个skill也能读取到
环境变量配置
| 变量名 | 必填 | 说明 |
|---|---|---|
REDFOX_API_KEY | 是 | RedFox API 访问密钥,格式 ak_xxxxxxxx |
使用指南
基础使用
按抖音名称/号查询
告诉助手你想查询的抖音账号(支持昵称和抖音号):
用户:帮我查"一乐店长"的相似抖音账号
>
助手:调用脚本 python scripts/douyin_similar_account.py --account_id "一乐店长",将脚本输出原样完整展示,禁止摘要、改写、增减或添加额外评论用户:查抖音号geng970616的相似账号
>
助手:调用脚本 python scripts/douyin_similar_account.py --account_id "geng970616",将脚本输出原样完整展示,禁止摘要、改写、增减或添加额外评论命令速查
| 命令 | 功能 |
|---|---|
--account_id "昵称或抖音号" | 按抖音账号昵称或抖音号查询(自动识别) |
--account_id "抖音号" --sync | 触发账号数据收录(账号未找到时,用户确认收录后使用) |
输出流程
详细的核心工作流程(操作步骤、输出模板、API接口详情、字段映射、对标匹配规则、推荐理由生成维度、输出格式规范等)请参考 references/core_workflow.md。
使用场景
场景一:新号起号参考
角色:抖音新手运营
需求:刚创建抖音号,不知道怎么定位和选题
使用方式: 1. 查询自己账号的对标推荐 2. 查看对标账号的内容方向和更新节奏 3. 复制对标账号的运营策略
预期收益:快速找到可复制的运营模式,降低起号试错成本
---
场景二:内容选题优化
角色:抖音内容运营
需求:内容遇到瓶颈,需要参考同赛道优秀账号的选题方向
使用方式: 1. 查询自己账号的相似推荐 2. 分析头部标杆的爆品特征和内容风格 3. 调整自身选题策略
预期收益:突破内容瓶颈,提升播放量和互动数据
---
场景三:账号投放决策
角色:品牌营销经理
需求:选择合适的抖音号进行广告投放
使用方式: 1. 查询目标赛道头部账号 2. 对比对标和头部账号的数据表现 3. 评估互动率和粉丝画像匹配度
预期收益:精准选择投放账号,提高投放ROI
---
场景四:竞品分析
角色:MCN 运营人员
需求:了解竞品账号的运营策略和数据表现
使用方式: 1. 查询竞品账号的相似推荐 2. 深度分析共通点和差异 3. 发现市场空白机会
预期收益:掌握竞品动态,发现差异化竞争机会
项目架构
目录结构
抖音相似账号推荐/
├── scripts/
│ └── douyin_similar_account.py # 核心脚本:调用API查询对标账号并格式化输出
├── references/
│ └── core_workflow.md # 核心工作流程:操作步骤、输出模板、API接口详情、字段映射、推荐理由生成维度
└── SKILL.md # 技能描述文件技术栈
| 组件 | 说明 |
|---|---|
| 运行环境 | Python 3.x |
| 依赖 | Python 标准库(json、argparse、os、time、urllib、platform、re) |
| 数据源 | RedFox API(https://redfox.hk/) |
| API 接口 | POST /story/api/dyUser/querySimilarAccounts(查询账号信息+对标账号+头部账号) |
常见问答
安装相关问题
Q1: 提示 "未找到 REDFOX_API_KEY 配置" 怎么办?
A: 请按以下步骤配置: 1. 访问 https://redfox.hk/ 注册账号并获取 API Key 2. Windows 用户在 PowerShell 执行:[Environment]::SetEnvironmentVariable("REDFOX_API_KEY", "<你的API Key>", "User") 3. macOS/Linux 用户执行:echo 'export REDFOX_API_KEY=<你的API Key>' >> ~/.zshrc 然后 source ~/.zshrc 4. 重启终端后生效
Q2: 需要安装额外的 Python 依赖吗?
A: 不需要。脚本仅使用 Python 标准库(json、argparse、os、urllib、re 等),无需 pip install 任何包。
---
使用相关问题
Q3: 查询不到账号数据怎么办?
A: 当查询不到账号时,系统会提示进行账号收录。回复抖音号(在抖音个人主页显示的ID),即可触发账号收录,30分钟后将自动推送相似账号报告。如暂不需要可下次再说。
可能原因:1) 该账号暂未被平台完整收录;2) 输入的抖音号或名称不准确。
Q4: 支持哪些查询方式?
A: 支持两种输入方式,脚本自动识别:
- 按昵称:
--account_id "一乐店长"(含中文自动用accountName查询) - 按抖音号/uid:
--account_id "geng970616"(非中文自动用accountId查询)
Q5: 对标账号和头部账号有什么区别?
A: 对标账号是红狐指数向上最近的5个账号,指数接近可直接复制玩法;头部账号是同分类红狐指数倒序前5,运营模式更成熟,适合追赶学习。
Q6: 红狐指数是什么?
A: 红狐指数是RedFox平台基于账号多维度数据(粉丝量、互动量、内容质量等)综合计算的评估指标,数值越高代表账号综合表现越好。对标账号推荐以此为核心排序依据。
Q7: 查询结果中的订阅推送是什么?
A: 每次查询结果末尾会提示是否订阅该账号的相似账号最新信息推送。选择订阅后,每日下午19点会推送最新数据,也可自行选择推送频率和时间。暂不需要则可选择"暂不需要"。
---
故障排除
Q8: API 请求返回 HTTP 错误怎么办?
A: 请检查以下几点: 1. 确认 API Key 是否正确且未过期 2. 确认网络可以正常访问 https://redfox.hk/ 3. 检查 API Key 是否有足够的积分余额
Q9: 输出结果中某些字段为空或为0?
A: 这是正常现象,说明该账号在对应数据维度上暂无数据记录。脚本会自动处理为"暂无"或"0"展示。
---
获取帮助
如有其他问题,可通过以下方式获取帮助:
- 📧 访问 红狐Hub 官网 了解更多
Douyin Similar Account Recommender / douyin-similar-account
---
Overview
A benchmark account matching tool for Douyin creators. Using the RedFox Index, it intelligently recommends benchmark accounts and top-tier accounts, providing deep analysis of commonalities, differences, and optimization suggestions—helping creators pinpoint their niche, replicate proven strategies, and plan growth trajectories.
Core Value
- Dual-group smart recommendations: Delivers both "Benchmark Accounts" (5 closest above your RedFox Index—directly copy their playbooks) and "Top Accounts" (Top 5 by RedFox Index in the same category—mature models to chase).
- RedFox Index gap quantification: Every benchmark/top account displays its RedFox Index and the index gap, making the distance clear at a glance.
- Deep analysis report: Automatically summarizes commonalities, difference analysis, and provides actionable optimization suggestions.
- Subscription push: Subscribe to similar account update notifications, pushed daily at 19:00, with customizable frequency and time.
Intended Users
- 📝 Douyin creators — Find benchmark accounts in your niche to learn content strategies and operational tactics.
- 🛍️ Brand / ad operators — Screen high-match Douyin accounts for ad placement and business collaborations.
- 🏢 MCN / content teams — Analyze niche landscapes at scale and plan differentiated directions for matrix accounts.
- 🌱 New account launchers — Reference benchmark account growth paths to reduce launch trial-and-error costs.
---
Features
Core Capabilities
- Smart query: Search by Douyin nickname or Douyin ID—automatically identifies the input type.
- Account data display: Show basic account info, RedFox Index, follower count, view data, and recent works for the queried account.
- Benchmark account recommendations: Recommend the 5 closest same-niche accounts with higher RedFox Index—directly copy their operational playbooks.
- Top account recommendations: Recommend the Top 5 accounts by RedFox Index in the same category—mature models to reference and chase.
- Deep analysis: Automatically summarize commonalities and differences, providing actionable optimization suggestions.
- Subscription push: At the end of each query result, support subscribing to similar account update notifications with customizable frequency and time.
Highlights
- RedFox Index quantification: Every account displays its RedFox Index and index gap, quantifying the benchmarking distance.
- Multi-dimension recommendation reasons: Covering content theme focus, viral work title quotes, publishing cadence, engagement rate, follower scale, and more.
- Self-account pinned first: The benchmark table's first row is your own account (bold), enabling intuitive comparison.
- Multi-input flexibility: Flexible queries by nickname or Douyin ID, with automatic Chinese-input detection.
---
API Key Acquisition & Security
- This skill requires the environment variable:
REDFOX_API_KEY. REDFOX_API_KEYis issued by RedFoxHub (https://redfox.hk)- Register at RedFoxHub to obtain
REDFOX_API_KEY. - Configure
REDFOX_API_KEYon your device before using this skill. - Before providing your key, confirm its source, scope, validity period, and whether it can be reset or revoked.
- Do not hard-code or expose keys in plain text in code, prompts, logs, or output files.
---
Usage Guide
Simply describe your query needs in natural language—no commands to memorize.
Quick Reference
| Intent | Example phrase | Result |
|---|---|---|
| Search by nickname | "Find similar Douyin accounts for 一乐店长" | Automatic nickname match, outputting both benchmark and top account recommendations |
| Search by Douyin ID | "Find similar accounts for Douyin ID geng970616" | Precise ID-based query |
| Competitor benchmarking | "Analyze competitor accounts in my niche for me" | Output deep analysis report: commonalities, differences, and optimization suggestions |
Output Example
After querying, you will receive the following structured analysis:
Account Basic Info: Nickname, Douyin ID, followers, total likes, RedFox Index, past-7-day metrics, and recent works
✨ Benchmark Accounts (5 closest above your RedFox Index): Your account pinned first in bold for intuitive comparison
| Account | Followers | Total Likes | 7-Day Engagement | RedFox Index | Index Gap | Recommendation Reason | | … | … | … | … | … | … | Multi-dimension analysis: content focus, viral quotes, cadence, engagement rate, etc. |
✨ Top Accounts (Top 5 by RedFox Index in same category): Mature models to pursue
📊 Deep Analysis: Commonalities + Difference Analysis + Optimization Suggestions
---
(When no data is found, submit the Douyin ID for data indexing; a diagnostic report will be auto-pushed in about 30 minutes.)
---
Use Cases
| Scenario | Role | Example question | Benefit |
|---|---|---|---|
| New account launch reference | New Douyin operator | "I just started a Douyin account—find me peer benchmarks at a similar stage" | Quickly find copyable operational models; lower launch trial-and-error costs |
| Content topic optimization | Douyin content operator | "My account traffic has been low lately—show me how top accounts in my niche are doing" | Analyze top benchmark viral patterns to break through content bottlenecks |
| Ad placement selection | Brand marketing manager | "Find food-niche Douyin accounts suitable for ad placement" | Precisely select placement accounts; improve ad ROI |
| Competitive analysis | MCN operations staff | "Analyze the food-niche Douyin competitive landscape for me" | Stay on top of competitor dynamics; discover differentiated opportunities |
---
Important Data Notes
- Data is sourced from the RedFox data platform; the displayed data retrieval time may differ from real-time figures.
- The RedFox Index is updated weekly; if no works were published during the statistical period, the index may be 0.
- Engagement rates exceeding 100% are flagged as data anomalies and will not be output.
- Recommendation reasons follow an 8-level dimension standard; when the queried account's RedFox Index is 0, a "Learning Points Summary" mode is used instead.
- When an account cannot be found, submit the Douyin ID for data indexing; a diagnostic report will be auto-pushed in about 30 minutes.
---
抖音相似账号推荐 / douyin-similar-account
---
简介
抖音创作者对标账号匹配工具,基于红狐指数智能推荐对标账号和头部账号,深度分析共通点、差异点和优化建议,帮助创作者精准定位赛道、复制成功打法、规划增长路径。
核心价值
- 双组智能推荐:同时输出「对标账号」(红狐指数向上最近的 5 个,可直接复制玩法)和「头部账号」(同分类红狐指数 Top5,模式成熟可追赶)两组推荐。
- 红狐指数量化差距:每个对标/头部账号均展示红狐指数和指数差距,对标差距一目了然。
- 深度分析报告:自动总结共通点、差异分析,并提供可落地的优化建议。
- 订阅推送:支持订阅相似账号最新信息推送,每日下午 19 点更新,可自定义频率和时间。
适用对象
- 📝 抖音创作者 — 找到同赛道对标账号,借鉴内容策略与运营打法。
- 🛍️ 品牌 / 投放运营 — 筛选高匹配度抖音号进行投放与商务合作。
- 🏢 MCN / 内容团队 — 批量分析赛道格局,为矩阵账号规划差异化方向。
- 🌱 新号起号者 — 参考对标账号的成长路径,降低起号试错成本。
---
功能特性
核心功能
- 智能查询:支持按抖音昵称、抖音号两种方式查询,自动识别昵称和抖音号。
- 账号数据展示:展示查询账号的基本信息、红狐指数、粉丝数、播放数据及近期作品。
- 对标账号推荐:推荐红狐指数向上最近的 5 个同赛道账号,可直接复制运营玩法。
- 头部账号推荐:推荐同分类红狐指数 Top5 的成熟账号,模式可参考追赶。
- 深度分析:自动总结共通点和差异,提供可落地的优化建议。
- 订阅推送:查询结果末尾支持订阅相似账号最新信息推送,可自定义频率和时间。
特色亮点
- 红狐指数量化:每个账号均展示红狐指数和指数差距,量化对标距离。
- 多维度推荐理由:涵盖内容主题聚焦、爆品标题引用、更新节奏、互动率、粉丝量级等维度。
- 本账号置首行:对标账号表格第一行为本账号(加粗),直观对比差异。
- 多输入方式:昵称和抖音号灵活查询,自动识别含中文输入。
---
密钥获取与安全说明
- 本技能需要使用环境变量:
REDFOX_API_KEY。 REDFOX_API_KEY由 红狐 hub (https://redfox.hk)提供。- 请前往 红狐 hub 注册账号,获取
REDFOX_API_KEY。 - 配置设备环境变量
REDFOX_API_KEY后使用本技能。 - 在提供密钥前,请先确认密钥来源、可用范围、有效期及是否支持重置/撤销。
- 禁止在代码、提示词、日志或输出文件中硬编码/明文暴露密钥。
---
使用指南
直接用自然语言描述查询需求,无需记忆命令。
常用说法速查
| 意图 | 示例话术 | 效果 |
|---|---|---|
| 按昵称查询 | 「帮我查一乐店长的相似抖音账号」 | 按昵称自动匹配,输出对标和头部两组推荐 |
| 按抖音号查询 | 「查抖音号 geng970616 的相似账号」 | 按抖音号精准查询 |
| 找竞品对标 | 「帮我分析一下同赛道竞品账号」 | 输出深度分析报告,含共通点、差异和优化建议 |
输出示例
完成查询后,你将收到以下结构化的分析结果:
查询账号基本信息:昵称、抖音号、粉丝数、总获赞、红狐指数、近 7 天数据及近期作品列表
✨ 对标账号(红狐指数向上最近 5 个):本账号置首行加粗,直观对比
| 账号名称 | 粉丝数 | 总获赞 | 近 7 天互动 | 红狐指数 | 指数差距 | 推荐理由 | | … | … | … | … | … | … | 多维度分析:内容聚焦、爆品引用、更新节奏、互动率等 |
✨ 头部账号(同分类红狐指数 Top5):模式成熟可追赶
📊 深度分析:共通点 + 差异分析 + 优化建议
---
(查询不到数据时,支持提交抖音号进行数据收录,30 分钟后自动推送诊断报告。)
---
使用场景
| 场景 | 角色 | 示例问法 | 收益 |
|---|---|---|---|
| 新号起号参考 | 抖音新手运营 | 「我刚做抖音号,帮我找同阶段的对标账号」 | 快速找到可复制的运营模式,降低起号试错成本 |
| 内容选题优化 | 抖音内容运营 | 「我的号最近流量低迷,帮我看看同赛道头部账号怎么做」 | 分析头部标杆爆品特征,突破内容瓶颈 |
| 账号投放决策 | 品牌营销经理 | 「帮我找美食赛道适合投放的抖音号」 | 精准选择投放账号,提高投放 ROI |
| 竞品分析 | MCN 运营人员 | 「帮我分析美食赛道的抖音竞争格局」 | 掌握竞品动态,发现差异化竞争机会 |
---
重要数据说明
- 数据源自红狐数据平台,展示的数据获取时间可能与实时数据存在差别。
- 红狐指数每周更新,若统计周期内账号未发布作品,红狐指数可能为 0。
- 互动率超过 100% 时判定为数据异常,不输出该指标。
- 对标的推荐理由包含 8 级维度标准,当查询账号红狐指数为 0 时走「学习点总结」模式。
- 查询不到账号时,可提交抖音号进行数据收录,约 30 分钟后自动推送诊断报告。
---
抖音相似账号推荐 - 核心工作流程
操作步骤
步骤1:接收用户输入,解析参数
输入方式:抖音账号昵称或抖音号
- 用户输入示例:"帮我查'一乐店长'的相似账号"或"查抖音号geng970616的相似账号"
- 参数:account_id(自动识别昵称和抖音号)
步骤2:调用脚本查询对标账号
# 按抖音号或昵称查询(自动识别)
python scripts/douyin_similar_account.py --account_id "一乐店长"
python scripts/douyin_similar_account.py --account_id "geng970616"查询流程: 一步调用 /dyUser/querySimilarAccounts 接口:
- 含中文输入 → 使用
accountName参数 - 非中文输入 → 使用
accountId参数 - 接口一次性返回 currentAccount + benchmarkAccounts + topAccounts
API接口:POST https://redfox.hk/story/api/dyUser/querySimilarAccounts
步骤3:按标准模版输出结果
强制约束:脚本输出的完整文本即为最终结果,AI必须原样呈现,禁止任何形式的摘要、改写、增减、重组或二次加工。不得在脚本输出前后添加任何额外的总结、解读或评论。
输出顺序: 1. 当前账号基本信息+红狐指数+近期作品 2. 开场白(只显示有数据的组) 3. 对标账号表格(有数据才展示,本账号置首行) 4. 头部账号表格(有数据才展示) 5. 深度分析:共通点 + 差异分析 + 优化建议(有数据才展示) 6. 数据说明:数据更新时间 + 红狐指数说明
输出格式示例:
**查询账号基本信息**
- 账号名称:[一乐店长](https://www.douyin.com/user/83267142382)
- 抖音号:geng970616
- 账号ID(uid):83267142382
- 简介:娱乐主播日常全随机 ...
- 性别:男
- 地区:河南南阳
- IP属地:北京
- 粉丝数:373.9w
- 总获赞数:1.2亿
- 作品总数:1238
- 红狐指数:843.2
- 近7天发布数:5
- 近7天互动量:56.6w
- 最近作品发布:2026-06-03 11:01:46
**近期作品**
| 作品标题 | 点赞数 | 评论数 | 分享数 | 总互动数 | 发布时间 |
| --- | --- | --- | --- | --- | --- |
| [标题](作品链接) | 30w | 1.5w | 8000 | 33.3w | 2026-05-20 12:00:00 |
✨ 为你匹配到【对标账号(5个)】和【头部账号(5个)】的2组推荐,可按需参考:
👉【对标账号(6个)】(红狐指数向上最近的账号,可直接复制玩法)
| 账号名称 | 粉丝数 | 总获赞 | 近7天互动 | 红狐指数 | 指数差距 | 推荐理由 |
| --- | --- | --- | --- | --- | --- | --- |
| **[一乐店长](账号链接)** | 373.9w | 1.2亿 | 56.6w | 843.2 | 本账号 | 「**本账号**」 |
| [老赫晨](账号链接) | 404.7w | 2976.7w | 23.5w | 843.6 | +0.4 | 持续更新(近7天1条),短视频/中等深度<br>粉丝404.7w,总获赞2976.7w<br>红狐指数843.6,高出你0.4点 |
👉【头部账号(5个)】(同分类红狐指数倒序前5,模式成熟可追赶)
| 账号名称 | 粉丝数 | 总获赞 | 近7天互动 | 红狐指数 | 指数差距 | 推荐理由 |
| --- | --- | --- | --- | --- | --- | --- |
| [陈伯(全能王)](账号链接) | 1634.2w | 1597.8w | 72.3w | 983.9 | +140.7 | 持续更新(近7天3条),短视频/中等深度<br>粉丝1634.2w,总获赞1597.8w<br>红狐指数983.9,高出你140.7点 |
**深度分析**
📌 **共通点**
- 更新节奏:同赛道账号平均近7天6条,保持稳定更新
- 粉丝量级:相似账号平均粉丝659.8w,处于同一发展阶段
- 红狐指数:相似账号平均891.8
📊 **差异分析**
- 红狐指数差距:对标账号平均843.7,比你高0.5点
- 头部差距:头部标杆最高红狐指数983.9,比你高140.7点
- 更新节奏差异:部分对标账号日更(近7天18条),高频更新是流量基础
💡 **优化建议**
1. **提升更新频率**:互动量最高的对标账号近7天发布7条,建议保持稳定更新节奏
*数据更新时间:2026-06-02 01:58:32*
*红狐指数:每周更新,若统计周期内账号未发布作品,红狐指数可能为0。*账号未找到情况: 当API返回"未找到账号"错误时,输出收录提示:
未查询到当前账号的相关信息,可提交当前抖音账号进行账号收录。
1. 回复抖音号(在抖音个人主页显示的ID,如 {account_id}_1234),即可进行账号收录。30分钟后将自动为您推送相似账号报告~
2. 下次再说;用户确认收录时,调用 --sync 参数触发:
python scripts/douyin_similar_account.py --account_id "oioioi" --sync调用 /dyUser/syncUserNotes 接口触发账号数据同步收录,输出:
已触发账号收录,30分钟后将自动为您推送相似账号报告~无对标/头部数据情况(账号已找到但无对标推荐):
当前未查询到相关对标账号数据。可能原因:1) 账号暂未被平台收录;2) 抖音号或名称输入有误。
建议:确认抖音号/名称是否正确后重新查询。数值格式化:< 10000 直接展示原值,>= 10000 格式化为 "X.Xw",>= 100000000 格式化为 "X.X亿"
推荐理由:严格参考下方「推荐理由生成维度」章节的8级维度标准与内容进行输出,不得自行扩展解读或增加额外维度
步骤4:输出结果
脚本直接输出格式化结果,AI必须将脚本输出原样完整展示,不得摘要、改写、增减、重组或添加额外评论。
API响应字段映射
接口 /dyUser/querySimilarAccounts 返回的抖音专用字段与输出内容的对应关系:
currentAccount(当前账号)
| API字段 | 类型 | 输出用途 |
|---|---|---|
| nickname | String | 账号名称 |
| accountId | String | 抖音号,用于基本信息 |
| uid | String | 账号标识,用于基本信息和构造主页链接 |
| avatarUrl | String | 头像链接 |
| signature | String | 账号简介 |
| gender | String | 性别 |
| age | Integer | 年龄 |
| province / city | String | 地区 |
| ipLocation | String | IP属地 |
| followerCount | Integer | 粉丝数 |
| awemeCount | Integer | 作品总数 |
| totalFavorited | Long | 总获赞数 |
| crawlTime | String | 数据更新时间 |
| redfoxIndex | Double | 红狐指数 |
| works | List | 近7天作品列表 |
benchmarkAccounts / topAccounts(对标/头部账号)
| API字段 | 类型 | 输出用途 |
|---|---|---|
| nickname | String | 账号名称,用于表格和标题 |
| url | String | 账号链接,用于Markdown超链接 |
| followerCount | Integer | 粉丝数,用于基本信息和表格 |
| uid | String | 账号标识 |
| awemeCount | Integer | 作品总数 |
| totalFavorited | Long | 总获赞数,用于基本信息和推荐理由 |
| awemeCountSeven | Integer | 近7天发布数,用于更新节奏分析 |
| interactiveCountSeven | Integer | 近7天互动量,用于表格和互动分析 |
| interactiveCountThirty | Integer | 近30天互动数 |
| lastAwemeCreateTime | String | 最近作品发布时间 |
| redfoxIndex | Double | 红狐指数,用于表格和指数对比 |
| works[].title | String | 作品标题,用于作品表格和主题分析 |
| works[].playCount | Integer | 播放量,用于作品表格和互动率/点赞率计算 |
| works[].diggCount | Integer | 点赞数,用于点赞率计算 |
| works[].commentCount | Integer | 评论数,用于作品表格 |
| works[].shareCount | Integer | 分享数,用于作品表格 |
| works[].interactiveCount | Integer | 总互动数,用于互动率计算 |
| works[].createTime | String | 发布时间,用于时段分析 |
| works[].workUrl | String | 作品链接,用于Markdown超链接 |
| works[].coverUrl | String | 封面链接,用于内容策略分析 |
| works[].desc | String | 作品正文,用于主题分析 |
对标匹配规则
对标匹配由API服务端完成,返回规则如下:
对标账号(benchmarkAccounts)
- 匹配逻辑:同分类中红狐指数向上最近的5个账号
- 特点:指数接近,运营阶段相似,玩法可直接复制
头部账号(topAccounts)
- 匹配逻辑:同分类中红狐指数倒序前5
- 特点:同赛道顶尖账号,运营模式成熟,适合追赶学习
输出格式规范
1. 查询账号基本信息和所有表格中的【账号名称】需添加跳转链接,统一使用 secUid 构造 https://www.douyin.com/user/{secUid};若 secUid 为空,则回退使用 uid 构造 https://www.douyin.com/user/{uid} 2. 表格中【推荐理由】需分多行展示(用 <br> 换行),且「」内的内容需加粗 3. 深度分析包含三部分:共通点、差异分析、优化建议,按需输出 4. 对标/头部账号表格列顺序:账号名称 | 粉丝数 | 总获赞 | 近7天互动 | 红狐指数 | 指数差距 | 推荐理由 5. 对标账号表格第一行为本账号(加粗显示),指数差距列显示"本账号",推荐理由为「本账号」,总数=对标账号数+1 6. 指数差距列:本账号显示"本账号",其他账号显示"+X.X"(高出查询账号)或"-X.X"(低于查询账号),无数据时显示"-" 7. 对标账号和头部账号数量如实展示,不人为补全 8. 末尾统一输出数据说明:
*数据更新时间:{crawlTime}*(取currentAccount.crawlTime)*红狐指数:每周更新,若统计周期内账号未发布作品,红狐指数可能为0。*
API接口详情
接口:查询抖音对标账号
接口地址: POST https://redfox.hk/story/api/dyUser/querySimilarAccounts
认证方式: 请求头 X-API-KEY(ak_xxx格式)
积分消费: resourceId: /story/api/dyUser/querySimilarAccounts
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| accountId | String | 条件必填 | 抖音账号ID(支持unique_id、short_id、uid任一匹配),与accountName二选一 |
| accountName | String | 条件必填 | 抖音账号名称,根据名称查询并匹配对标账号,与accountId二选一 |
| source | String | 否 | 来源标识,用于调用次数限制 |
两种查询模式:
1. 传入accountId:通过账号ID查询该账号信息并匹配对标账号
2. 传入accountName:通过账号名称查询该账号信息并匹配对标账号
请求示例(通过账号ID查询):
{
"accountId": "dy_example123",
"source": "coze"
}请求示例(通过账号名称查询):
{
"accountName": "一乐店长",
"source": "coze"
}响应字段说明:
| 字段路径 | 类型 | 说明 |
|---|---|---|
| data.currentAccount | DyUserInfoVO | 当前账号信息 |
| data.benchmarkAccounts | List\<DySimilarAccountDetailVO\> | 对标账号列表(红狐指数向上最近的5个) |
| data.topAccounts | List\<DySimilarAccountDetailVO\> | 头部账号列表(同分类红狐指数倒序前5) |
当前账号信息(DyUserInfoVO):
| 字段 | 类型 | 说明 |
|---|---|---|
| nickname | String | 账号名 |
| avatarUrl | String | 头像链接 |
| signature | String | 账号简介 |
| accountId | String | 账号平台展示id(unique_id优先,备选short_id) |
| uid | String | uid |
| secUid | String | 加密用户标识,用于构造抖音主页链接(统一使用secUid,secUid为空时回退uid) |
| gender | String | 性别 |
| age | Integer | 年龄 |
| country | String | 地域-国家 |
| province | String | 地域-省 |
| city | String | 地域-市 |
| ipLocation | String | IP属地-省 |
| followerCount | Integer | 平台粉丝数 |
| awemeCount | Integer | 总发布作品数 |
| totalFavorited | Long | 总点赞数 |
| crawlTime | String | 账号更新时间 |
| redfoxIndex | Double | 红狐指数 |
| works | List\<DyWorkVO\> | 近7天作品列表 |
| similarAccounts | List\<DySimilarAccountVO\> | 相似账号列表 |
对标/头部账号详情(DySimilarAccountDetailVO):
| 字段 | 类型 | 说明 |
|---|---|---|
| nickname | String | 账号名 |
| url | String | 账号链接 |
| followerCount | Integer | 粉丝数 |
| uid | String | 账号标识(uid) |
| secUid | String | 加密用户标识,用于构造抖音主页链接(统一使用secUid,secUid为空时回退uid) |
| awemeCount | Integer | 作品总数 |
| totalFavorited | Long | 总获赞数 |
| awemeCountSeven | Integer | 近7天发作品数 |
| interactiveCountSeven | Integer | 近7天作品互动量 |
| interactiveCountThirty | Integer | 近30天互动数 |
| lastAwemeCreateTime | String | 最近作品发布时间 |
| redfoxIndex | Double | 红狐指数 |
| works | List\<DyWorkVO\> | 近7天作品列表 |
作品信息(DyWorkVO):
| 字段 | 类型 | 说明 |
|---|---|---|
| awemeId | String | 作品ID |
| title | String | 作品标题(取正文首行) |
| coverUrl | String | 作品封面链接 |
| desc | String | 作品正文 |
| createTime | String | 发布时间 |
| diggCount | Integer | 点赞数 |
| commentCount | Integer | 评论数 |
| shareCount | Integer | 分享数 |
| playCount | Integer | 播放数 |
| interactiveCount | Integer | 总互动数 |
| workUrl | String | 作品链接 |
错误码:
| code | 说明 |
|---|---|
| 200 / 2000 | 成功(实际返回2000) |
| 4001 | 参数错误/未找到账号 |
| 500 | 业务异常,具体原因见msg字段 |
常见业务错误:
| msg | 场景 |
|---|---|
| 今日调用次数已达上限,请明日再试 | source标识对应的每日调用次数已达上限 |
核心模块说明
| 模块 | 职责 |
|---|---|
query_similar_accounts() | 调用 /dyUser/querySimilarAccounts 接口,支持accountId和accountName两种查询方式,返回currentAccount+benchmarkAccounts+topAccounts |
sync_user_notes() | 调用 /dyUser/syncUserNotes 接口,触发账号数据同步收录,账号未找到时自动调用 |
format_output() | 格式化完整文本输出,包含当前账号信息、对标表格、头部表格、深度分析 |
generate_recommendation_reason() | 基于多维度生成推荐理由,涵盖红狐指数对比、爆品引用、更新节奏、互动率等 |
generate_analysis_summary() | 基于共通点、差异分析、优化建议三维输出深度分析 |
推荐理由生成维度
推荐理由由多个维度按优先级组合输出,数据稀疏时自动降级补充:
| 优先级 | 维度 | 数据来源 | 示例 |
|---|---|---|---|
| 1 | 内容主题聚焦 | works + effective_avg | 近7天3条爆品,聚焦于美食教程/家常菜 |
| 2 | 爆品标题引用 | works中最高播放作品 | 爆品「红烧肉的秘诀…」达均播2.4倍 |
| 3 | 与查询账号播放倍数对比 | 查询账号 + 对标账号均播 | 均播约为你的3.2倍,模式成熟可追赶 |
| 4 | 更新节奏+近7天发布量+内容策略 | awemeCountSeven + works | 日更高产(近7天10条),短视频/深度解析 |
| 5 | 互动率+点赞率 | works中互动/点赞/播放数据 | 互动率8.5%,点赞率5.2%,用户粘性强 |
| 6 | 粉丝量级+总获赞+红狐指数对比 | followerCount + totalFavorited + redfoxIndex | 粉丝5w,总获赞200w,红狐指数843.6,高出你0.4点 |
| 7 | 数据稀疏补充 | 多维度兜底 | 内容方向:美食教程/家常菜,近7天发布5条 |
| 8 | 结论兜底 | 赛道+均播+7天互动 | 同赛道账号,均播5.2w,可参考运营策略 |
关键机制:
effective_avg计算:从 works 中计算effective_avg = max(works播放均值, ...)作为爆品判断基准- 互动率超过100%判定为数据异常,不输出
- 点赞率分级描述:>=5%用户粘性极强,>=3%用户粘性强,1%-3%粘性尚可
- 播放倍数对比:>=3倍模式成熟可追赶,>=1.5倍策略可参考,0.7-1.3倍玩法可直接复制
- 红狐指数对比:显示对标账号与查询账号的指数差距
- 各维度间自动去重,避免同一条信息重复输出
输出约束:
- 推荐理由必须严格按上述8级维度标准生成,仅使用对应数据来源和描述模板
- 禁止自行扩展解读、增加额外维度或改写标准话术
- 脚本输出的推荐理由即为最终结果,AI展示时直接呈现,不做二次加工
红狐指数为0时的推荐理由: 当查询账号的红狐指数为0时,推荐理由走「学习点总结」模式(_generate_learning_point_reason),基于账号数据、内容数据、更新节奏、整体内容策略定位等总结该账号的值得学习点,输出格式不同于标准8级维度:
| 维度 | 数据来源 | 示例 |
|---|---|---|
| 同赛道+爆品/内容聚焦+路径可复制 | works互动数据 + content_themes | 同赛道近7天2篇爆文,全聚焦于历史人物/历史事件,路径可复制 |
| 更新节奏+内容策略定位 | awemeCountSeven + works | 日更高产(近7天7条),短视频/深度解析 |
| 互动/点赞数据亮点 | works中互动/点赞/播放数据 | 互动率8.5% |
| 粉丝量级+总获赞 | followerCount + totalFavorited | 粉丝5w,总获赞200w |
| 近7天互动 | interactiveCountSeven | 近7天互动284.0w |
| 数据稀疏补充 | 多维度兜底 | 内容方向:美食教程/家常菜,近7天发布5条 |
| 结论兜底 | 赛道+粉丝+7天互动 | 同赛道对标账号,运营策略可参考 |
订阅服务
查询结果末尾自动输出订阅服务提示,文案如下:
是否订阅「{查询账号昵称}」的相似账号最新信息推送?
1. 每日下午19点推送最新数据。可自行选择推送频率和时间~
2. 暂不需要#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
抖音相似账号推荐脚本
功能:调用红狐API查询抖音对标账号和头部账号,输出对标账号信息+近期作品+深度分析
接口文档:POST /dyUser/querySimilarAccounts
"""
import argparse
import json
import os
import platform
import re
import urllib.error
import urllib.parse
import urllib.request
# ============================================================
# API Key 管理
# ============================================================
def get_api_key():
"""获取 RedFox API Key,依次从环境变量、shell配置文件中读取,均未找到则提示用户配置"""
api_key = os.getenv("REDFOX_API_KEY")
if api_key:
return api_key.strip()
system = platform.system()
if system == "Windows":
api_key = _read_api_key_from_windows()
else:
api_key = _read_api_key_from_unix_shell_config()
if api_key:
return api_key.strip()
if system == "Windows":
config_hint = (
"未找到 REDFOX_API_KEY 配置,请按以下步骤配置:\n"
" 1. 访问 https://redfox.hk/ 注册账号并获取 API Key\n"
" 2. 在 PowerShell 中执行:\n"
' [Environment]::SetEnvironmentVariable("REDFOX_API_KEY", "<你的API Key>", "User")\n'
" 3. 重启终端后生效"
)
else:
shell = os.getenv("SHELL", "")
if "zsh" in shell:
rc_file = "~/.zshrc"
elif "bash" in shell:
rc_file = "~/.bashrc"
else:
rc_file = "~/.bashrc"
config_hint = (
"未找到 REDFOX_API_KEY 配置,请按以下步骤配置:\n"
" 1. 访问 https://redfox.hk/ 注册账号并获取 API Key\n"
f" 2. 执行:echo 'export REDFOX_API_KEY=<你的API Key>' >> {rc_file}\n"
f" 3. 执行:source {rc_file}"
)
raise ValueError(config_hint)
def _read_api_key_from_unix_shell_config():
config_files = [
os.path.expanduser("~/.zshrc"),
os.path.expanduser("~/.bashrc"),
os.path.expanduser("~/.bash_profile"),
os.path.expanduser("~/.profile"),
]
for config_file in config_files:
if not os.path.isfile(config_file):
continue
try:
with open(config_file, "r", encoding="utf-8", errors="ignore") as f:
for line in f:
line = line.strip()
m = re.match(r'^(?:export\s+)?REDFOX_API_KEY=["\']?(.+?)["\']?\s*$', line)
if m:
return m.group(1)
except (IOError, OSError):
continue
return None
def _read_api_key_from_windows():
try:
import winreg
key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Environment")
try:
value, _ = winreg.QueryValueEx(key, "REDFOX_API_KEY")
if value:
return str(value)
finally:
winreg.CloseKey(key)
except (ImportError, OSError):
pass
ps_profile_paths = [
os.path.join(os.path.expanduser("~"), "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1"),
os.path.join(os.path.expanduser("~"), "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1"),
]
for profile_path in ps_profile_paths:
if not os.path.isfile(profile_path):
continue
try:
with open(profile_path, "r", encoding="utf-8", errors="ignore") as f:
for line in f:
line = line.strip()
m = re.match(r'\$env:REDFOX_API_KEY\s*=\s*["\']?(.+?)["\']?\s*$', line)
if m:
return m.group(1)
except (IOError, OSError):
continue
return None
# ============================================================
# API 调用
# ============================================================
def query_similar_accounts(accountId=None, accountName=None):
"""调用API查询对标账号和头部账号
接口文档:POST /dyUser/querySimilarAccounts
两种查询模式:
1. 传入accountId:通过账号ID查询该账号信息并匹配对标账号
2. 传入accountName:通过账号名称查询该账号信息并匹配对标账号
响应字段:
data.currentAccount: DyUserInfoVO 当前账号信息(含redfoxIndex、similarAccounts)
data.benchmarkAccounts: List<DySimilarAccountDetailVO> 对标账号列表(红狐指数向上最近的5个)
data.topAccounts: List<DySimilarAccountDetailVO> 头部账号列表(同分类红狐指数倒序前5)
账号详情 DySimilarAccountDetailVO: nickname, url, followerCount, uid,
awemeCount, totalFavorited, awemeCountSeven, interactiveCountSeven,
interactiveCountThirty, lastAwemeCreateTime, redfoxIndex, works[]
作品 DyWorkVO: awemeId, title, coverUrl, desc, createTime, diggCount,
commentCount, shareCount, playCount, interactiveCount, workUrl
"""
credential = get_api_key()
url = "https://redfox.hk/story/api/dyUser/querySimilarAccounts"
headers = {
"Content-Type": "application/json",
"X-API-KEY": credential
}
payload = {}
if accountId:
payload["accountId"] = accountId
if accountName:
payload["accountName"] = accountName
payload["source"] = "抖音相似账号推荐-GitHub"
try:
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(url, data=data, headers=headers, method="POST")
with urllib.request.urlopen(req, timeout=30) as resp:
result = json.loads(resp.read().decode("utf-8"))
except urllib.error.HTTPError as e:
body = e.read().decode("utf-8", errors="replace")
raise Exception(f"HTTP请求失败: {e.code}, {body}")
except urllib.error.URLError as e:
raise Exception(f"请求失败: {str(e)}")
# 实际成功码为2000(非文档中的200)
if result.get("code") not in (200, 2000):
msg = result.get("msg", "未知错误")
raise Exception(f"API返回错误: {msg}")
data = result.get("data")
if data is None:
return None, [], []
current_account = data.get("currentAccount")
benchmark_accounts = data.get("benchmarkAccounts") or []
top_accounts = data.get("topAccounts") or []
return current_account, benchmark_accounts, top_accounts
# ============================================================
# 数据格式化
# ============================================================
def format_number(num):
"""格式化数字:< 10000直接展示,>= 10000格式化为X.Xw,>= 100000000格式化为X.X亿"""
if num is None:
return "0"
if num >= 100000000:
return f"{round(num / 100000000, 1)}亿"
if num >= 10000:
return f"{round(num / 10000, 1)}w"
return str(num)
def calc_avg_play(account):
"""从works计算平均播放量"""
works = account.get("works") or []
if not works:
return 0
total = sum(w.get("playCount") or 0 for w in works)
return total / len(works) if len(works) > 0 else 0
def calc_seven_day_plays(account):
"""计算近7天播放量:从works累加playCount"""
works = account.get("works") or []
if works:
return sum(w.get("playCount") or 0 for w in works)
return account.get("interactiveCountSeven") or 0
# ============================================================
# 内容分析辅助函数
# ============================================================
def _extract_content_themes(works):
"""从作品标题中提取内容主题聚焦方向"""
if not works:
return []
theme_keywords = {
"美食": ["美食", "菜谱", "做法", "食谱", "烹饪", "好吃", "探店", "下厨", "家常", "下饭", "快手菜"],
"旅行": ["旅行", "旅游", "攻略", "景点", "出行", "打卡", "自驾"],
"数码科技": ["科技", "数码", "手机", "电脑", "AI", "互联网", "软件", "测评"],
"学习教育": ["科普", "知识", "考试", "高考", "考研", "培训", "学习", "升学", "原理", "揭秘"],
"情感": ["情感", "婚姻", "爱情", "亲情", "家庭", "夫妻", "恋爱"],
"小剧场": ["搞笑", "剧情", "段子", "整蛊", "反转", "沙雕", "短剧", "连载", "大结局"],
"身体锻炼": ["健身", "运动", "减肥", "瑜伽", "跑步", "增肌"],
"化妆美容": ["美妆", "护肤", "化妆", "口红", "粉底", "种草"],
"潮流风尚": ["穿搭", "时尚", "搭配", "OOTD", "潮流", "衣服"],
"亲子": ["亲子", "育儿", "宝宝", "孩子", "母婴", "早教"],
"汽车": ["汽车", "新能源", "买车", "驾照", "车型", "评测"],
"游戏": ["游戏", "电竞", "攻略", "排位", "上分", "直播"],
"音乐": ["音乐", "翻唱", "歌曲", "吉他", "钢琴", "原创"],
"动物": ["宠物", "猫", "狗", "萌宠", "撸猫", "遛狗"],
"居家装修": ["装修", "家居", "设计", "改造", "收纳", "好物"],
"财富理财": ["理财", "投资", "基金", "股票", "房产", "存款", "财经", "金融"],
"三农": ["农村", "农活", "种地", "养殖", "家乡", "田园"],
"健康医学": ["健康", "养生", "饮食", "睡眠", "中医", "医疗", "医生"],
"舞蹈才艺": ["舞蹈", "编舞", "街舞", "古典舞", "教学"],
"二次元": ["动漫", "漫画", "cos", "二次元", "手办"],
"颜值造型": ["颜值", "造型", "变装", "化妆", "美颜"],
"人文": ["人文", "社科", "历史", "哲学", "文化", "读书"],
"影视": ["影视", "综艺", "电影", "电视剧", "解说", "影评"],
"体育": ["体育", "足球", "篮球", "赛事", "奥运", "比赛"],
"明星娱乐": ["明星", "八卦", "娱乐圈", "偶像", "追星"],
"个人才艺": ["才艺", "技能", "手艺", "表演", "绝活"],
"生活vlog": ["日常", "vlog", "记录", "生活", "沉浸式"],
}
all_text = " ".join(
[w.get("title", "") for w in works if w.get("title")] +
[w.get("desc", "") for w in works if w.get("desc")]
)
matched_themes = []
for theme, keywords in theme_keywords.items():
match_count = sum(1 for kw in keywords if kw in all_text)
if match_count >= 1:
matched_themes.append((theme, match_count))
matched_themes.sort(key=lambda x: x[1], reverse=True)
return [t[0] for t in matched_themes[:3]]
def _analyze_content_strategy(works):
"""分析内容策略和风格定位"""
if not works:
return ""
style_parts = []
has_cover = sum(1 for w in works if w.get("coverUrl"))
if has_cover > len(works) * 0.5:
style_parts.append("短视频")
else:
style_parts.append("图文/混剪")
titles = [w.get("title", "") for w in works if w.get("title")]
if titles:
avg_len = sum(len(t) for t in titles) / len(titles)
if avg_len > 30:
style_parts.append("深度解析")
elif avg_len < 10:
style_parts.append("短平快")
else:
style_parts.append("中等深度")
return "/".join(style_parts) if style_parts else ""
def _analyze_publish_schedule(works):
"""从作品发布时间推断发布时段规律"""
if not works:
return ""
hours = []
for w in works:
pt = w.get("createTime") or ""
m = re.search(r'(\d{1,2}):(\d{2})', pt)
if m:
hours.append(int(m.group(1)))
if not hours:
return ""
from collections import Counter
hour_counter = Counter(hours)
most_common_hour, count = hour_counter.most_common(1)[0]
total = len(hours)
if 5 <= most_common_hour < 9:
period = "早间"
elif 9 <= most_common_hour < 12:
period = "上午"
elif 12 <= most_common_hour < 14:
period = "午间"
elif 14 <= most_common_hour < 18:
period = "下午"
elif 18 <= most_common_hour < 22:
period = "晚间"
else:
period = "深夜"
if count >= total * 0.6 and count >= 2:
return f"{period}{most_common_hour}点固定发布"
elif count >= 2:
return f"{period}时段为主"
return ""
def _extract_top_work(works, avg_play):
"""提取最高播放作品的标题(爆品引用),返回 (标题, 播放量) 或 None"""
if not works or avg_play <= 0:
return None
top_work = max(works, key=lambda w: w.get("playCount") or 0)
top_plays = top_work.get("playCount") or 0
if top_plays >= avg_play * 2 and top_plays > 0:
title = top_work.get("title") or ""
if len(title) > 20:
title = title[:18] + "…"
return (title, top_plays)
return None
def _calc_interaction_rate(works):
"""计算互动率:总互动数/播放量"""
if not works:
return None
total_plays = sum(w.get("playCount") or 0 for w in works)
total_interactive = sum(w.get("interactiveCount") or 0 for w in works)
if total_plays <= 0 or total_interactive <= 0:
return None
rate = total_interactive / total_plays
if rate > 1.0:
return None
if rate < 0.001:
return None
return rate
def _calc_like_rate(works):
"""计算点赞率:点赞数/播放量(diggCount/playCount)"""
if not works:
return None
total_plays = sum(w.get("playCount") or 0 for w in works)
total_likes = sum(w.get("diggCount") or 0 for w in works)
if total_plays <= 0 or total_likes <= 0:
return None
rate = total_likes / total_plays
if rate > 1.0 or rate < 0.001:
return None
return rate
def _add_sparse_data_reasons(parts, account, aweme_count_seven, works, content_themes):
"""当数据稀疏时,补充其他维度的推荐理由"""
interactive_count_seven = account.get("interactiveCountSeven") or 0
if interactive_count_seven > 0 and not any("互动" in p for p in parts):
parts.append(f"近7天互动{format_number(interactive_count_seven)},用户活跃度可参考")
if works and not content_themes:
topic = _infer_topic_from_titles(works)
if topic:
parts.append(f"内容方向:{topic}")
if works and not any("点赞率" in p for p in parts):
like_rate = _calc_like_rate(works)
if like_rate and like_rate >= 0.01:
parts.append(f"点赞率{like_rate*100:.1f}%,用户粘性强")
if works and not any("发布" in p or "固定" in p or "时段" in p for p in parts):
schedule = _analyze_publish_schedule(works)
if schedule:
parts.append(schedule)
if aweme_count_seven > 0 and not any("更新" in p or "日更" in p or "周更" in p for p in parts):
parts.append(f"近7天发布{aweme_count_seven}条,保持更新节奏")
follower_count = account.get("followerCount") or 0
total_favorited = account.get("totalFavorited") or 0
if follower_count > 0 and not any("粉丝" in p for p in parts):
parts.append(f"粉丝{format_number(follower_count)},总获赞{format_number(total_favorited)},账号体量可参考")
if len(parts) < 2:
parts.append("同赛道定位匹配,可参考其内容策略和运营节奏")
def _infer_topic_from_titles(works):
"""从作品标题中推断内容方向"""
if not works:
return ""
titles = [w.get("title", "") for w in works if w.get("title")]
if not titles:
return ""
extended_themes = {
"美食": ["美食", "菜谱", "做法", "食谱", "烹饪", "好吃", "探店"],
"旅行": ["旅行", "旅游", "攻略", "景点", "出行", "打卡"],
"数码科技": ["科技", "数码", "手机", "电脑", "AI", "互联网", "软件"],
"学习教育": ["科普", "知识", "原理", "揭秘", "考试", "学习"],
"小剧场": ["搞笑", "剧情", "段子", "反转"],
"化妆美容": ["美妆", "护肤", "化妆", "口红", "种草"],
"汽车": ["汽车", "新能源", "买车", "车型"],
"游戏": ["游戏", "电竞", "攻略", "上分"],
"亲子": ["亲子", "育儿", "宝宝", "孩子", "母婴"],
"情感": ["情感", "婚姻", "爱情", "恋爱"],
"财富理财": ["理财", "投资", "基金", "股票"],
"健康医学": ["健康", "养生", "医疗", "中医"],
}
all_titles_text = " ".join(titles)
matched = []
for theme, keywords in extended_themes.items():
match_count = sum(1 for kw in keywords if kw in all_titles_text)
if match_count >= 1:
matched.append(theme)
return "/".join(matched[:2]) if matched else ""
def bold_bracket_content(text):
"""将「」中的内容加粗展示"""
return re.sub(r'「([^」]+)」', r'「**\1**」', text)
def _describe_like_level(like_rate):
"""根据点赞率分级描述用户粘性"""
pct = like_rate * 100
if pct >= 5:
return f"点赞率{pct:.1f}%,用户粘性极强"
elif pct >= 3:
return f"点赞率{pct:.1f}%,用户粘性强"
else:
return f"点赞率{pct:.1f}%,粘性尚可"
# ============================================================
# 推荐理由生成
# ============================================================
def generate_recommendation_reason(account, query_avg_play=None, query_redfox_index=None):
"""生成推荐理由:基于账号数据、内容数据、更新节奏等多维度总结值得学习点
当查询账号红狐指数为0时,走「学习点总结」模式:
基于账号数据、内容数据、更新节奏、整体内容策略定位等总结该账号的值得学习点
eg: 同赛道近7天2篇爆文,全聚焦于历史人物、历史事件的深度分析,路径可复制
当查询账号红狐指数>0时,走标准8级维度模式。
"""
# 判断是否走「学习点总结」模式(查询账号红狐指数为0)
is_zero_redfox = query_redfox_index is None or query_redfox_index <= 0
if is_zero_redfox:
return _generate_learning_point_reason(account, query_avg_play)
# ===== 以下为标准8级维度模式(红狐指数>0) =====
parts = []
works = account.get("works") or []
aweme_count_seven = account.get("awemeCountSeven") or 0
follower_count = account.get("followerCount") or 0
total_favorited = account.get("totalFavorited") or 0
interactive_count_seven = account.get("interactiveCountSeven") or 0
# 从 works 计算播放数据
works_total_plays = sum(w.get("playCount") or 0 for w in works) if works else 0
works_avg_play = works_total_plays / len(works) if works and len(works) > 0 else 0
effective_avg = works_avg_play if works_avg_play > 0 else 0
# 1. 内容主题聚焦
burst_works = []
if works and effective_avg > 0:
for w in works:
plays = w.get("playCount") or 0
if plays >= effective_avg * 2:
burst_works.append(w)
content_themes = _extract_content_themes(works) if works else []
if burst_works and content_themes:
burst_count = len(burst_works)
theme_str = "/".join(content_themes[:2])
parts.append(f"近7天{burst_count}条爆品,聚焦于{theme_str}")
elif burst_works:
burst_count = len(burst_works)
parts.append(f"近7天{burst_count}条爆品")
elif content_themes:
theme_str = "/".join(content_themes[:2])
parts.append(f"内容聚焦于{theme_str}")
# 2. 爆品标题引用
if works and effective_avg > 0:
top_work = _extract_top_work(works, effective_avg)
if top_work:
title, plays = top_work
parts.append(f"爆品「{title}」达均播{plays/effective_avg:.1f}倍")
# 3. 与查询账号的播放倍数对比
if query_avg_play and query_avg_play > 0 and effective_avg > 0:
ratio = effective_avg / query_avg_play
if ratio >= 3:
parts.append(f"均播约为你的{ratio:.1f}倍,模式成熟可追赶")
elif ratio >= 1.5:
parts.append(f"均播约为你的{ratio:.1f}倍,运营策略可参考")
elif 0.7 <= ratio <= 1.3:
parts.append(f"均播与你接近,玩法可直接复制")
elif ratio < 0.7:
parts.append(f"均播约为你的{ratio:.1f}倍,起号阶段可互鉴")
# 4. 更新节奏 + 近7天发布量 + 内容策略
strategy_parts = []
if aweme_count_seven >= 7:
strategy_parts.append(f"日更高产(近7天{aweme_count_seven}条)")
elif aweme_count_seven >= 4:
strategy_parts.append(f"稳定周更(近7天{aweme_count_seven}条)")
elif aweme_count_seven >= 1:
strategy_parts.append(f"持续更新(近7天{aweme_count_seven}条)")
content_style = _analyze_content_strategy(works)
if content_style:
strategy_parts.append(content_style)
if works:
schedule = _analyze_publish_schedule(works)
if schedule:
strategy_parts.append(schedule)
if strategy_parts:
parts.append(",".join(strategy_parts))
# 5. 数据亮点:互动率 + 点赞率
if works:
interaction_rate = _calc_interaction_rate(works)
if interaction_rate and interaction_rate >= 0.005:
parts.append(f"互动率{interaction_rate*100:.1f}%")
like_rate = _calc_like_rate(works)
if like_rate and like_rate >= 0.01:
parts.append(_describe_like_level(like_rate))
# 6. 粉丝量级 + 总获赞 + 红狐指数对比
if follower_count > 0:
parts.append(f"粉丝{format_number(follower_count)},总获赞{format_number(total_favorited)}")
redfox_index = account.get("redfoxIndex")
if redfox_index is not None and query_redfox_index is not None and query_redfox_index > 0:
diff = redfox_index - query_redfox_index
if diff > 0:
parts.append(f"红狐指数{redfox_index:.1f},高出你{diff:.1f}点")
elif abs(diff) < 5:
parts.append(f"红狐指数{redfox_index:.1f},与你接近")
# 7. 近7天互动数据
if interactive_count_seven > 0 and effective_avg == 0:
parts.append(f"近7天互动{format_number(interactive_count_seven)},用户活跃度可参考")
# 8. 数据稀疏补充
if effective_avg == 0:
_add_sparse_data_reasons(parts, account, aweme_count_seven, works, content_themes)
# 9. 结论兜底
if parts:
result = "<br>".join(parts)
else:
fallback_parts = []
if follower_count > 0:
fallback_parts.append(f"粉丝{format_number(follower_count)}")
if total_favorited > 0:
fallback_parts.append(f"总获赞{format_number(total_favorited)}")
if aweme_count_seven > 0:
fallback_parts.append(f"7天发布{aweme_count_seven}条")
if interactive_count_seven > 0:
fallback_parts.append(f"7天互动{format_number(interactive_count_seven)}")
result = ",".join(fallback_parts) + ",可参考运营策略" if fallback_parts else "同赛道对标账号,可参考运营策略"
result = bold_bracket_content(result)
if len(result) < 20:
result += ",可参考运营策略"
return result
def _generate_learning_point_reason(account, query_avg_play=None):
"""红狐指数为0时的推荐理由:基于账号数据、内容数据、更新节奏、整体内容策略定位等总结值得学习点
eg: 同赛道近7天2篇爆文,全聚焦于历史人物、历史事件的深度分析,路径可复制
"""
parts = []
works = account.get("works") or []
aweme_count_seven = account.get("awemeCountSeven") or 0
follower_count = account.get("followerCount") or 0
total_favorited = account.get("totalFavorited") or 0
interactive_count_seven = account.get("interactiveCountSeven") or 0
# 从 works 计算播放数据
works_total_plays = sum(w.get("playCount") or 0 for w in works) if works else 0
works_avg_play = works_total_plays / len(works) if works and len(works) > 0 else 0
effective_avg = works_avg_play if works_avg_play > 0 else 0
content_themes = _extract_content_themes(works) if works else []
# 1. 同赛道 + 爆品/内容聚焦 + 路径可复制
if works and content_themes:
# 统计高互动作品(互动量 >= 平均互动2倍视为爆品)
interactive_list = [w.get("interactiveCount") or 0 for w in works]
avg_interactive = sum(interactive_list) / len(interactive_list) if interactive_list else 0
burst_count = sum(1 for ic in interactive_list if ic >= avg_interactive * 2 and ic > 0) if avg_interactive > 0 else 0
theme_str = "/".join(content_themes[:2])
if burst_count > 0:
parts.append(f"同赛道近7天{burst_count}篇爆文,全聚焦于{theme_str},路径可复制")
else:
parts.append(f"同赛道内容聚焦于{theme_str},内容策略可参考")
elif content_themes:
theme_str = "/".join(content_themes[:2])
parts.append(f"同赛道内容聚焦于{theme_str},内容策略可参考")
# 2. 更新节奏 + 内容策略定位
strategy_parts = []
if aweme_count_seven >= 7:
strategy_parts.append(f"日更高产(近7天{aweme_count_seven}条)")
elif aweme_count_seven >= 4:
strategy_parts.append(f"稳定周更(近7天{aweme_count_seven}条)")
elif aweme_count_seven >= 1:
strategy_parts.append(f"持续更新(近7天{aweme_count_seven}条)")
content_style = _analyze_content_strategy(works)
if content_style:
strategy_parts.append(content_style)
if works:
schedule = _analyze_publish_schedule(works)
if schedule:
strategy_parts.append(schedule)
if strategy_parts:
parts.append(",".join(strategy_parts))
# 3. 互动/点赞数据亮点
if works:
interaction_rate = _calc_interaction_rate(works)
if interaction_rate and interaction_rate >= 0.005:
parts.append(f"互动率{interaction_rate*100:.1f}%")
like_rate = _calc_like_rate(works)
if like_rate and like_rate >= 0.01:
parts.append(_describe_like_level(like_rate))
# 4. 粉丝量级 + 总获赞
if follower_count > 0:
parts.append(f"粉丝{format_number(follower_count)},总获赞{format_number(total_favorited)}")
# 5. 近7天互动
if interactive_count_seven > 0 and effective_avg == 0:
parts.append(f"近7天互动{format_number(interactive_count_seven)}")
# 6. 数据稀疏补充
if effective_avg == 0:
_add_sparse_data_reasons(parts, account, aweme_count_seven, works, content_themes)
# 结论兜底
if not parts:
fallback_parts = []
if follower_count > 0:
fallback_parts.append(f"粉丝{format_number(follower_count)}")
if total_favorited > 0:
fallback_parts.append(f"总获赞{format_number(total_favorited)}")
if aweme_count_seven > 0:
fallback_parts.append(f"7天发布{aweme_count_seven}条")
if interactive_count_seven > 0:
fallback_parts.append(f"7天互动{format_number(interactive_count_seven)}")
parts = [",".join(fallback_parts) + ",运营策略可参考"] if fallback_parts else ["同赛道对标账号,运营策略可参考"]
result = "<br>".join(parts)
result = bold_bracket_content(result)
if len(result) < 20:
result += ",运营策略可参考"
return result
# ============================================================
# 输出格式化
# ============================================================
def format_account_info(account, label="查询账号"):
"""格式化账号基本信息(适配新版接口currentAccount/DyUserInfoVO)"""
if not account:
return f"未获取到{label}信息"
lines = []
lines.append(f"**{label}基本信息**")
lines.append("")
nickname = account.get("nickname") or "未知"
# 统一使用secUid拼接抖音主页链接,secUid为空时回退uid
sec_uid = account.get("secUid") or ""
uid = account.get("uid") or ""
if sec_uid:
url = f"https://www.douyin.com/user/{sec_uid}"
elif uid and uid != "未知":
url = f"https://www.douyin.com/user/{uid}"
else:
url = "#"
account_id = account.get("accountId") or ""
follower_count = account.get("followerCount") or 0
aweme_count = account.get("awemeCount") or 0
total_favorited = account.get("totalFavorited") or 0
aweme_count_seven = account.get("awemeCountSeven") or 0
# currentAccount 无 awemeCountSeven 字段,用 works 列表长度代替
if aweme_count_seven == 0:
works_list = account.get("works") or []
if works_list:
aweme_count_seven = len(works_list)
interactive_count_seven = account.get("interactiveCountSeven") or 0
interactive_count_thirty = account.get("interactiveCountThirty") or 0
last_aweme_create_time = account.get("lastAwemeCreateTime") or "未知"
signature = account.get("signature") or ""
gender = account.get("gender") or ""
province = account.get("province") or ""
city = account.get("city") or ""
ip_location = account.get("ipLocation") or ""
redfox_index = account.get("redfoxIndex")
crawl_time = account.get("crawlTime") or ""
lines.append(f"- 账号名称:[{nickname}]({url})")
if account_id:
lines.append(f"- 抖音号:{account_id}")
lines.append(f"- 账号ID(uid):{uid}")
if signature:
sig = signature.replace("\n", " | ")
lines.append(f"- 简介:{sig}")
if gender:
lines.append(f"- 性别:{gender}")
location_parts = [p for p in [province, city] if p]
if location_parts:
lines.append(f"- 地区:{''.join(location_parts)}")
if ip_location:
lines.append(f"- IP属地:{ip_location}")
lines.append(f"- 粉丝数:{format_number(follower_count)}")
lines.append(f"- 总获赞数:{format_number(total_favorited)}")
lines.append(f"- 作品总数:{format_number(aweme_count)}")
if redfox_index is not None:
lines.append(f"- 红狐指数:{redfox_index}")
lines.append(f"- 近7天发布数:{aweme_count_seven}")
lines.append(f"- 近7天互动量:{format_number(interactive_count_seven)}")
if interactive_count_thirty:
lines.append(f"- 近30天互动数:{format_number(interactive_count_thirty)}")
lines.append(f"- 最近作品发布:{last_aweme_create_time}")
# 近期作品
works = account.get("works") or []
if works:
lines.append("")
lines.append("**近期作品**")
lines.append("")
lines.append("| 作品标题 | 点赞数 | 评论数 | 分享数 | 总互动数 | 发布时间 |")
lines.append("| --- | --- | --- | --- | --- | --- |")
for w in works[:5]:
title = w.get("title") or "无标题"
work_url = w.get("workUrl") or ""
if work_url:
title = f"[{title}]({work_url})"
diggs = format_number(w.get("diggCount"))
comments = format_number(w.get("commentCount"))
shares = format_number(w.get("shareCount"))
interactive = format_number(w.get("interactiveCount"))
create_time = w.get("createTime") or "未知"
lines.append(f"| {title} | {diggs} | {comments} | {shares} | {interactive} | {create_time} |")
return "\n".join(lines)
def format_table(accounts, title_line, query_avg_play=None, query_redfox_index=None, current_account=None):
"""格式化对标账号Markdown表格(含红狐指数),本账号置首行"""
lines = []
lines.append(title_line)
lines.append("")
lines.append("| 账号名称 | 粉丝数 | 总获赞 | 近7天互动 | 红狐指数 | 指数差距 | 推荐理由 |")
lines.append("| --- | --- | --- | --- | --- | --- | --- |")
# 本账号置首行
if current_account:
ca_nickname = current_account.get("nickname") or "未知"
# 统一使用secUid拼接抖音主页链接,secUid为空时回退uid
ca_sec_uid = current_account.get("secUid") or ""
ca_uid = current_account.get("uid") or ""
if ca_sec_uid:
ca_url = f"https://www.douyin.com/user/{ca_sec_uid}"
elif ca_uid:
ca_url = f"https://www.douyin.com/user/{ca_uid}"
else:
ca_url = "#"
ca_followers = current_account.get("followerCount") or 0
ca_favorited = current_account.get("totalFavorited") or 0
ca_interactive_seven = current_account.get("interactiveCountSeven") or 0
ca_redfox = current_account.get("redfoxIndex")
ca_link = f"**[{ca_nickname}]({ca_url})**"
ca_followers_display = format_number(ca_followers)
ca_favorited_display = format_number(ca_favorited)
ca_interactive_display = format_number(ca_interactive_seven)
ca_redfox_display = f"{ca_redfox:.1f}" if ca_redfox is not None else "-"
ca_diff_display = "本账号"
ca_reason = "「**本账号**」"
lines.append(f"| {ca_link} | {ca_followers_display} | {ca_favorited_display} | {ca_interactive_display} | {ca_redfox_display} | {ca_diff_display} | {ca_reason} |")
for account in accounts:
nickname = account.get("nickname") or "未知"
# 统一使用secUid拼接抖音主页链接,secUid为空时回退uid
sec_uid = account.get("secUid") or ""
uid = account.get("uid") or ""
if sec_uid:
url = f"https://www.douyin.com/user/{sec_uid}"
elif uid:
url = f"https://www.douyin.com/user/{uid}"
else:
url = "#"
follower_count = account.get("followerCount") or 0
total_favorited = account.get("totalFavorited") or 0
interactive_count_seven = account.get("interactiveCountSeven") or 0
redfox_index = account.get("redfoxIndex")
account_link = f"[{nickname}]({url})"
followers_display = format_number(follower_count)
favorited_display = format_number(total_favorited)
interactive_display = format_number(interactive_count_seven)
redfox_display = f"{redfox_index:.1f}" if redfox_index is not None else "-"
# 计算指数差距
if redfox_index is not None and query_redfox_index is not None and query_redfox_index > 0:
diff = redfox_index - query_redfox_index
if diff > 0:
diff_display = f"+{diff:.1f}"
elif diff < 0:
diff_display = f"{diff:.1f}"
else:
diff_display = "0"
else:
diff_display = "-"
recommendation = generate_recommendation_reason(account, query_avg_play, query_redfox_index)
lines.append(f"| {account_link} | {followers_display} | {favorited_display} | {interactive_display} | {redfox_display} | {diff_display} | {recommendation} |")
return "\n".join(lines)
def generate_analysis_summary(benchmark_accounts, top_accounts, query_avg_play=None, query_redfox_index=None):
"""生成深度分析:共通点 + 差异 + 建议"""
lines = []
lines.append("")
lines.append("**深度分析**")
lines.append("")
all_accounts = (benchmark_accounts or []) + (top_accounts or [])
if not all_accounts:
return ""
# --- 共通点分析 ---
lines.append("📌 **共通点**")
common_points = []
# 更新节奏共通
update_counts = [acc.get("awemeCountSeven") or 0 for acc in all_accounts if acc.get("awemeCountSeven")]
if update_counts:
avg_update = sum(update_counts) / len(update_counts)
if avg_update >= 7:
common_points.append(f"- 更新节奏:同赛道账号普遍日更(平均近7天{avg_update:.0f}条)")
elif avg_update >= 3:
common_points.append(f"- 更新节奏:同赛道账号平均近7天{avg_update:.0f}条,保持稳定更新")
else:
common_points.append(f"- 更新节奏:同赛道账号平均近7天{avg_update:.0f}条,低频高质型")
# 互动表现共通
interaction_rates = []
for acc in all_accounts:
works = acc.get("works") or []
rate = _calc_interaction_rate(works)
if rate:
interaction_rates.append(rate)
if interaction_rates:
avg_rate = sum(interaction_rates) / len(interaction_rates)
common_points.append(f"- 互动表现:相似账号平均互动率{avg_rate*100:.1f}%,反映该赛道用户互动偏好")
# 粉丝量级分布
follower_counts = [acc.get("followerCount") or 0 for acc in all_accounts if acc.get("followerCount")]
if follower_counts:
avg_followers = sum(follower_counts) / len(follower_counts)
common_points.append(f"- 粉丝量级:相似账号平均粉丝{format_number(avg_followers)},处于同一发展阶段")
# 红狐指数分布
redfox_indices = [acc.get("redfoxIndex") for acc in all_accounts if acc.get("redfoxIndex") is not None]
if redfox_indices:
avg_redfox = sum(redfox_indices) / len(redfox_indices)
common_points.append(f"- 红狐指数:相似账号平均{avg_redfox:.1f}")
if common_points:
lines.extend(common_points)
else:
lines.append("- 同赛道账号,内容方向和目标受众有较高重合度")
# --- 差异分析 ---
lines.append("")
lines.append("📊 **差异分析**")
diff_points = []
# 红狐指数差异
if query_redfox_index is not None:
benchmark_redfox = [acc.get("redfoxIndex") for acc in (benchmark_accounts or []) if acc.get("redfoxIndex") is not None]
top_redfox = [acc.get("redfoxIndex") for acc in (top_accounts or []) if acc.get("redfoxIndex") is not None]
if benchmark_redfox:
avg_bench = sum(benchmark_redfox) / len(benchmark_redfox)
diff = avg_bench - query_redfox_index
direction = "高" if diff > 0 else "低"
diff_points.append(f"- 红狐指数差距:对标账号平均{avg_bench:.1f},比你{direction}{abs(diff):.1f}点")
if top_redfox:
max_top = max(top_redfox)
diff = max_top - query_redfox_index
if diff > 0:
diff_points.append(f"- 头部差距:头部标杆最高红狐指数{max_top:.1f},比你高{diff:.1f}点")
elif diff < 0:
diff_points.append(f"- 红狐指数领先:你的红狐指数{query_redfox_index:.1f}已超过头部标杆最高{max_top:.1f},表现优异")
else:
diff_points.append(f"- 红狐指数持平:你的红狐指数与头部标杆最高{max_top:.1f}一致")
if query_avg_play and query_avg_play > 0:
# 对标账号播放量差异
bench_plays = []
for acc in (benchmark_accounts or []):
works = acc.get("works") or []
if works:
avg = sum(w.get("playCount") or 0 for w in works) / len(works)
bench_plays.append(avg)
if bench_plays:
bench_avg = sum(bench_plays) / len(bench_plays)
ratio = bench_avg / query_avg_play
if ratio > 1.3:
diff_points.append(f"- 播放量差距:对标账号均播是你的{ratio:.1f}倍,内容吸引力有提升空间")
elif 0.7 <= ratio <= 1.3:
diff_points.append(f"- 播放量差距:对标账号均播与你接近,竞争激烈需差异化突围")
# 头部播放量差异
top_plays = []
for acc in (top_accounts or []):
works = acc.get("works") or []
if works:
avg = sum(w.get("playCount") or 0 for w in works) / len(works)
top_plays.append(avg)
if top_plays:
top_avg = sum(top_plays) / len(top_plays)
ratio = top_avg / query_avg_play
diff_points.append(f"- 头部差距:头部标杆均播是你的{ratio:.1f}倍,模式成熟可追赶")
# 更新节奏差异
bench_updates = [acc.get("awemeCountSeven") or 0 for acc in (benchmark_accounts or []) if acc.get("awemeCountSeven")]
if bench_updates:
max_update = max(bench_updates)
if max_update >= 7:
diff_points.append(f"- 更新节奏差异:部分对标账号日更(近7天{max_update}条),高频更新是流量基础")
if diff_points:
lines.extend(diff_points)
else:
lines.append("- 建议对比各账号的内容形式、更新节奏和互动策略,找到差异化突破点")
# --- 优化建议 ---
lines.append("")
lines.append("💡 **优化建议**")
suggestions = []
# 基于数据差异给出建议
if benchmark_accounts:
top_bench = max(benchmark_accounts, key=lambda a: a.get("interactiveCountSeven") or 0)
top_update = top_bench.get("awemeCountSeven") or 0
if top_update >= 5:
suggestions.append(f"1. **提升更新频率**:互动量最高的对标账号近7天发布{top_update}条,建议保持稳定更新节奏")
if top_accounts:
top_head = max(top_accounts, key=lambda a: a.get("followerCount") or 0)
high_followers = top_head.get("followerCount") or 0
high_works = top_head.get("works") or []
if high_works:
high_like_rate = _calc_like_rate(high_works)
if high_like_rate and high_like_rate >= 0.03:
suggestions.append(f"2. **优化内容吸引力**:头部标杆点赞率{high_like_rate*100:.1f}%,建议强化开头3秒吸引力和选题热度")
if not suggestions:
suggestions.append("1. **学习对标账号的内容方向和选题策略**,找到适合自己的内容定位")
suggestions.append("2. **参考头部标杆的运营模式**,逐步提升内容质量和更新节奏")
suggestions.append("3. **关注互动率高的账号**,学习其内容形式和互动引导方式")
lines.extend(suggestions)
return "\n".join(lines)
def format_output(current_account, benchmark_accounts, top_accounts, query_avg_play=None, query_redfox_index=None):
"""格式化完整文本输出(适配新版接口)"""
output_lines = []
# 当前账号基本信息(优先使用querySimilarAccounts返回的currentAccount)
if current_account:
output_lines.append(format_account_info(current_account, "查询账号"))
output_lines.append("")
# 匹配结果
bench_count = len(benchmark_accounts) if benchmark_accounts else 0
top_count = len(top_accounts) if top_accounts else 0
tips_parts = []
if bench_count > 0:
tips_parts.append(f"【对标账号({bench_count}个)】")
if top_count > 0:
tips_parts.append(f"【头部账号({top_count}个)】")
if tips_parts:
output_lines.append(f"为你匹配到{'和'.join(tips_parts)}的{len(tips_parts)}组推荐,可按需参考:")
if benchmark_accounts:
total_bench = bench_count + (1 if current_account else 0)
table_title = f"👉【对标账号({total_bench}个)】(红狐指数向上最近的账号,可直接复制玩法)"
output_lines.append(format_table(benchmark_accounts, table_title, query_avg_play, query_redfox_index, current_account))
if top_accounts:
table_title = f"👉【头部账号({top_count}个)】(同分类红狐指数倒序前5,模式成熟可追赶)"
output_lines.append(format_table(top_accounts, table_title, query_avg_play, query_redfox_index))
# 深度分析
analysis = generate_analysis_summary(benchmark_accounts, top_accounts, query_avg_play, query_redfox_index)
if analysis:
output_lines.append(analysis)
else:
output_lines.append("当前未查询到相关对标账号数据。可能原因:1) 账号暂未被平台收录;2) 抖音号或名称输入有误。")
output_lines.append("建议:确认抖音号/名称是否正确后重新查询。")
# 数据说明统一放在末尾
crawl_time = current_account.get("crawlTime") if current_account else None
output_lines.append("")
if crawl_time:
output_lines.append(f"*数据更新时间:{crawl_time}*")
output_lines.append("*红狐指数:每周更新,若统计周期内账号未发布作品,红狐指数可能为0。*")
# 订阅服务提示
account_name = current_account.get("nickname") or account_id if current_account else account_id
output_lines.append("")
output_lines.append(format_subscription_prompt(account_name))
return "\n".join(output_lines)
# ============================================================
# 账号未找到时的收录提示
# ============================================================
def format_account_not_found(account_id):
"""账号未查询到时,输出数据收录提示文案"""
lines = []
lines.append("未查询到当前账号的相关信息,可提交当前抖音账号进行账号收录。")
lines.append("")
lines.append(f"1. 回复抖音号(在抖音个人主页显示的ID,如 {account_id}_1234),即可进行账号收录。30分钟后将自动为您推送相似账号报告~")
lines.append("2. 下次再说;")
return "\n".join(lines)
def format_subscription_prompt(account_name):
"""查询结果末尾输出订阅服务提示文案"""
lines = []
lines.append(f"是否订阅「{account_name}」的相似账号最新信息推送?")
lines.append("")
lines.append("1. 每日下午19点推送最新数据。可自行选择推送频率和时间~")
lines.append("2. 暂不需要")
return "\n".join(lines)
def sync_user_notes(account_id):
"""调用API触发账号数据同步收录
接口文档:POST /dyUser/syncUserNotes
将指定账号加入抖音待同步队列,系统会异步拉取该账号的文章/作品数据。
"""
credential = get_api_key()
url = "https://redfox.hk/story/api/dyUser/syncUserNotes"
headers = {
"Content-Type": "application/json",
"X-API-KEY": credential
}
payload = {
"accountId": account_id,
"source": "抖音相似账号推荐"
}
try:
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(url, data=data, headers=headers, method="POST")
with urllib.request.urlopen(req, timeout=30) as resp:
result = json.loads(resp.read().decode("utf-8")) if resp.read else None
except urllib.error.HTTPError as e:
body = e.read().decode("utf-8", errors="replace")
raise Exception(f"账号收录请求失败: {e.code}, {body}")
except urllib.error.URLError as e:
raise Exception(f"账号收录请求失败: {str(e)}")
return True
# ============================================================
# 主入口
# ============================================================
def main():
parser = argparse.ArgumentParser(description="抖音相似账号推荐脚本")
parser.add_argument("--account_id", help="抖音账号ID或昵称(支持unique_id、short_id、uid、昵称)")
parser.add_argument("--sync", action="store_true", help="触发账号数据收录(用户确认收录时使用)")
args = parser.parse_args()
if not args.account_id:
print("错误:请提供 --account_id 抖音号或昵称")
return
# 用户确认收录:直接调用 syncUserNotes 接口
if args.sync:
try:
sync_user_notes(args.account_id)
print(f"已触发账号收录,30分钟后将自动为您推送相似账号报告~")
except Exception as e:
print(f"账号收录失败: {str(e)}")
return
try:
# 判断输入是昵称还是抖音号/uid
is_likely_nickname = bool(re.search(r'[\u4e00-\u9fff]', args.account_id))
# 直接调用 querySimilarAccounts,支持 accountName 和 accountId 两种方式
if is_likely_nickname:
current_account, benchmark_accounts, top_accounts = query_similar_accounts(accountName=args.account_id)
else:
current_account, benchmark_accounts, top_accounts = query_similar_accounts(accountId=args.account_id)
# 计算当前账号的平均播放量
query_avg_play = None
query_redfox_index = None
if current_account:
works = current_account.get("works") or []
if works:
query_avg_play = sum(w.get("playCount") or 0 for w in works) / len(works)
query_redfox_index = current_account.get("redfoxIndex")
# 格式化输出
result = format_output(current_account, benchmark_accounts, top_accounts, query_avg_play, query_redfox_index)
print(result)
except Exception as e:
error_msg = str(e)
# 账号未找到时,输出收录提示,等用户确认后再触发收录
if "未找到账号" in error_msg:
print(format_account_not_found(args.account_id))
else:
print(f"查询失败: {error_msg}")
if __name__ == "__main__":
main()