Claude Skill

global-ai-news-brief

全球AI新闻简报 — 一个关键词同时搜索抖音、小红书、公众号、B站、快手、视频号、今日头条、TikTok、Instagram、X(Twitter)、YouTube 共 11 大平台,跨平台聚合后由 AI 生成智能摘要、热点聚类、舆情分析和深度解读报告,输出终端表格 + 交互式 HTML 报告。包含详细信息源列表,适用于各种AI agent进行社媒资讯分析。当用户需要新闻搜索、舆情分析、热点追踪、跨平台情报对比、资讯聚合、新闻解读、全网搜索、事件追踪、行业情报时使用。触发词:新闻情报、全网搜索、舆情分析、热点追踪、新闻解读、资讯聚合、跨平台分析、事件追踪、

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download redfox-data-redfox-community-skills_global-ai-news-brief-5e7b435.zip · 22 KB
Part of redfox-data/redfox-community — 66 skills

Install

skills CLI npx skills add https://github.com/redfox-data/redfox-community/tree/main/skills/global-ai-news-brief
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install redfox-data-redfox-community@llmmart
Git git clone https://github.com/redfox-data/redfox-community.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole redfox-data/redfox-community collection as a plugin from our marketplace. Git is the plain clone.

README

全球AI新闻简报 / global-ai-news-brief


简介

输入一个关键词,同时搜索抖音、小红书、公众号、B站、快手、视频号、今日头条、TikTok、Instagram、X(Twitter)、YouTube 共 11 大平台,跨平台聚合数据后由 AI 生成智能摘要、热点聚类、舆情分析和深度解读报告。

核心价值

  • 一次搜索、全网覆盖:一个关键词同时搜遍 11 大平台,无需逐个平台手动翻找
  • 深度情报而非简单罗列:AI 自动聚类热点子话题、提炼关键发现、判断舆情风向
  • 跨平台对比视角:一眼看清各平台关注焦点与解读倾向的差异
  • 双重呈现:终端表格快速浏览 + 可视化报告完整存档

适用对象

  • 📊 市场与舆情分析人员 — 快速掌握事件全貌与情感走向
  • ✍️ 内容创作者 — 一次获取多平台热点素材,辅助选题
  • 📰 媒体与行业研究者 — 跨平台对比解读,获得深度洞察

功能特性

核心功能

  • 全网聚合搜索:一个关键词同时覆盖 11 大平台(含抖音、小红书、公众号、B站、快手、视频号、今日头条、TikTok、Instagram、X(Twitter)、YouTube),也可指定只搜国内 7 大平台
  • 四板块深度报告:新闻事件(概述 + 时间线 + 子话题聚类)、新闻解读(摘要 + 关键发现 + 舆情风向 + KOL)、各平台解读倾向对比、原始数据源,依次完整呈现
  • 智能舆情分析:自动计算全网正面/中性/负面情感占比,提炼核心共识点与争议点,识别关键意见领袖
  • 跨平台对比矩阵:内容数、总互动量、情感倾向、关注焦点、代表观点一表看清各平台差异
  • 可视化报告:自动生成带平台切换、情感仪表盘、对比图表的可视化页面并打开,终端同时输出平台 TOP5 数据表格

密钥获取与安全说明

  • 本技能需要使用环境变量:REDFOX_API_KEY。
  • REDFOX_API_KEY 由 红狐 hub (https://redfox.hk)提供。
  • 请前往 红狐 hub 注册账号,获取 REDFOX_API_KEY。
  • 配置设备环境变量 REDFOX_API_KEY 后使用本技能。
  • 在提供密钥前,请先确认密钥来源、可用范围、有效期及是否支持重置/撤销。
  • 禁止在代码、提示词、日志或输出文件中硬编码/明文暴露密钥。

使用指南

直接用自然语言描述需求,无需记忆命令。

常用说法速查

意图 示例话术 效果
全网舆情查询 帮我查一下"新能源汽车"最新的全网舆情 并行搜索 11 平台,输出终端表格 + 可视化报告
事件追踪 追踪一下"台风"相关的全网信息 侧重时间线和事件传播路径还原
国内平台搜索 只看国内平台,搜一下"暑期旅游" 仅搜索抖音/小红书/公众号/B站/快手/视频号/头条 7 个国内平台

输出示例

一次搜索产出一份完整的深度情报报告,包含:

  • 新闻事件:事件概述卡片、关键时间线、热点子话题聚类
  • 新闻解读:200 字核心摘要、3-5 条关键发现、舆情风向(正面/中性/负面占比)、关键意见领袖
  • 各平台解读倾向:跨平台对比矩阵表 + 情感对比图表
  • 数据源:各平台完整数据,含封面、标题、作者、互动数据与原文链接

使用场景

场景 角色 示例问法 收益
热点追踪 内容创作者、媒体人 查一下"新能源汽车"全网舆情 一次看全 11 平台,快速掌握热点全貌
舆情分析 市场、公关人员 追踪"台风"相关全网信息 获得时间线、情感分布、共识点与争议点
行业情报 分析师、运营人员 只看国内平台,搜一下"暑期旅游" 跨平台对比矩阵,洞察各平台关注差异

Skill manifest

全球AI新闻简报

输入一个关键词,同时发起 11 大平台搜索请求,跨平台聚合数据后由 AI 生成深度情报报告。

覆盖平台

# 平台 接口路径 搜索参数 排序选项
1 抖音 /story/api/dy/data/searchWork keyword, pageNum, pageSize —
2 小红书 /story/api/xhsUser/searchArticle keyword, offset, sortType 0=默认/2=最新/4=最热
3 公众号 /story/api/gzh/data/searchArticle keyword, offset, sortType 0=默认/2=最新/4=最热
4 B站 /story/api/bili/data/workSearch keyword, page, pageSize, order time/play/like/comment/favorite
5 快手 /story/api/ksAllData/searchWork keyword, page, size, sort 综合/最新/最多点赞/最多收藏
6 视频号 /story/api/sphAllData/searchWork keyword, sort, page, size 综合/最新/最多点赞/最多收藏
7 今日头条 /story/api/toutiao/searchWork keyword, offset —
8 TikTok /story/api/tiktok/ability/searchVideo keyword, offset, count, sortType, publishTime, region 0=相关度/1=最多点赞
9 Instagram /story/api/ins/search keyword, paginationToken —
10 X(Twitter) /story/api/x/search keyword, searchType, cursor Top/Latest/Media
11 YouTube /story/api/youtube/searchVideo searchQuery, continuationToken —

所有接口 Host: https://redfox.hk,Method: POST,Content-Type: application/json,鉴权方式见下方「🔑 鉴权」。 详细请求/响应字段见 api-reference.md。

🔑 鉴权

获取 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..."

所有平台接口的请求头均携带 REDFOX-API-KEY + X-API-Key(值均为 $REDFOX_API_KEY),缺失时脚本报错退出并提示配置。

工作流程

Step 1:关键词处理

  • 用户输入的关键词直接作为搜索词
  • 若输入含"达人""博主""KOL""网红""账号"等后缀,自动剥离后缀仅保留核心语义词
  • 可询问用户是否需要指定平台范围(默认全部 11 个平台)

Step 2:并行数据采集

使用脚本 scripts/fetch_all.py 一键并行采集(内部用线程池并发请求全部平台):

python3 ~/.agents/skills/global-ai-news-brief/scripts/fetch_all.py "关键词" --pretty
  • 前置条件:环境变量 REDFOX_API_KEY 已设置(脚本会检测,缺失时报错退出)
  • 默认行为:并行请求全部 11 个平台,每个平台取首页数据(20条)
  • 指定平台子集:--platforms douyin,xhs,gzh,bilibili,kuaishou,shipinhao,toutiao(仅搜国内平台时用)
  • 输出:标准化 JSON 写入 /tmp/news_intel_result.json,同时在 stderr 打印各平台采集状态
  • 容错:单平台失败自动跳过,在结果的 failedPlatforms 字段中标注,不影响其他平台

输出 JSON 结构:

{
  keyword: string,          // 搜索关键词
  generatedAt: string,      // 生成时间
  platformCount: number,    // 成功平台数
  failedPlatforms: [],      // 失败平台列表 [{platform, error}]
  totalItems: number,       // 总内容条数
  totalEngagement: number,  // 总互动量(点赞+评论+分享+播放)
  results: {                // 按平台 key 分组
    douyin: { platform, count, total, items[] },
    ...
  }
}

每个 items[] 条目已由脚本标准化为统一结构(见 Step 3),Agent 直接读取 JSON 文件做分析即可,无需再处理各平台字段名差异。

Step 3:数据标准化

将各平台返回数据统一为以下标准结构:

{
  platform: string,     // 平台名称
  title: string,        // 标题/描述首行
  content: string,      // 正文/描述
  author: string,       // 作者昵称
  url: string,          // 作品链接
  publishTime: string,  // 发布时间
  likes: number,        // 点赞数
  comments: number,     // 评论数
  shares: number,       // 分享/转发数
  views: number,        // 播放/阅读数
  collects: number,     // 收藏数
  followers: number,    // 作者粉丝数
  coverUrl: string,     // 封面图
  mediaType: string     // video/image/text
}

字段映射要点(处理各平台字段名差异):

标准字段 抖音 小红书 公众号 B站 快手 视频号 头条 TikTok Instagram X YouTube
title content workTitle title title caption description title content captionText text title
author authorName accountNickname author author nickname nickname nickname authorData.userName user.fullName user.displayName author
likes likeCount workLikedCount likeCount likeCount likeCount likeCount — statsData.likeCount likeCount likeCount —
comments commentCount workCommentsCount commentCount commentCount commentCount commentCount commentNum statsData.commentTotal commentCount replyCount —
views — — readCount playCount viewCount — — statsData.viewCount playCount viewCount viewCount
url opusUrl workUrl workUrl 拼接BV 拼接photoId — opusUrl shareLink 拼接code 拼接tweetId 拼接videoId

Step 4:AI 智能分析与输出

对聚合后的全部数据执行分析,严格按以下四个板块依次输出(终端和 HTML 报告均遵循此顺序):


板块一:新闻事件

还原"发生了什么"——客观呈现事件全貌。

  • 事件概述:用 3-5 句话概括核心事件(谁、什么、何时、何地、影响范围)
  • 关键事件时间线:按发布时间排列关键节点,还原事件从萌芽到发酵的传播路径;排序规则:最新时间在最上面(倒序),无明确日期的条目(如「海外长线」)排在最后
  • 热点话题聚类:将全部内容按主题自动聚类为 3-8 个热点话题,每个话题标注:
    • 主题名称
    • 涉及平台数
    • 代表内容 2-3 条(含标题、作者、平台、链接)

板块二:新闻解读

AI 深度分析"意味着什么"——提炼洞察与判断。

  • 核心摘要:200 字以内的精炼总结,包含事件定性、影响评估、趋势预判
  • 关键发现:3-5 条核心洞察,每条包含论点 + 数据支撑
  • 舆情风向:
    • 全网情感分布:正面 / 中性 / 负面占比
    • 核心共识点(多数人认同的观点)
    • 核心争议点(分歧最大的议题)
  • 大V观点(KOL):识别粉丝量 > 10000 或单条互动量 TOP 的作者,列出作者名、平台、粉丝数、代表观点;标题统一使用通俗说法「大V观点」,不使用「关键意见领袖」。账号名渲染为可点击链接跳转作者主页,主页链接拼接规则(从作品链接或接口字段提取作者 ID 拼接):
    • X/Twitter:https://x.com/{username}(从作品 url /status/ 前段提取)
    • TikTok:https://www.tiktok.com/@{username}(从作品 url /@xxx/ 段提取)
    • Instagram:https://www.instagram.com/{username}/
    • B站:https://space.bilibili.com/{mid}(接口无 mid 时回退 https://search.bilibili.com/all?keyword={作者名})
    • 公众号:https://open.weixin.qq.com/qr/code?username={biz}
    • 快手/小红书等无法提取作者 ID 的平台:回退平台搜索链接(如 https://www.kuaishou.com/search/video?searchKey={作者名})
    • 视频号无公开主页链接:不渲染链接

板块三:各平台不同的解读倾向

跨平台对比"各平台怎么看"——揭示平台差异化特征。

对每个有数据的平台分析以下维度:

分析维度 说明
情感倾向 该平台正面/中性/负面比例,与全网均值对比
关注焦点 该平台用户最关注的子话题/角度(与其他平台的差异点)
内容形态 以视频/图文/长文哪种为主
热度指标 内容条数、总互动量、平均互动量
代表声音 该平台互动量最高的 2-3 条内容及观点摘要

输出为跨平台对比矩阵表:

| 平台 | 内容数 | 总互动 | 情感倾向 | 关注焦点 | 代表观点 |
|------|-------|-------|---------|---------|---------|
| 抖音 | 20 | 58000 | 正面65% | 事件现场视频 | "xxx" |
| 公众号 | 18 | 120000 | 中性55% | 深度分析文章 | "xxx" |
| X/Twitter | 15 | 9200 | 负面60% | 批评与讨论 | "xxx" |

板块四:数据源

原始数据完整展示——按平台分段列出全部搜索结果。

终端输出:每个平台展示 TOP 5 表格:

### 抖音 TOP 5

| # | 标题 | 作者 | 点赞 | 评论 | 分享 | 发布时间 | 链接 |
|---|------|------|------|------|------|---------|------|
| 1 | xxx | xxx | 8000 | 280 | 150 | 2026-05-20 | [查看](url) |

HTML 报告:每个平台一个可切换 Tab,展示该平台全部数据条目,含封面图、标题、作者、完整数据指标、原文链接。

数据时间范围标注:数据源标题(h2「四、数据源」)后以 .formula-note 小字标注实际数据时间范围,如「(数据时间范围:2026-07-20 ~ 2026-08-19 为主体近30天数据,含少量历史旧闻,最早 2024-07-02)」。计算规则:

  • 解析全部条目的 publishTime(兼容三种格式:YYYY-MM-DD...、X/Twitter 的 %a %b %d %H:%M:%S +0000 %Y、相对时间 N days/weeks/months ago(以采集日为基准推算)),取最小/最大日期
  • 口径:报告当前时间前 30 天为主体窗口,若 90% 以上条目落在此窗口,文案注明「主体近30天(起始日期 ~ 最晚日期)」;窗口外的更早条目计为「历史旧闻」,注明最早日期

Step 5:HTML 报告生成

使用 assets/report-template.html 模板生成交互式 HTML 报告,严格按四大板块组织:

  1. 顶部概览:subtitle 行展示搜索关键词、覆盖平台数、总内容条数、数据时间范围(短格式「YYYY-MM-DD ~ YYYY-MM-DD」,长说明在数据源标题后);概览卡片区仅 4 张卡(覆盖平台/内容总数/总互动量/活跃平台);生成时间只出现在页面底部 footer
  2. 板块一 · 新闻事件:事件概述卡片 + 垂直时间轴 + 热点话题标签云 + 热点话题详情卡片(.topic-list 网格 + .topic-card 卡片样式,卡头带蓝色小方块装饰 + 话题名 + 平台数,正文为项目符号列表)
  3. 板块二 · 新闻解读:核心摘要区 + 关键发现列表 + 舆情风向仪表盘(正面/中性/负面进度条)+ 大V观点卡片
  4. 板块三 · 各平台解读倾向:跨平台对比矩阵表 + 各平台情感对比柱状图(CSS 实现,标题后以 .formula-note 小字标注计算公式「互动量 = 点赞 + 评论 + 分享 + 播放」)+ 差异亮点
  5. 板块四 · 数据源:平台 Tab 切换器,每个 Tab 内展示该平台全部内容卡片(封面、标题、作者、指标、链接)。Tab 排序规则:按平台互动量(点赞+评论+分享+播放)降序排列,互动量最高的平台排最前;Tab 内条目保持接口返回原始顺序,不做二次排序

封面展示规则:

  • 接口不返回封面的平台(如今日头条):该平台所有卡片不渲染封面区域,直接从正文开始(生成时检测:平台内全部条目 coverUrl 为空即视为无封面平台)
  • 其他平台封面为空时:渲染固定高度(180px)白色背景占位块,保证卡片高度统一
  • 封面加载失败(onerror):移除 src 保留白色占位块,不隐藏不塌陷

对话输出:报告中生成的所有关键标注必须同步展示在对话回复中,包括:

  • 数据时间范围(短格式 + 主体占比/历史旧闻说明)
  • 互动量计算公式口径:互动量 = 点赞 + 评论 + 分享 + 播放(接口不返回播放量的平台按 0 计)
  • 各平台数据统计、互动排名、报告文件路径

HTML 文件保存到本 Skill 的 output/ 目录,文件名 global-ai-news-brief-report-{keyword}-{date}.html(目录不存在时先创建),用 open 命令打开。禁止保存到 /tmp 等临时目录。

错误处理

  • 某个平台请求失败时跳过该平台并在报告中标注"数据暂不可用"
  • 不阻断其他平台数据采集
  • API 密钥缺失时提示用户设置 REDFOX_API_KEY 环境变量

使用示例

用户:帮我查一下"新能源汽车"最新的全网舆情
Agent:→ 并行搜索 11 平台 → 聚合数据 → AI 分析 → 输出终端表格 + HTML 报告

用户:追踪一下"台风"相关的全网信息
Agent:→ 同上流程,侧重时间线和事件追踪

用户:只看国内平台,搜一下"暑期旅游"
Agent:→ 仅搜索抖音/小红书/公众号/B站/快手/视频号/头条 7 个国内平台
Files (redfox-community)
  • assets
    • report-template.html 12.4 KB · in bundle
  • references
    • api-reference.md 10.9 KB
      # API 接口参考
      
      所有接口统一规范:
      - **Host**: `https://redfox.hk`
      - **Method**: `POST`
      - **Content-Type**: `application/json`
      - **认证头**: `REDFOX-API-KEY` + `X-API-Key`(值均为 `$REDFOX_API_KEY`)
      - **成功状态码**: `code: 2000`
      
      ---
      
      ## 1. 抖音(广域库)
      
      **Path**: `/story/api/dy/data/searchWork`
      
      **请求体**:
      ```json
      {"keyword": "关键词", "pageNum": 1, "pageSize": 20}
      ```
      - `keyword`: 搜索关键词(必填,匹配作品正文)
      - `pageNum`: 页码,从1开始,默认1
      - `pageSize`: 每页大小,默认10,最大50
      
      **响应**: `data.list[]`,另有 `data.total`(总记录数)
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | videoId | String | 作品ID |
      | content | String | 作品正文/描述 |
      | videoType | String | 0=普通视频, 68=图集, 63=直播录屏等 |
      | duration | Integer | 时长(毫秒) |
      | publishTime | String | 发布时间 |
      | coverUrl | String | 封面链接 |
      | opusUrl | String | 作品链接 |
      | imageUrlList | Array | 图片列表(图文作品) |
      | tagList | Array | 话题列表 |
      | likeCount | Integer | 点赞数 |
      | commentCount | Integer | 评论数 |
      | shareCount | Integer | 分享数 |
      | collectCount | Integer | 收藏数 |
      | authorUid | String | 作者ID |
      | authorName | String | 作者昵称 |
      | authorAvatarUrl | String | 作者头像 |
      | authorShortId | String | 作者抖音short_id |
      | authorUniqueId | String | 作者抖音unique_id |
      | authorSecUid | String | 作者sec_uid |
      
      **URL 构造**: `opusUrl` 即为完整链接
      
      ---
      
      ## 2. 小红书(优质库)
      
      **Path**: `/story/api/xhsUser/searchArticle`
      
      **请求体**:
      ```json
      {"keyword": "关键词", "offset": 0, "sortType": "0"}
      ```
      - `sortType`: `0`=默认, `2`=最新, `4`=最热
      - `offset`: 从0开始,每页+20
      
      **响应**: `data.list[]`
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | workId | String | 作品ID |
      | workTitle | String | 标题 |
      | workDesc | String | 内容 |
      | coverUrl | String | 封面图 |
      | workUrl | String | 作品链接 |
      | workPublishTime | String | 发布时间 |
      | accountNickname | String | 作者昵称 |
      | accountUserid | String | 作者ID |
      | workLikedCount | Integer | 点赞数 |
      | workCommentsCount | Integer | 评论数 |
      | workCollectedCount | Integer | 收藏数 |
      | workSharedCount | Integer | 转发数 |
      | workType | String | video/normal |
      
      **URL 构造**: `workUrl` 即为完整链接
      
      ---
      
      ## 3. 公众号(广域库)
      
      **Path**: `/story/api/gzh/data/searchArticle`
      
      **请求体**:
      ```json
      {"keyword": "关键词", "offset": 0, "sortType": "0"}
      ```
      - `sortType`: `0`=默认, `2`=最新, `4`=最热
      - `offset`: 从0开始,每页+20
      
      **响应**: `data.list[]`
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | title | String | 标题 |
      | summary | String | 摘要 |
      | content | String | 正文HTML |
      | workUrl | String | 文章链接 |
      | coverUrl | String | 封面链接 |
      | publishTime | String | 发布时间 |
      | readCount | Integer | 阅读数 |
      | likeCount | Integer | 点赞数 |
      | watchCount | Integer | 在看数 |
      | commentCount | Integer | 评论数 |
      | collectCount | Integer | 收藏数 |
      | shareCount | Integer | 分享数 |
      | author | String | 账号昵称 |
      | isOriginal | Integer | 1=原创 |
      | orderNum | Integer | 0=头条 |
      | originalAuthor | String | 原创作者 |
      | authorAvatarUrl | String | 头像链接 |
      | workUuid | String | 作品ID |
      
      ---
      
      ## 4. B站(优质库)
      
      **Path**: `/story/api/bili/data/workSearch`
      
      **请求体**:
      ```json
      {"keyword": "关键词", "page": "1", "pageSize": 20, "order": "time"}
      ```
      - `order`: `time`=最新, `play`=播放数, `like`=点赞, `comment`=评论, `favorite`=收藏
      
      **响应**: `data.workList[]`
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | bvId | String | BV号 |
      | title | String | 标题 |
      | description | String | 描述 |
      | duration | Integer | 时长(秒) |
      | picUrl | String | 封面 |
      | created | String | 发布时间 |
      | author | String | 作者 |
      | authorId | String | 作者ID |
      | firstType | String | 一级分类 |
      | secondType | String | 二级分类 |
      | playCount | Integer | 播放数 |
      | likeCount | Integer | 点赞数 |
      | favoriteCount | Integer | 收藏数 |
      | commentCount | Integer | 评论数 |
      | shareCount | Integer | 分享数 |
      | videoReview | Integer | 弹幕数 |
      | coinCount | Integer | 投币数 |
      | interactionQuantity | Integer | 互动数 |
      | tagNames | Array | 标签 |
      
      **URL 构造**: `https://www.bilibili.com/video/{bvId}`
      
      ---
      
      ## 5. 快手(广域库)
      
      **Path**: `/story/api/ksAllData/searchWork`
      
      **请求体**:
      ```json
      {"keyword": "关键词", "page": 1, "size": 20, "sort": "综合"}
      ```
      - `sort`: `综合`/`最新`/`最多点赞`/`最多收藏`
      - `size`: 最大50
      
      **响应**: `data.list[]`
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | photoId | String | 作品ID |
      | caption | String | 标题 |
      | nickname | String | 作者 |
      | headUrl | String | 头像 |
      | coverUrl | String | 封面 |
      | videoUrl | String | 视频URL |
      | publishTime | String | 发布时间 |
      | duration | Integer | 时长(毫秒) |
      | viewCount | Integer | 播放数 |
      | likeCount | Integer | 点赞数 |
      | commentCount | Integer | 评论数 |
      | collectCount | Integer | 收藏数 |
      | shareCount | Integer | 分享数 |
      | forwardCount | Integer | 转发数 |
      | authorFans | Integer | 粉丝数 |
      
      **URL 构造**: `https://www.kuaishou.com/short-video/{photoId}`
      
      ---
      
      ## 6. 视频号(广域库)
      
      **Path**: `/story/api/sphAllData/searchWork`
      
      **请求体**:
      ```json
      {"keyword": "关键词", "page": 1, "size": 20, "sort": "综合"}
      ```
      - `sort`: `综合`/`最新`/`最多点赞`/`最多收藏`
      
      **响应**: `data.list[]`
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | description | String | 作品描述 |
      | nickname | String | 账号昵称 |
      | headUrl | String | 头像 |
      | coverUrl | String | 封面 |
      | thumbUrl | String | 缩略图 |
      | videoUrl | String | 视频URL |
      | publishTime | String | 发布时间 |
      | videoDuration | String | 时长(秒) |
      | likeCount | Integer | 点赞数 |
      | commentCount | Integer | 评论数 |
      | forwardCount | Integer | 转发数 |
      | favCount | Integer | 收藏数 |
      | topic | String | 话题JSON数组 |
      | width/height | Integer | 分辨率 |
      
      ---
      
      ## 7. 今日头条(实时)
      
      **Path**: `/story/api/toutiao/searchWork`
      
      **请求体**:
      ```json
      {"keyword": "关键词", "offset": "0"}
      ```
      - `offset`: 从"0"开始,每页+1
      
      **响应**: `data[]`(注意:data 是数组,非对象)
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | opusId | String | 作品ID |
      | opusUrl | String | 作品链接 |
      | title | String | 标题 |
      | nickname | String | 作者昵称 |
      | uid | String | 作者UID |
      | publishTime | String | 秒级时间戳 |
      | commentNum | Integer | 评论数 |
      | hasNext | Boolean | 是否有下一页 |
      | pageCount | Integer | 每页条数 |
      
      ---
      
      ## 8. TikTok
      
      **Path**: `/story/api/tiktok/ability/searchVideo`
      
      **请求体**:
      ```json
      {"keyword": "关键词", "offset": "0", "count": "20", "sortType": "0", "publishTime": "0", "region": "US"}
      ```
      - `sortType`: `0`=相关度, `1`=最多点赞
      - `publishTime`: `0`=不限, `1`=一天内, `7`=一周, `30`=一月, `90`=三月, `180`=半年
      - `region`: ISO 3166-1 alpha-2 代码,默认 `US`
      
      **响应**: `data[]`(注意:data 是数组)
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | workId | String | 作品ID |
      | content | String | 作品描述 |
      | mediaType | String | video/photo |
      | publishTime | Integer | 秒级时间戳 |
      | shareLink | String | 分享链接 |
      | authorData.userName | String | 作者昵称 |
      | authorData.userHandle | String | 作者handle |
      | authorData.fansCount | Integer | 粉丝数 |
      | authorData.avatarImage | String | 头像 |
      | statsData.viewCount | Integer | 播放数 |
      | statsData.likeCount | Integer | 点赞数 |
      | statsData.commentTotal | Integer | 评论数 |
      | statsData.shareTotal | Integer | 分享数 |
      | statsData.favoriteCount | Integer | 收藏数 |
      | statsData.repostTotal | Integer | 转载数 |
      | videoData.coverImage | String | 封面 |
      | videoData.playAddress | String | 播放地址 |
      | videoData.downloadNoMarkAddress | String | 无水印下载 |
      | videoData.playDuration | Integer | 时长(毫秒) |
      
      ---
      
      ## 9. Instagram
      
      **Path**: `/story/api/ins/search`
      
      **请求体**:
      ```json
      {"keyword": "关键词"}
      ```
      - 可选 `paginationToken` 翻页
      
      **响应**: `data.items[]`
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | mediaId | String | 媒体ID |
      | code | String | 短码(拼接链接用) |
      | captionText | String | 正文 |
      | captionHashtags | Array | 标签 |
      | mediaFormat | String | video/image/album |
      | mediaType | Integer | 1=图片,2=视频,8=轮播 |
      | imageUrl | String | 封面图 |
      | thumbnailUrl | String | 缩略图 |
      | videoUrl | String | 视频URL(图片时为null) |
      | videoDuration | Double | 时长(秒) |
      | playCount | Integer | 播放数 |
      | likeCount | Integer | 点赞数 |
      | commentCount | Integer | 评论数 |
      | shareCount | Integer | 分享数 |
      | takenAt | Integer | 秒级时间戳 |
      | takenAtDate | String | ISO 8601 时间 |
      | user.username | String | 用户名 |
      | user.fullName | String | 显示名 |
      | user.followerCount | Integer | 粉丝数 |
      | user.profilePicUrl | String | 头像 |
      | user.isVerified | Boolean | 是否认证 |
      
      **URL 构造**: `https://www.instagram.com/p/{code}/`
      
      ---
      
      ## 10. X (Twitter)
      
      **Path**: `/story/api/x/search`
      
      **请求体**:
      ```json
      {"keyword": "关键词", "searchType": "Top"}
      ```
      - `searchType`: `Top`/`Latest`/`Media`/`People`/`Lists`
      - `cursor`: 翻页游标
      
      **响应**: `data.tweets[]`
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | tweetId | String | 推文ID |
      | text | String | 正文内容 |
      | createdAt | String | 发布时间 |
      | language | String | 语言 |
      | likeCount | Integer | 点赞数 |
      | retweetCount | Integer | 转推数 |
      | replyCount | Integer | 回复数 |
      | quoteCount | Integer | 引用数 |
      | bookmarkCount | Integer | 收藏数 |
      | viewCount | String | 浏览量 |
      | username | String | 作者用户名 |
      | user.displayName | String | 显示名 |
      | user.followers | Integer | 粉丝数 |
      | user.avatar | String | 头像 |
      | user.verified | Boolean | 是否认证 |
      | medias[] | Array | 媒体附件 |
      | medias[].type | String | video/photo |
      | medias[].coverUrl | String | 媒体封面 |
      | medias[].variants[] | Array | 视频清晰度列表 |
      
      **URL 构造**: `https://x.com/{username}/status/{tweetId}`
      
      ---
      
      ## 11. YouTube
      
      **Path**: `/story/api/youtube/searchVideo`
      
      **请求体**:
      ```json
      {"searchQuery": "关键词"}
      ```
      - 注意参数名为 `searchQuery` 而非 `keyword`
      - 可选 `continuationToken` 翻页
      
      **响应**: `data.videos[]`
      | 字段 | 类型 | 说明 |
      |------|------|------|
      | videoId | String | 视频ID |
      | title | String | 标题 |
      | description | String | 描述 |
      | author | String | 频道名 |
      | channelId | String | 频道ID |
      | duration | String | 时长(如 "35:38") |
      | publishedTime | String | 发布时间 |
      | viewCount | Integer | 播放量 |
      | thumbnails[] | Array | 缩略图 |
      | thumbnails[].url | String | 缩略图URL |
      
      **URL 构造**: `https://www.youtube.com/watch?v={videoId}`
      
  • scripts
    • fetch_all.py 16.2 KB
      #!/usr/bin/env python3
      """
      全球AI新闻简报 — 数据采集脚本
      并行请求 11 大平台搜索接口,统一标准化后输出 JSON。
      
      用法:
          python3 fetch_all.py "关键词" [--output /tmp/result.json] [--platforms douyin,xhs,gzh]
      
      依赖: 仅 Python 标准库 (urllib + concurrent.futures),无需 pip 安装
      环境变量: REDFOX_API_KEY (红狐 API 密钥)
      """
      
      import argparse
      import concurrent.futures
      import json
      import os
      import sys
      import time
      import urllib.error
      import urllib.request
      
      HOST = "https://redfox.hk"
      TIMEOUT = 30
      
      # ---------------------------------------------------------------- 平台定义
      # name: 平台名; path: 接口路径; body: 请求体模板; list_key: 响应中列表的定位路径
      PLATFORMS = {
          "douyin": {
              "name": "抖音",
              "path": "/story/api/dy/data/searchWork",
              "body": {"keyword": "{kw}", "pageNum": 1, "pageSize": 20},
              "list_key": ["data", "list"],
          },
          "xiaohongshu": {
              "name": "小红书",
              "path": "/story/api/xhsUser/searchArticle",
              "body": {"keyword": "{kw}", "offset": 0, "sortType": "0"},
              "list_key": ["data", "list"],
          },
          "wechat_gzh": {
              "name": "公众号",
              "path": "/story/api/gzh/data/searchArticle",
              "body": {"keyword": "{kw}", "offset": 0, "sortType": "0"},
              "list_key": ["data", "list"],
          },
          "bilibili": {
              "name": "B站",
              "path": "/story/api/bili/data/workSearch",
              "body": {"keyword": "{kw}", "page": "1", "pageSize": 20, "order": "time"},
              "list_key": ["data", "workList"],
          },
          "kuaishou": {
              "name": "快手",
              "path": "/story/api/ksAllData/searchWork",
              "body": {"keyword": "{kw}", "page": 1, "size": 20, "sort": "综合"},
              "list_key": ["data", "list"],
          },
          "shipinhao": {
              "name": "视频号",
              "path": "/story/api/sphAllData/searchWork",
              "body": {"keyword": "{kw}", "page": 1, "size": 20, "sort": "综合"},
              "list_key": ["data", "list"],
          },
          "toutiao": {
              "name": "今日头条",
              "path": "/story/api/toutiao/searchWork",
              "body": {"keyword": "{kw}", "offset": "0"},
              "list_key": ["data"],  # data 直接是数组
          },
          "tiktok": {
              "name": "TikTok",
              "path": "/story/api/tiktok/ability/searchVideo",
              "body": {"keyword": "{kw}", "offset": "0", "count": "20", "sortType": "0", "publishTime": "0"},
              "list_key": ["data"],  # data 直接是数组
          },
          "instagram": {
              "name": "Instagram",
              "path": "/story/api/ins/search",
              "body": {"keyword": "{kw}"},
              "list_key": ["data", "items"],
          },
          "x_twitter": {
              "name": "X(Twitter)",
              "path": "/story/api/x/search",
              "body": {"keyword": "{kw}", "searchType": "Top"},
              "list_key": ["data", "tweets"],
          },
          "youtube": {
              "name": "YouTube",
              "path": "/story/api/youtube/searchVideo",
              "body": {"searchQuery": "{kw}"},  # 注意参数名为 searchQuery
              "list_key": ["data", "videos"],
          },
      }
      
      # ---------------------------------------------------------------- 平台专属映射函数
      # 每个函数输入原始条目 dict,输出标准化 dict
      
      
      def norm_douyin(i):
          vt = str(i.get("videoType", ""))
          return {
              "title": i.get("content", ""),
              "content": i.get("content", ""),
              "author": i.get("authorName", ""),
              "url": i.get("opusUrl", ""),
              "publishTime": i.get("publishTime", ""),
              "likes": i.get("likeCount", 0) or 0,
              "comments": i.get("commentCount", 0) or 0,
              "shares": i.get("shareCount", 0) or 0,
              "views": None,
              "collects": i.get("collectCount", 0) or 0,
              "followers": None,
              "coverUrl": i.get("coverUrl", ""),
              "mediaType": "image" if vt == "68" else "video",
          }
      
      
      def norm_xiaohongshu(i):
          return {
              "title": i.get("workTitle", ""),
              "content": i.get("workDesc", ""),
              "author": i.get("accountNickname", ""),
              "url": i.get("workUrl", ""),
              "publishTime": i.get("workPublishTime", ""),
              "likes": i.get("workLikedCount", 0) or 0,
              "comments": i.get("workCommentsCount", 0) or 0,
              "shares": i.get("workSharedCount", 0) or 0,
              "views": None,
              "collects": i.get("workCollectedCount", 0) or 0,
              "followers": None,
              "coverUrl": i.get("coverUrl", ""),
              "mediaType": "video" if "video" in str(i.get("workType", "")) else "image",
          }
      
      
      def norm_wechat_gzh(i):
          return {
              "title": i.get("title", ""),
              "content": i.get("summary", ""),
              "author": i.get("author", ""),
              "url": i.get("workUrl", ""),
              "publishTime": i.get("publishTime", ""),
              "likes": i.get("likeCount", 0) or 0,
              "comments": i.get("commentCount", 0) or 0,
              "shares": i.get("shareCount", 0) or 0,
              "views": i.get("readCount", 0) or 0,
              "collects": i.get("collectCount", 0) or 0,
              "followers": None,
              "coverUrl": i.get("coverUrl", ""),
              "mediaType": "text",
          }
      
      
      def norm_bilibili(i):
          bv = i.get("bvId", "")
          return {
              "title": i.get("title", ""),
              "content": i.get("description", ""),
              "author": i.get("author", ""),
              "url": f"https://www.bilibili.com/video/{bv}" if bv else "",
              "publishTime": i.get("created", ""),
              "likes": i.get("likeCount", 0) or 0,
              "comments": i.get("commentCount", 0) or 0,
              "shares": i.get("shareCount", 0) or 0,
              "views": i.get("playCount", 0) or 0,
              "collects": i.get("favoriteCount", 0) or 0,
              "followers": None,
              "coverUrl": i.get("picUrl", ""),
              "mediaType": "video",
          }
      
      
      def norm_kuaishou(i):
          pid = i.get("photoId", "")
          return {
              "title": i.get("caption", ""),
              "content": i.get("caption", ""),
              "author": i.get("nickname", ""),
              "url": f"https://www.kuaishou.com/short-video/{pid}" if pid else "",
              "publishTime": i.get("publishTime", ""),
              "likes": i.get("likeCount", 0) or 0,
              "comments": i.get("commentCount", 0) or 0,
              "shares": i.get("shareCount", 0) or 0,
              "views": i.get("viewCount", 0) or 0,
              "collects": i.get("collectCount", 0) or 0,
              "followers": i.get("authorFans", 0) or 0,
              "coverUrl": i.get("coverUrl", ""),
              "mediaType": "video",
          }
      
      
      def norm_shipinhao(i):
          return {
              "title": i.get("description", ""),
              "content": i.get("description", ""),
              "author": i.get("nickname", ""),
              "url": i.get("videoUrl", ""),
              "publishTime": i.get("publishTime", ""),
              "likes": i.get("likeCount", 0) or 0,
              "comments": i.get("commentCount", 0) or 0,
              "shares": i.get("forwardCount", 0) or 0,
              "views": None,
              "collects": i.get("favCount", 0) or 0,
              "followers": None,
              "coverUrl": i.get("coverUrl", "") or i.get("thumbUrl", ""),
              "mediaType": "video",
          }
      
      
      def norm_toutiao(i):
          return {
              "title": i.get("title", ""),
              "content": "",
              "author": i.get("nickname", ""),
              "url": i.get("opusUrl", ""),
              "publishTime": _ts_to_str(i.get("publishTime")),
              "likes": None,
              "comments": i.get("commentNum", 0) or 0,
              "shares": None,
              "views": None,
              "collects": None,
              "followers": None,
              "coverUrl": "",
              "mediaType": "text",
          }
      
      
      def norm_tiktok(i):
          author = i.get("authorData") or {}
          stats = i.get("statsData") or {}
          video = i.get("videoData") or {}
          return {
              "title": i.get("content", ""),
              "content": i.get("content", ""),
              "author": author.get("userName", ""),
              "url": i.get("shareLink", ""),
              "publishTime": _ts_to_str(i.get("publishTime")),
              "likes": stats.get("likeCount", 0) or 0,
              "comments": stats.get("commentTotal", 0) or 0,
              "shares": stats.get("shareTotal", 0) or 0,
              "views": stats.get("viewCount", 0) or 0,
              "collects": stats.get("favoriteCount", 0) or 0,
              "followers": author.get("fansCount", 0) or 0,
              "coverUrl": video.get("coverImage", ""),
              "mediaType": "video" if i.get("mediaType") == "video" else "image",
          }
      
      
      def norm_instagram(i):
          code = i.get("code", "")
          user = i.get("user") or {}
          return {
              "title": i.get("captionText", ""),
              "content": i.get("captionText", ""),
              "author": user.get("username", "") or user.get("fullName", ""),
              "url": f"https://www.instagram.com/p/{code}/" if code else "",
              "publishTime": i.get("takenAtDate", "") or _ts_to_str(i.get("takenAt")),
              "likes": i.get("likeCount", 0) or 0,
              "comments": i.get("commentCount", 0) or 0,
              "shares": i.get("shareCount", 0) or 0,
              "views": i.get("playCount", 0) or 0,
              "collects": None,
              "followers": user.get("followerCount", 0) or 0,
              "coverUrl": i.get("imageUrl", "") or i.get("thumbnailUrl", ""),
              "mediaType": {"video": "video", "image": "image", "album": "image"}.get(i.get("mediaFormat", ""), "image"),
          }
      
      
      def norm_x_twitter(i):
          user = i.get("user") or {}
          username = user.get("username", "") or i.get("username", "")
          tweet_id = i.get("tweetId", "")
          medias = i.get("medias") or []
          first_media = medias[0] if medias else {}
          media_type = first_media.get("type", "") if first_media else ""
          return {
              "title": i.get("text", ""),
              "content": i.get("text", ""),
              "author": user.get("displayName", "") or username,
              "url": f"https://x.com/{username}/status/{tweet_id}" if username and tweet_id else "",
              "publishTime": i.get("createdAt", ""),
              "likes": i.get("likeCount", 0) or 0,
              "comments": i.get("replyCount", 0) or 0,
              "shares": i.get("retweetCount", 0) or 0,
              "views": _to_int(i.get("viewCount")),
              "collects": i.get("bookmarkCount", 0) or 0,
              "followers": user.get("followers", 0) or 0,
              "coverUrl": first_media.get("coverUrl", ""),
              "mediaType": media_type or "text",
          }
      
      
      def norm_youtube(i):
          vid = i.get("videoId", "")
          thumbs = i.get("thumbnails") or []
          return {
              "title": i.get("title", ""),
              "content": i.get("description", ""),
              "author": i.get("author", ""),
              "url": f"https://www.youtube.com/watch?v={vid}" if vid else "",
              "publishTime": i.get("publishedTime", ""),
              "likes": None,
              "comments": None,
              "shares": None,
              "views": i.get("viewCount", 0) or 0,
              "collects": None,
              "followers": None,
              "coverUrl": thumbs[0].get("url", "") if thumbs else "",
              "mediaType": "video",
          }
      
      
      NORMALIZERS = {
          "douyin": norm_douyin,
          "xiaohongshu": norm_xiaohongshu,
          "wechat_gzh": norm_wechat_gzh,
          "bilibili": norm_bilibili,
          "kuaishou": norm_kuaishou,
          "shipinhao": norm_shipinhao,
          "toutiao": norm_toutiao,
          "tiktok": norm_tiktok,
          "instagram": norm_instagram,
          "x_twitter": norm_x_twitter,
          "youtube": norm_youtube,
      }
      
      # ---------------------------------------------------------------- 工具函数
      
      
      def _ts_to_str(ts):
          """秒级时间戳转 'YYYY-MM-DD HH:MM:SS',None/非法返回空串"""
          if not ts:
              return ""
          try:
              return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(ts)))
          except (ValueError, TypeError, OSError):
              return ""
      
      
      def _to_int(v):
          try:
              return int(v) if v is not None else None
          except (ValueError, TypeError):
              return None
      
      
      def _deep_get(obj, keys):
          """按路径取嵌套字段,任一环节缺失返回 None"""
          cur = obj
          for k in keys:
              if isinstance(cur, dict) and k in cur:
                  cur = cur[k]
              else:
                  return None
          return cur
      
      
      # ---------------------------------------------------------------- 请求与解析
      
      
      def fetch_platform(key, keyword, api_key):
          """请求单个平台,返回 (平台key, 结果dict)。失败时 result 含 error 字段。"""
          cfg = PLATFORMS[key]
          headers = {
              "Content-Type": "application/json",
              "REDFOX-API-KEY": api_key,
              "X-API-Key": api_key,
          }
          body_dict = {k: v.replace("{kw}", keyword) if isinstance(v, str) else v
                       for k, v in cfg["body"].items()}
          body_dict["source"] = "全球AI新闻简报-GitHub"
          body = json.dumps(body_dict).encode("utf-8")
          req = urllib.request.Request(f"{HOST}{cfg['path']}", data=body, headers=headers, method="POST")
      
          try:
              with urllib.request.urlopen(req, timeout=TIMEOUT) as resp:
                  raw = json.loads(resp.read().decode("utf-8"))
          except urllib.error.HTTPError as e:
              detail = e.read().decode("utf-8", errors="replace")[:500]
              return key, {"platform": cfg["name"], "error": f"HTTP {e.code}: {detail}"}
          except urllib.error.URLError as e:
              return key, {"platform": cfg["name"], "error": f"网络错误: {e.reason}"}
          except Exception as e:  # noqa: BLE001 — 兜底保证单平台失败不影响整体
              return key, {"platform": cfg["name"], "error": f"解析错误: {e}"}
      
          if raw.get("code") != 2000:
              return key, {"platform": cfg["name"], "error": f"接口返回 code={raw.get('code')}, msg={raw.get('msg')}"}
      
          items = _deep_get(raw, cfg["list_key"])
          if items is None:
              items = []
      
          norm = NORMALIZERS[key]
          normalized = [norm(i) for i in items]
          total = _to_int(_deep_get(raw, ["data", "total"])) if key != "toutiao" and key != "tiktok" else None
      
          return key, {
              "platform": cfg["name"],
              "count": len(normalized),
              "total": total,
              "items": normalized,
          }
      
      
      def main():
          parser = argparse.ArgumentParser(description="全球AI新闻简报 — 11 平台并行搜索")
          parser.add_argument("keyword", help="搜索关键词")
          parser.add_argument("-o", "--output", default="/tmp/news_intel_result.json", help="输出 JSON 路径")
          parser.add_argument("--platforms", default=None,
                              help="逗号分隔的平台子集,如 douyin,xhs。默认全部 11 平台")
          parser.add_argument("--pretty", action="store_true", help="格式化输出 JSON")
          args = parser.parse_args()
      
          api_key = os.environ.get("REDFOX_API_KEY", "").strip()
          if not api_key:
              print("错误: 环境变量 REDFOX_API_KEY 未设置", file=sys.stderr)
              print("请先执行: export REDFOX_API_KEY='你的密钥'", file=sys.stderr)
              sys.exit(1)
      
          if args.platforms:
              selected = [p.strip() for p in args.platforms.split(",") if p.strip()]
              unknown = [p for p in selected if p not in PLATFORMS]
              if unknown:
                  print(f"错误: 未知平台 {unknown},可选: {list(PLATFORMS)}", file=sys.stderr)
                  sys.exit(1)
          else:
              selected = list(PLATFORMS)
      
          print(f"开始并行搜索 {len(selected)} 个平台,关键词: {args.keyword}", file=sys.stderr)
          results = {}
          errors = []
          with concurrent.futures.ThreadPoolExecutor(max_workers=len(selected)) as pool:
              futures = {pool.submit(fetch_platform, k, args.keyword, api_key): k for k in selected}
              for fut in concurrent.futures.as_completed(futures):
                  key, result = fut.result()
                  if "error" in result:
                      errors.append(result)
                      print(f"  ✗ {result['platform']}: {result['error']}", file=sys.stderr)
                  else:
                      results[key] = result
                      print(f"  ✓ {result['platform']}: {result['count']} 条", file=sys.stderr)
      
          total_items = sum(r["count"] for r in results.values())
          total_engagement = sum(
              (i.get("likes") or 0) + (i.get("comments") or 0) + (i.get("shares") or 0)
              for r in results.values() for i in r["items"]
          )
      
          output = {
              "keyword": args.keyword,
              "generatedAt": time.strftime("%Y-%m-%d %H:%M:%S"),
              "platformCount": len(results),
              "failedPlatforms": errors,
              "totalItems": total_items,
              "totalEngagement": total_engagement,
              "results": results,
          }
      
          with open(args.output, "w", encoding="utf-8") as f:
              json.dump(output, f, ensure_ascii=False, indent=2 if args.pretty else None)
      
          print(f"\n完成: 成功 {len(results)}/{len(selected)} 平台, 共 {total_items} 条, 总互动 {total_engagement}", file=sys.stderr)
          print(args.output)
      
      
      if __name__ == "__main__":
          main()
      
  • README.en.md 5.3 KB
    # Global AI News Brief / global-ai-news-brief
    
    ---
    
    ## Introduction
    
    Enter a keyword to search 11 major platforms at once — Douyin, Xiaohongshu, WeChat Official Accounts, Bilibili, Kuaishou, WeChat Channels, Toutiao, TikTok, Instagram, X(Twitter), and YouTube — then let AI aggregate the cross-platform data into smart summaries, topic clustering, sentiment analysis, and in-depth interpretation reports.
    
    **Core Value**
    
    - **One search, full coverage**: a single keyword searches all 11 platforms at once, no need to browse each one manually
    - **Deep intelligence, not just listings**: AI automatically clusters hot subtopics, extracts key findings, and gauges public sentiment
    - **Cross-platform comparison**: see differences in focus and interpretation across platforms at a glance
    - **Dual presentation**: quick browsing via terminal tables + complete archive via visual report
    
    **Who It's For**
    
    - 📊 Market & sentiment analysts — quickly grasp the full picture and sentiment trends of an event
    - ✍️ Content creators — collect multi-platform hot material in one go to support topic selection
    - 📰 Media & industry researchers — gain deep insights through cross-platform comparison
    
    ---
    
    ## Features
    
    ### Core Features
    
    - **Aggregated cross-platform search**: one keyword covers 11 major platforms (Douyin, Xiaohongshu, WeChat Official Accounts, Bilibili, Kuaishou, WeChat Channels, Toutiao, TikTok, Instagram, X(Twitter), YouTube); you can also limit the search to the 7 domestic platforms
    - **Four-section in-depth report**: News Events (overview + timeline + subtopic clustering), News Interpretation (summary + key findings + sentiment + KOLs), cross-platform interpretation comparison, and raw data sources — presented in sequence
    - **Smart sentiment analysis**: automatically calculates the positive/neutral/negative sentiment ratio across the web, extracts core consensus and controversy points, and identifies key opinion leaders
    - **Cross-platform comparison matrix**: content volume, total engagement, sentiment tendency, focus, and representative opinions of each platform in one table
    - **Visual report**: automatically generates and opens a visual page with platform tabs, sentiment dashboard, and comparison charts, while the terminal shows TOP 5 data tables per platform
    
    ---
    
    ## API Key Acquisition & Security
    
    - This skill requires the environment variable: `REDFOX_API_KEY`.
    - `REDFOX_API_KEY` is provided by [RedFoxHub](https://redfox.hk/settings/api-keys?source=github) (`https://redfox.hk`).
    - Please register an account at [RedFoxHub](https://redfox.hk?source=github) to obtain `REDFOX_API_KEY`.
    - Configure the `REDFOX_API_KEY` environment variable on your device before using this skill.
    - Before providing a key, please verify its source, available scope, validity period, and whether it supports reset/revocation.
    - Never hard-code or expose the key in plain text in code, prompts, logs, or output files.
    
    ---
    
    ## Usage Guide
    
    Describe your needs in natural language — no commands to memorize.
    
    ### Quick Phrase Reference
    
    | Intent                     | Example Phrase                                                  | Result                                                              |
    | -------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------- |
    | Cross-platform sentiment   | Look up the latest cross-platform buzz on "new energy vehicles" | Searches 11 platforms in parallel and outputs terminal tables + visual report |
    | Event tracking             | Track all cross-platform information about "typhoon"            | Focuses on the timeline and spread path of the event                |
    | Domestic platforms only    | Search "summer travel" on domestic platforms only               | Searches only the 7 domestic platforms: Douyin/Xiaohongshu/WeChat Official Accounts/Bilibili/Kuaishou/WeChat Channels/Toutiao |
    
    ### Output Example
    
    A single search produces a complete in-depth intelligence report, including:
    
    - **News Events**: event overview card, key timeline, hot subtopic clustering
    - **News Interpretation**: 200-character core summary, 3-5 key findings, sentiment (positive/neutral/negative ratio), key opinion leaders
    - **Platform Interpretation Tendencies**: cross-platform comparison matrix + sentiment comparison charts
    - **Data Sources**: complete data per platform, including covers, titles, authors, engagement metrics, and original links
    
    ---
    
    ## Use Cases
    
    | Scenario           | Role                              | Example Question                              | Benefit                                                    |
    | ------------------ | --------------------------------- | --------------------------------------------- | ---------------------------------------------------------- |
    | Hot topic tracking | Content creators, media staff     | Look up the cross-platform buzz on "new energy vehicles" | See all 11 platforms at once and quickly grasp the full picture |
    | Sentiment analysis | Marketing & PR professionals      | Track cross-platform information about "typhoon"         | Get timelines, sentiment distribution, consensus and controversy points |
    | Industry intelligence | Analysts & operations staff    | Search "summer travel" on domestic platforms only       | Cross-platform comparison matrix reveals focus differences |
    
  • README.md 4.4 KB
    # 全球AI新闻简报 / global-ai-news-brief
    
    ---
    
    ## 简介
    
    输入一个关键词,同时搜索抖音、小红书、公众号、B站、快手、视频号、今日头条、TikTok、Instagram、X(Twitter)、YouTube 共 11 大平台,跨平台聚合数据后由 AI 生成智能摘要、热点聚类、舆情分析和深度解读报告。
    
    **核心价值**
    
    - **一次搜索、全网覆盖**:一个关键词同时搜遍 11 大平台,无需逐个平台手动翻找
    - **深度情报而非简单罗列**:AI 自动聚类热点子话题、提炼关键发现、判断舆情风向
    - **跨平台对比视角**:一眼看清各平台关注焦点与解读倾向的差异
    - **双重呈现**:终端表格快速浏览 + 可视化报告完整存档
    
    **适用对象**
    
    - 📊 市场与舆情分析人员 — 快速掌握事件全貌与情感走向
    - ✍️ 内容创作者 — 一次获取多平台热点素材,辅助选题
    - 📰 媒体与行业研究者 — 跨平台对比解读,获得深度洞察
    
    ---
    
    ## 功能特性
    
    ### 核心功能
    
    - **全网聚合搜索**:一个关键词同时覆盖 11 大平台(含抖音、小红书、公众号、B站、快手、视频号、今日头条、TikTok、Instagram、X(Twitter)、YouTube),也可指定只搜国内 7 大平台
    - **四板块深度报告**:新闻事件(概述 + 时间线 + 子话题聚类)、新闻解读(摘要 + 关键发现 + 舆情风向 + KOL)、各平台解读倾向对比、原始数据源,依次完整呈现
    - **智能舆情分析**:自动计算全网正面/中性/负面情感占比,提炼核心共识点与争议点,识别关键意见领袖
    - **跨平台对比矩阵**:内容数、总互动量、情感倾向、关注焦点、代表观点一表看清各平台差异
    - **可视化报告**:自动生成带平台切换、情感仪表盘、对比图表的可视化页面并打开,终端同时输出平台 TOP5 数据表格
    
    ---
    
    ## 密钥获取与安全说明
    
    - 本技能需要使用环境变量:`REDFOX_API_KEY`。
    - `REDFOX_API_KEY` 由 [红狐 hub](https://redfox.hk/settings/api-keys?source=github) (`https://redfox.hk`)提供。
    - 请前往 [红狐 hub](https://redfox.hk?source=github) 注册账号,获取 `REDFOX_API_KEY`。
    - 配置设备环境变量 `REDFOX_API_KEY` 后使用本技能。
    - 在提供密钥前,请先确认密钥来源、可用范围、有效期及是否支持重置/撤销。
    - 禁止在代码、提示词、日志或输出文件中硬编码/明文暴露密钥。
    
    ---
    
    ## 使用指南
    
    直接用自然语言描述需求,无需记忆命令。
    
    ### 常用说法速查
    
    | 意图         | 示例话术                                         | 效果                                       |
    | ------------ | ------------------------------------------------ | ------------------------------------------ |
    | 全网舆情查询 | 帮我查一下"新能源汽车"最新的全网舆情             | 并行搜索 11 平台,输出终端表格 + 可视化报告 |
    | 事件追踪     | 追踪一下"台风"相关的全网信息                     | 侧重时间线和事件传播路径还原               |
    | 国内平台搜索 | 只看国内平台,搜一下"暑期旅游"                   | 仅搜索抖音/小红书/公众号/B站/快手/视频号/头条 7 个国内平台 |
    
    ### 输出示例
    
    一次搜索产出一份完整的深度情报报告,包含:
    
    - **新闻事件**:事件概述卡片、关键时间线、热点子话题聚类
    - **新闻解读**:200 字核心摘要、3-5 条关键发现、舆情风向(正面/中性/负面占比)、关键意见领袖
    - **各平台解读倾向**:跨平台对比矩阵表 + 情感对比图表
    - **数据源**:各平台完整数据,含封面、标题、作者、互动数据与原文链接
    
    ---
    
    ## 使用场景
    
    | 场景     | 角色               | 示例问法                             | 收益                                   |
    | -------- | ------------------ | ------------------------------------ | -------------------------------------- |
    | 热点追踪 | 内容创作者、媒体人 | 查一下"新能源汽车"全网舆情           | 一次看全 11 平台,快速掌握热点全貌     |
    | 舆情分析 | 市场、公关人员     | 追踪"台风"相关全网信息               | 获得时间线、情感分布、共识点与争议点   |
    | 行业情报 | 分析师、运营人员   | 只看国内平台,搜一下"暑期旅游"       | 跨平台对比矩阵,洞察各平台关注差异     |
    
  • SKILL.md 13.9 KB
    ---
    name: global-ai-news-brief
    description: 全球AI新闻简报 — 一个关键词同时搜索抖音、小红书、公众号、B站、快手、视频号、今日头条、TikTok、Instagram、X(Twitter)、YouTube 共 11 大平台,跨平台聚合后由 AI 生成智能摘要、热点聚类、舆情分析和深度解读报告,输出终端表格 + 交互式 HTML 报告。包含详细信息源列表,适用于各种AI agent进行社媒资讯分析。当用户需要新闻搜索、舆情分析、热点追踪、跨平台情报对比、资讯聚合、新闻解读、全网搜索、事件追踪、行业情报时使用。触发词:新闻情报、全网搜索、舆情分析、热点追踪、新闻解读、资讯聚合、跨平台分析、事件追踪、行业情报、news brief、global news。
    ---
    
    # 全球AI新闻简报
    
    输入一个关键词,同时发起 11 大平台搜索请求,跨平台聚合数据后由 AI 生成深度情报报告。
    
    ## 覆盖平台
    
    | # | 平台 | 接口路径 | 搜索参数 | 排序选项 |
    |---|------|---------|---------|---------|
    | 1 | 抖音 | `/story/api/dy/data/searchWork` | keyword, pageNum, pageSize | — |
    | 2 | 小红书 | `/story/api/xhsUser/searchArticle` | keyword, offset, sortType | 0=默认/2=最新/4=最热 |
    | 3 | 公众号 | `/story/api/gzh/data/searchArticle` | keyword, offset, sortType | 0=默认/2=最新/4=最热 |
    | 4 | B站 | `/story/api/bili/data/workSearch` | keyword, page, pageSize, order | time/play/like/comment/favorite |
    | 5 | 快手 | `/story/api/ksAllData/searchWork` | keyword, page, size, sort | 综合/最新/最多点赞/最多收藏 |
    | 6 | 视频号 | `/story/api/sphAllData/searchWork` | keyword, sort, page, size | 综合/最新/最多点赞/最多收藏 |
    | 7 | 今日头条 | `/story/api/toutiao/searchWork` | keyword, offset | — |
    | 8 | TikTok | `/story/api/tiktok/ability/searchVideo` | keyword, offset, count, sortType, publishTime, region | 0=相关度/1=最多点赞 |
    | 9 | Instagram | `/story/api/ins/search` | keyword, paginationToken | — |
    | 10 | X(Twitter) | `/story/api/x/search` | keyword, searchType, cursor | Top/Latest/Media |
    | 11 | YouTube | `/story/api/youtube/searchVideo` | searchQuery, continuationToken | — |
    
    > 所有接口 Host: `https://redfox.hk`,Method: `POST`,Content-Type: `application/json`,鉴权方式见下方「🔑 鉴权」。
    > 详细请求/响应字段见 [api-reference.md](api-reference.md)。
    
    ## 🔑 鉴权
    
    ### 获取 API Key
    
    请前往 [红狐hub](https://redfox.hk/settings/api-keys?source=github) 获取 API KEY
    
    ### 配置 API Key
    
    方案1: 以 OpenClaw 为例,将 REDFOX_API_KEY 添加到 `~/.openclaw/openclaw.json` 中:
    
    ```bash
    { "env": { "REDFOX_API_KEY": "ak_xxxx..." } }
    ```
    
    方案2: 终端配置
    
    ```bash
    export REDFOX_API_KEY="ak_xxxx..."
    ```
    
    所有平台接口的请求头均携带 `REDFOX-API-KEY` + `X-API-Key`(值均为 `$REDFOX_API_KEY`),缺失时脚本报错退出并提示配置。
    
    ## 工作流程
    
    ### Step 1:关键词处理
    
    - 用户输入的关键词直接作为搜索词
    - 若输入含"达人""博主""KOL""网红""账号"等后缀,自动剥离后缀仅保留核心语义词
    - 可询问用户是否需要指定平台范围(默认全部 11 个平台)
    
    ### Step 2:并行数据采集
    
    使用脚本 [scripts/fetch_all.py](scripts/fetch_all.py) 一键并行采集(内部用线程池并发请求全部平台):
    
    ```bash
    python3 ~/.agents/skills/global-ai-news-brief/scripts/fetch_all.py "关键词" --pretty
    ```
    
    - **前置条件**:环境变量 `REDFOX_API_KEY` 已设置(脚本会检测,缺失时报错退出)
    - **默认行为**:并行请求全部 11 个平台,每个平台取首页数据(20条)
    - **指定平台子集**:`--platforms douyin,xhs,gzh,bilibili,kuaishou,shipinhao,toutiao`(仅搜国内平台时用)
    - **输出**:标准化 JSON 写入 `/tmp/news_intel_result.json`,同时在 stderr 打印各平台采集状态
    - **容错**:单平台失败自动跳过,在结果的 `failedPlatforms` 字段中标注,不影响其他平台
    
    输出 JSON 结构:
    
    ```
    {
      keyword: string,          // 搜索关键词
      generatedAt: string,      // 生成时间
      platformCount: number,    // 成功平台数
      failedPlatforms: [],      // 失败平台列表 [{platform, error}]
      totalItems: number,       // 总内容条数
      totalEngagement: number,  // 总互动量(点赞+评论+分享+播放)
      results: {                // 按平台 key 分组
        douyin: { platform, count, total, items[] },
        ...
      }
    }
    ```
    
    每个 `items[]` 条目已由脚本标准化为统一结构(见 Step 3),Agent 直接读取 JSON 文件做分析即可,无需再处理各平台字段名差异。
    
    ### Step 3:数据标准化
    
    将各平台返回数据统一为以下标准结构:
    
    ```
    {
      platform: string,     // 平台名称
      title: string,        // 标题/描述首行
      content: string,      // 正文/描述
      author: string,       // 作者昵称
      url: string,          // 作品链接
      publishTime: string,  // 发布时间
      likes: number,        // 点赞数
      comments: number,     // 评论数
      shares: number,       // 分享/转发数
      views: number,        // 播放/阅读数
      collects: number,     // 收藏数
      followers: number,    // 作者粉丝数
      coverUrl: string,     // 封面图
      mediaType: string     // video/image/text
    }
    ```
    
    **字段映射要点**(处理各平台字段名差异):
    
    | 标准字段 | 抖音 | 小红书 | 公众号 | B站 | 快手 | 视频号 | 头条 | TikTok | Instagram | X | YouTube |
    |---------|------|-------|-------|-----|-----|-------|------|--------|----------|---|---------|
    | title | content | workTitle | title | title | caption | description | title | content | captionText | text | title |
    | author | authorName | accountNickname | author | author | nickname | nickname | nickname | authorData.userName | user.fullName | user.displayName | author |
    | likes | likeCount | workLikedCount | likeCount | likeCount | likeCount | likeCount | — | statsData.likeCount | likeCount | likeCount | — |
    | comments | commentCount | workCommentsCount | commentCount | commentCount | commentCount | commentCount | commentNum | statsData.commentTotal | commentCount | replyCount | — |
    | views | — | — | readCount | playCount | viewCount | — | — | statsData.viewCount | playCount | viewCount | viewCount |
    | url | opusUrl | workUrl | workUrl | 拼接BV | 拼接photoId | — | opusUrl | shareLink | 拼接code | 拼接tweetId | 拼接videoId |
    
    ### Step 4:AI 智能分析与输出
    
    对聚合后的全部数据执行分析,**严格按以下四个板块依次输出**(终端和 HTML 报告均遵循此顺序):
    
    ---
    
    #### 板块一:新闻事件
    
    还原"发生了什么"——客观呈现事件全貌。
    
    - **事件概述**:用 3-5 句话概括核心事件(谁、什么、何时、何地、影响范围)
    - **关键事件时间线**:按发布时间排列关键节点,还原事件从萌芽到发酵的传播路径;排序规则:**最新时间在最上面(倒序)**,无明确日期的条目(如「海外长线」)排在最后
    - **热点话题聚类**:将全部内容按主题自动聚类为 3-8 个热点话题,每个话题标注:
      - 主题名称
      - 涉及平台数
      - 代表内容 2-3 条(含标题、作者、平台、链接)
    
    ---
    
    #### 板块二:新闻解读
    
    AI 深度分析"意味着什么"——提炼洞察与判断。
    
    - **核心摘要**:200 字以内的精炼总结,包含事件定性、影响评估、趋势预判
    - **关键发现**:3-5 条核心洞察,每条包含论点 + 数据支撑
    - **舆情风向**:
      - 全网情感分布:正面 / 中性 / 负面占比
      - 核心共识点(多数人认同的观点)
      - 核心争议点(分歧最大的议题)
    - **大V观点(KOL)**:识别粉丝量 > 10000 或单条互动量 TOP 的作者,列出作者名、平台、粉丝数、代表观点;标题统一使用通俗说法「大V观点」,不使用「关键意见领袖」。账号名渲染为可点击链接跳转作者主页,主页链接拼接规则(从作品链接或接口字段提取作者 ID 拼接):
      - X/Twitter:`https://x.com/{username}`(从作品 url `/status/` 前段提取)
      - TikTok:`https://www.tiktok.com/@{username}`(从作品 url `/@xxx/` 段提取)
      - Instagram:`https://www.instagram.com/{username}/`
      - B站:`https://space.bilibili.com/{mid}`(接口无 mid 时回退 `https://search.bilibili.com/all?keyword={作者名}`)
      - 公众号:`https://open.weixin.qq.com/qr/code?username={biz}`
      - 快手/小红书等无法提取作者 ID 的平台:回退平台搜索链接(如 `https://www.kuaishou.com/search/video?searchKey={作者名}`)
      - 视频号无公开主页链接:不渲染链接
    
    ---
    
    #### 板块三:各平台不同的解读倾向
    
    跨平台对比"各平台怎么看"——揭示平台差异化特征。
    
    对每个有数据的平台分析以下维度:
    
    | 分析维度 | 说明 |
    |---------|------|
    | 情感倾向 | 该平台正面/中性/负面比例,与全网均值对比 |
    | 关注焦点 | 该平台用户最关注的子话题/角度(与其他平台的差异点) |
    | 内容形态 | 以视频/图文/长文哪种为主 |
    | 热度指标 | 内容条数、总互动量、平均互动量 |
    | 代表声音 | 该平台互动量最高的 2-3 条内容及观点摘要 |
    
    输出为**跨平台对比矩阵表**:
    
    ```markdown
    | 平台 | 内容数 | 总互动 | 情感倾向 | 关注焦点 | 代表观点 |
    |------|-------|-------|---------|---------|---------|
    | 抖音 | 20 | 58000 | 正面65% | 事件现场视频 | "xxx" |
    | 公众号 | 18 | 120000 | 中性55% | 深度分析文章 | "xxx" |
    | X/Twitter | 15 | 9200 | 负面60% | 批评与讨论 | "xxx" |
    ```
    
    ---
    
    #### 板块四:数据源
    
    原始数据完整展示——按平台分段列出全部搜索结果。
    
    **终端输出**:每个平台展示 TOP 5 表格:
    
    ```markdown
    ### 抖音 TOP 5
    
    | # | 标题 | 作者 | 点赞 | 评论 | 分享 | 发布时间 | 链接 |
    |---|------|------|------|------|------|---------|------|
    | 1 | xxx | xxx | 8000 | 280 | 150 | 2026-05-20 | [查看](url) |
    ```
    
    **HTML 报告**:每个平台一个可切换 Tab,展示该平台全部数据条目,含封面图、标题、作者、完整数据指标、原文链接。
    
    **数据时间范围标注**:数据源标题(h2「四、数据源」)后以 .formula-note 小字标注实际数据时间范围,如「(数据时间范围:2026-07-20 ~ 2026-08-19 为主体近30天数据,含少量历史旧闻,最早 2024-07-02)」。计算规则:
    - 解析全部条目的 publishTime(兼容三种格式:`YYYY-MM-DD...`、X/Twitter 的 `%a %b %d %H:%M:%S +0000 %Y`、相对时间 `N days/weeks/months ago`(以采集日为基准推算)),取最小/最大日期
    - 口径:报告当前时间前 30 天为主体窗口,若 90% 以上条目落在此窗口,文案注明「主体近30天(起始日期 ~ 最晚日期)」;窗口外的更早条目计为「历史旧闻」,注明最早日期
    
    ### Step 5:HTML 报告生成
    
    使用 [assets/report-template.html](assets/report-template.html) 模板生成交互式 HTML 报告,严格按四大板块组织:
    
    1. **顶部概览**:subtitle 行展示搜索关键词、覆盖平台数、总内容条数、**数据时间范围(短格式「YYYY-MM-DD ~ YYYY-MM-DD」,长说明在数据源标题后)**;概览卡片区仅 4 张卡(覆盖平台/内容总数/总互动量/活跃平台);生成时间只出现在页面底部 footer
    2. **板块一 · 新闻事件**:事件概述卡片 + 垂直时间轴 + 热点话题标签云 + 热点话题详情卡片(.topic-list 网格 + .topic-card 卡片样式,卡头带蓝色小方块装饰 + 话题名 + 平台数,正文为项目符号列表)
    3. **板块二 · 新闻解读**:核心摘要区 + 关键发现列表 + 舆情风向仪表盘(正面/中性/负面进度条)+ 大V观点卡片
    4. **板块三 · 各平台解读倾向**:跨平台对比矩阵表 + 各平台情感对比柱状图(CSS 实现,标题后以 .formula-note 小字标注计算公式「互动量 = 点赞 + 评论 + 分享 + 播放」)+ 差异亮点
    5. **板块四 · 数据源**:平台 Tab 切换器,每个 Tab 内展示该平台全部内容卡片(封面、标题、作者、指标、链接)。**Tab 排序规则:按平台互动量(点赞+评论+分享+播放)降序排列,互动量最高的平台排最前**;Tab 内条目保持接口返回原始顺序,不做二次排序
    
    **封面展示规则**:
    
    - 接口不返回封面的平台(如今日头条):该平台所有卡片不渲染封面区域,直接从正文开始(生成时检测:平台内全部条目 coverUrl 为空即视为无封面平台)
    - 其他平台封面为空时:渲染固定高度(180px)白色背景占位块,保证卡片高度统一
    - 封面加载失败(onerror):移除 src 保留白色占位块,不隐藏不塌陷
    
    **对话输出**:报告中生成的所有关键标注必须同步展示在对话回复中,包括:
    - 数据时间范围(短格式 + 主体占比/历史旧闻说明)
    - 互动量计算公式口径:互动量 = 点赞 + 评论 + 分享 + 播放(接口不返回播放量的平台按 0 计)
    - 各平台数据统计、互动排名、报告文件路径
    
    HTML 文件保存到本 Skill 的 [output/](output/) 目录,文件名 `global-ai-news-brief-report-{keyword}-{date}.html`(目录不存在时先创建),用 `open` 命令打开。禁止保存到 /tmp 等临时目录。
    
    ## 错误处理
    
    - 某个平台请求失败时跳过该平台并在报告中标注"数据暂不可用"
    - 不阻断其他平台数据采集
    - API 密钥缺失时提示用户设置 `REDFOX_API_KEY` 环境变量
    
    ## 使用示例
    
    ```
    用户:帮我查一下"新能源汽车"最新的全网舆情
    Agent:→ 并行搜索 11 平台 → 聚合数据 → AI 分析 → 输出终端表格 + HTML 报告
    
    用户:追踪一下"台风"相关的全网信息
    Agent:→ 同上流程,侧重时间线和事件追踪
    
    用户:只看国内平台,搜一下"暑期旅游"
    Agent:→ 仅搜索抖音/小红书/公众号/B站/快手/视频号/头条 7 个国内平台
    ```
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related