Claude Skill

bilibili-comment

B站评论分析工具。输入B站视频链接或BV号即可获取一级评论数据,支持分页浏览、评论情感分析(积极/负面/需求/竞品),生成精美 HTML 报告。当用户需要查看B站视频评论、分析评论舆情、了解用户反馈时使用。触发词:B站评论、B站视频评论、评论查询、评论分析、评论舆情、看评论、bilibili评论。

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_bilibili-comment-5e7b435.zip · 21 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/bilibili-comment
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

B站评论分析 / bilibili-comment


简介

输入任意B站视频链接或BV号,一键获取评论数据,AI 自动完成四维情感分析(积极/负面/需求/竞品),同时生成可离线保存的交互式 HTML 报告。

功能介绍

B站评论分析是专为内容创作者、UP主和品牌运营打造的智能评论洞察工具。基于红狐 API 实时拉取视频一级评论,每页20条,支持分页浏览;AI 深度理解B站梗文化(awsl / yyds / 爷青回 等弹幕术语),完成积极/负面/需求/竞品四维分析并引用代表评论;最终生成深色主题交互式 HTML 报告,便于保存与分享。

核心价值

  • 实时评论拉取:粘贴链接即可获取最新评论,无需手动翻找评论区。
  • B站梗文化理解:AI 识别弹幕术语和梗的真实语境,分析结果更准确。
  • 结构化四维分析:积极/负面/需求/竞品清晰分层,各维度附代表评论引用,快速抓住舆情核心。

适用对象

  • 🎬 UP主 — 复盘视频反馈,优化选题和内容策略。
  • 🏢 品牌运营 — 监测舆情,及时发现用户声音和风险信号。
  • 📊 内容策划 / 产品经理 — 挖掘竞品评论,研究用户真实需求。

功能特性

核心功能

  • 评论获取:输入BV号或视频链接,自动拉取一级评论,每页20条
  • 分页浏览:支持「下一页」「第N页」等自然语言翻页,逐步浏览大量评论
  • 四维 AI 分析:积极/负面/需求/竞品四类情感分析,各附代表评论引用,百分比展示
  • 置顶标记:置顶评论特殊标识,一眼识别重要内容
  • HTML 报告:深色主题交互式报告,支持离线保存与分享

特色亮点

  • B站梗文化理解:识别 awsl / yyds / xswl / 爷青回 / 下次一定 等弹幕术语及梗的真实含义
  • 数据完整展示:作品详情(播放/点赞/投币/收藏/弹幕等)与评论表格全量呈现
  • 编码安全回填:智能编码保障,中文分析内容完整无误地注入报告

密钥获取与安全说明

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

使用指南

直接用自然语言说出视频链接或BV号即可,无需记忆固定命令。

常用说法速查

意图 示例话术 效果
查看视频评论 「查看B站视频 BV1xx411c7mD 的评论」 获取第1页评论 + AI总结
通过链接查询 粘贴 https://www.bilibili.com/video/BV1xx411c7mD 自动提取BV号并拉取评论
翻页 「下一页」「第3页」 沿用当前视频,获取指定页评论
生成报告 「需要」「生成HTML」 回填AI分析,生成交互式HTML报告

输出示例

完成查询后,你将依次收到:

作品详情

🎬 视频标题

UP主:昵称 | 发布:2024-01-01 | 时长:12:34

▶ 12.5w 👍 3.2w 🪙 1.8w ⭐ 2.1w 🔄 5.6k 💬 1.2k 📝 8.9k

评论表格(当前页全部评论)

# 用户昵称 评论内容 👍 时间 IP
1 用户名 评论内容... 1223 01-12 15:30 广东

四维情感分析(AI总结,含代表评论引用)

询问是否生成 HTML 可视化报告


使用场景

场景 角色 示例问法 收益
内容复盘 UP主 「看看这个视频的评论怎么样」 快速了解观众反馈,优化选题策略
舆情监测 品牌运营 「分析这条视频的负面评论」 及时发现危机信号,制定应对方案
竞品分析 内容策划 「分析竞品视频的用户评论」 了解竞品优劣势,找准差异化方向
用户研究 产品经理 「看看用户在评论区提了哪些需求」 挖掘真实需求,指导产品迭代

Skill manifest

B站评论分析

简介

B站评论分析是一款专为内容创作者、UP主、品牌运营和研究人员设计的智能评论洞察工具。输入任意B站视频链接或BV号,即可一键获取评论数据,并通过四维情感分析(积极/负面/需求/竞品)快速了解用户真实反馈,同时生成可离线保存的交互式 HTML 报告。

通过本技能,你可以:

  • 📊 逐页获取视频一级评论(每页20条,支持翻页)
  • 🤖 AI 自动完成四维情感分析,理解B站梗文化
  • 📋 生成深色主题交互式 HTML 报告,便于保存与分享

适用于 UP主复盘、品牌舆情监测、竞品分析、内容策略研究等场景。

功能特性

核心功能

  • 评论获取:粘贴视频链接或BV号即可拉取最新评论数据
  • 分页浏览:每页20条,支持前后翻页,逐步浏览大量评论
  • 四维 AI 分析:积极/负面/需求/竞品四类情感分析,各维度附代表评论引用
  • 置顶标记:置顶评论特殊标识,一眼识别重要内容
  • HTML 报告:深色主题交互式报告,支持离线保存与分享

特色亮点

  • B站梗文化理解:识别弹幕术语、缩写(awsl / yyds / xswl / 爷青回 等)及热门梗的真实语境
  • 数据完整展示:作品详情(播放/点赞/投币/收藏/弹幕等)与评论表格全量展示,不截断
  • 编码安全回填:智能编码保障,中文分析内容完整无误地注入报告

鉴权

  • 获取 API Key:前往 红狐hub
  • 配置方式1:写入 ~/.openclaw/openclaw.json → { "env": { "REDFOX_API_KEY": "ak_xxxx..." } }
  • 配置方式2:终端执行 export REDFOX_API_KEY="ak_xxxx..."

工作流程

核心执行流程详见 references/core_workflow.md

使用指南

直接用自然语言说出视频链接或BV号即可,无需记忆固定命令。

常用说法速查

意图 示例话术 效果
查看视频评论 「查看B站视频 BV1xx411c7mD 的评论」 获取第1页评论 + AI总结
通过链接查询 粘贴 https://www.bilibili.com/video/BV1xx411c7mD 自动提取BV号并拉取评论
翻页 「下一页」「第3页」 沿用当前视频,获取指定页评论
生成报告 「需要」「生成HTML」 回填AI分析,生成交互式HTML报告

输出示例

完成查询后,你将依次收到:

  1. 作品详情(标题、UP主、播放量、点赞等核心数据)
  2. 评论表格(当前页全部评论,含昵称链接、内容、点赞数、时间、IP属地)
  3. 四维情感分析(积极/负面/需求/竞品,各附代表评论)
  4. 询问是否生成 HTML 报告

使用场景

场景 角色 示例问法 收益
内容复盘 UP主 「看看这个视频的评论怎么样」 快速了解观众反馈,优化选题策略
舆情监测 品牌运营 「分析这条视频的负面评论」 及时发现危机信号,制定应对方案
竞品分析 内容策划 「分析竞品视频的用户评论」 了解竞品优劣势,找准差异化方向
用户研究 产品经理 「看看用户在评论区提了哪些需求」 挖掘真实需求,指导产品迭代

项目架构

bilibili-comment/
├── SKILL.md                    # 技能配置与使用说明
├── references/
│   └── core_workflow.md        # Agent 核心执行流程
├── assets/
│   └── report_template.html    # HTML 报告模板
└── scripts/
    ├── bili_comment_search.py  # 评论获取脚本(调用 API,自动生成 HTML)
    └── backfill_html.py        # AI 分析回填脚本(将分析结果写入 HTML)
模块 职责
bili_comment_search.py 调用红狐 API 获取评论数据,生成含占位符的 HTML 报告
backfill_html.py 将 AI 四维分析 JSON 安全回填至 HTML 报告,支持文件直读模式
report_template.html 深色主题交互式报告模板

技术栈:Python 标准库(urllib),无需额外安装依赖。

常见问答

安装相关

Q1: 如何获取 REDFOX_API_KEY?

A: 前往 红狐hub 注册账号并申请 API Key,按鉴权章节说明配置到本地环境变量。

Q2: 需要安装额外依赖吗?

A: 不需要。脚本使用 Python 标准库 urllib,Python 3.6+ 环境即可直接运行。

使用相关

Q3: 一次能获取多少条评论?

A: 每次调用获取1页(20条)。如需更多数据,通过翻页命令逐页获取,或前往 红狐平台 联系客服获取批量能力。

Q4: 支持获取二级评论(回复)吗?

A: 当前版本仅支持一级评论,二级回复暂不支持。

故障排除

Q5: HTML 报告中部分中文显示乱码(问号)怎么办?

A: 这是编码回填环节的兼容性问题。解决方案:用 Python 写入分析数据为 UTF-8 JSON 文件,再使用 backfill_html.py --json-file 直接读取回填。详见 references/core_workflow.md Step 3。

Q6: 如有其他问题如何获取帮助?

A: 前往 红狐平台 联系客服,或查阅技能文档。

Files (redfox-community)
  • assets
    • report_template.html 14.5 KB · in bundle
  • references
    • core_workflow.md 4.3 KB
      # Core Workflow
      
      ## Step 1:理解用户意图,提取 bvId
      
      - 从用户输入中提取 bvId(BV号);若提供视频链接则从链接中提取
      - 若用户未提供,主动询问:「请提供B站视频链接或BV号」
      - 若上一轮已查询某视频且本轮输入模糊(如「下一页」「评论分析」),沿用上一轮 bvId
      
      ## Step 2:调用评论获取脚本
      
      每次调用仅请求一页数据(一次 API 请求),不可擅自发起多次调用拉取多页。
      
      ```bash
      python3 "$SKILL_PATH/scripts/bili_comment_search.py" "<bvId>" [--page <page>]
      ```
      
      参数:`bvId`(必填)、`--page`(默认1)、`--output-dir`(默认 ~/Downloads/QoderReports)
      
      脚本自动生成含 `{{PLACEHOLDER}}` 占位符的 HTML 报告(未回填分析数据)。
      
      脚本返回 JSON 字段:`work_detail`、`total_count`、`total_fetched`、`has_next`、`comments`、`html_path`
      
      ## Step 3:对话中展示评论数据 + AI 总结
      
      **A0(每次查询必须输出)** 作品详情(标题、UP主链接、发布时间、时长、播放/点赞/投币/收藏/分享/评论/弹幕数);数字 ≥ 10000 使用 x.xw 格式。
      
      **A1** 告知查询范围(获取条数)
      
      **A2** 渲染评论表格:用户昵称带 Bilibili 主页链接、评论超40字截断加 `...`、时间格式 MM-DD HH:MM、点赞数 ≥ 10000 用 x.xw 格式;每页最多20条全部展示,不得截断。
      
      **A3(每次查询必须输出)** 四维情感分析(积极/负面/需求/竞品):
      - 基于B站梗文化理解(awsl / 爷青回 / xswl / yyds / 绝绝子 等)
      - 每条要点引用代表评论关键词/短语
      - 百分比为各类评论占总评论数比例,四类总和可超100%
      - 若 `total_fetched` < `work_detail.reply_count`,追加提示引导用户前往红狐平台
      
      A0~A3 在同一轮输出中连续完成,不可省略任何一步。
      
      A3 完毕后询问用户:「📊 是否需要生成 HTML 可视化报告?」
      
      **用户确认后(无需重新调用脚本,HTML 已在 Step 2 生成):**
      
      **① 写入分析 JSON 文件(用 Python,确保 UTF-8)**
      
      ⚠️ 不可用 Write 工具写 JSON 文件(Windows 上默认 GBK 会损坏中文)。
      必须用 Python 写:
      
      ```bash
      python -c "import json; json.dump({分析数据}, open('temp.json','w',encoding='utf-8'), ensure_ascii=False)"
      ```
      
      若 Python 字符串中含中文标点/引号导致 PowerShell 转义错误,改用 unicode 转义:
      ```bash
      $env:PYTHONIOENCODING='utf-8'; python -c "import json; d={...}; open('temp.json','w',encoding='utf-8').write(json.dumps(d,ensure_ascii=False))"
      ```
      
      **② 回填 AI 分析到 HTML(--json-file 绕过管道)**
      
      ```bash
      python "$SKILL_PATH/scripts/backfill_html.py" "<html_path>" --json-file "<temp_json_file>"
      ```
      
      JSON 字段:`positive_ratio`、`negative_ratio`、`demand_ratio`、`competitor_ratio`(纯整数);
      `positive_summary`、`negative_summary`、`demand_summary`、`competitor_summary`(HTML `<ul><li>` 格式)
      
      **③ 打开 HTML 报告**
      - Windows: `Start-Process "<html_path>"`
      - macOS/Linux: `open "<html_path>"`
      
      ## Step 4:翻页处理
      
      当用户回复「下一页」「上一页」「第N页」时:
      1. 沿用已有 bvId,计算新 page 值(`offset = (page - 1) × 20`)
      2. 重新调用脚本(`--page <page>`),脚本自动生成当页 HTML
      3. 完整执行 Step 3(A1~A3),A3 后询问是否生成当前页 HTML
      4. 翻页规则:`has_next=true` 有下一页;`has_next=false` 已是最后一页
      
      ## Step 5:错误处理
      
      | 错误类型 | 处理方式 |
      |---------|---------|
      | 无 API Key | 提示配置 REDFOX_API_KEY,给出配置指引 |
      | 视频链接无效 | 提示「未找到该视频的评论,请检查视频链接是否正确」 |
      | 接口返回 502 错误 | 服务返回 502 错误,可能存在网络不稳定问题,请稍后重试 |
      | 获取 0 条评论 | 提示「该视频暂无评论」并建议检查视频是否存在或已删除 |
      | 网络请求超时 | 提示「网络请求超时,请稍后重试」 |
      | 评论任务超时 | 提示「评论数据获取超时,请稍后重试」 |
      | HTML 中文乱码 | 根本原因:Write 工具写 JSON 为 GBK 或 PowerShell 管道二次编码损坏。解决方案:用 Python `json.dump(ensure_ascii=False)` + `open(f,'w',encoding='utf-8')` 写 JSON,再用 `backfill_html.py --json-file` 直接读文件回填,全程不经过 Write 工具和管道 |
      
  • scripts
    • backfill_html.py 3.7 KB
      #!/usr/bin/env python3
      """
      HTML 报告分析数据回填脚本
      将 AI 分析结果回填到脚本生成的 HTML 报告中的 {{PLACEHOLDER}} 占位符。
      用法: python3 backfill_html.py <html_path> --json-file <json_file>
            python3 backfill_html.py <html_path> --analysis-json '<json>'
            或通过 stdin 传入 JSON: echo '<json>' | python3 backfill_html.py <html_path>
      
      推荐 --json-file:从文件直接读取,彻底规避 Windows 管道/Write 工具编码问题。
      """
      
      import sys
      import os
      import json
      import argparse
      
      
      def backfill(html_path: str, analysis: dict) -> None:
          """读取 HTML 文件,替换分析占位符,写回文件"""
          if not os.path.exists(html_path):
              print(f"[error] HTML 文件不存在: {html_path}", file=sys.stderr)
              sys.exit(1)
      
          with open(html_path, "r", encoding="utf-8") as f:
              html = f.read()
      
          # 统计栏比例
          ratio_map = {
              "{{POSITIVE_RATIO}}": str(analysis.get("positive_ratio", "--")),
              "{{NEGATIVE_RATIO}}": str(analysis.get("negative_ratio", "--")),
              "{{DEMAND_RATIO}}": str(analysis.get("demand_ratio", "--")),
              "{{COMPETITOR_RATIO}}": str(analysis.get("competitor_ratio", "--")),
          }
      
          for key, val in ratio_map.items():
              html = html.replace(key, val)
      
          # 摘要卡片内容
          summary_map = {
              "{{SUMMARY_POSITIVE}}": analysis.get("positive_summary", ""),
              "{{SUMMARY_NEGATIVE}}": analysis.get("negative_summary", ""),
              "{{SUMMARY_DEMAND}}": analysis.get("demand_summary", ""),
              "{{SUMMARY_COMPETITOR}}": analysis.get("competitor_summary", ""),
          }
      
          for key, val in summary_map.items():
              html = html.replace(key, val)
      
          with open(html_path, "w", encoding="utf-8") as f:
              f.write(html)
      
          print(f"[backfill] 分析数据已回填到: {html_path}", file=sys.stderr)
      
      
      def main():
          parser = argparse.ArgumentParser(description="HTML 报告分析数据回填")
          parser.add_argument("html_path", help="HTML 报告文件路径")
          parser.add_argument(
              "--analysis-json", dest="analysis_json", type=str, default=None,
              help='分析数据 JSON 字符串,格式: {"positive_ratio":45,"positive_summary":"<ul>...</ul>",...}',
          )
          parser.add_argument(
              "--json-file", dest="json_file", type=str, default=None,
              help="分析数据 JSON 文件路径(推荐,绕过管道编码问题)",
          )
      
          args = parser.parse_args()
      
          # 优先级:--json-file > --analysis-json > stdin
          if args.json_file:
              if not os.path.exists(args.json_file):
                  print(f"[error] JSON 文件不存在: {args.json_file}", file=sys.stderr)
                  sys.exit(1)
              try:
                  with open(args.json_file, "r", encoding="utf-8") as f:
                      analysis = json.load(f)
              except json.JSONDecodeError as e:
                  print(f"[error] JSON 文件解析失败: {e}", file=sys.stderr)
                  sys.exit(1)
          elif args.analysis_json:
              try:
                  analysis = json.loads(args.analysis_json)
              except json.JSONDecodeError as e:
                  print(f"[error] JSON 解析失败: {e}", file=sys.stderr)
                  sys.exit(1)
          else:
              # 从 stdin 读取 JSON(显式 UTF-8,避免 Windows 管道编码问题)
              try:
                  raw = sys.stdin.buffer.read().decode('utf-8')
                  analysis = json.loads(raw) if raw.strip() else {}
              except json.JSONDecodeError as e:
                  print(f"[error] stdin JSON 解析失败: {e}", file=sys.stderr)
                  sys.exit(1)
      
          if not analysis:
              print("[warn] 未提供分析数据,跳过回填", file=sys.stderr)
              return
      
          backfill(args.html_path, analysis)
      
      
      if __name__ == "__main__":
          main()
      
    • bili_comment_search.py 16.2 KB
      #!/usr/bin/env python3
      """
      B站评论分析脚本
      调用 Redfox API 获取B站视频一级评论数据,同步生成 HTML 报告
      两步异步接口:commentSubmit 提交任务 → commentResult 轮询结果
      用法: python3 bili_comment_search.py "<bvId>" [--page 1] [--no-html] [--output-dir ~/Downloads/QoderReports]
      """
      
      import sys
      import os
      import re
      import json
      import time
      import argparse
      import urllib.request
      import urllib.error
      import urllib.parse
      from datetime import datetime
      
      SUBMIT_API = "https://redfox.hk/story/api/bili/commentSubmit"
      RESULT_API = "https://redfox.hk/story/api/bili/commentResult"
      WORK_DETAIL_API = "https://redfox.hk/story/api/bili/workDetail"
      PAGE_SIZE = 20  # 每页固定 20 条
      MAX_POLL_ATTEMPTS = 30  # 最大轮询次数
      POLL_INTERVAL = 2  # 轮询间隔(秒)
      
      # 脚本所在目录,用于定位模板
      SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
      TEMPLATE_PATH = os.path.join(SCRIPT_DIR, "..", "assets", "report_template.html")
      
      
      def get_api_key() -> str:
          val = os.environ.get("REDFOX_API_KEY", "")
          if not val:
              print("[error] 未找到环境变量 REDFOX_API_KEY,请确认已设置 API Key", file=sys.stderr)
              print("[hint] 获取 API Key: https://redfox.hk/settings/api-keys?source=github", file=sys.stderr)
              print("[hint] 配置: export REDFOX_API_KEY=ak_xxxx...", file=sys.stderr)
              sys.exit(1)
          return val
      
      
      def extract_bv_id(input_str: str) -> str:
          """从用户输入中提取 BV号(支持直接 BV号或完整链接)"""
          input_str = input_str.strip()
          # 匹配 BV号(以 BV 开头,后跟字母数字)
          match = re.search(r"(BV[A-Za-z0-9]+)", input_str)
          if match:
              return match.group(1)
          return input_str
      
      
      def fetch_work_detail(bv_id: str, api_key: str) -> dict:
          """获取作品详情(同步接口,POST JSON)"""
          payload = {
              "bvid": bv_id,
              "source": "B站评论分析-GitHub",
          }
          result = api_request(WORK_DETAIL_API, payload, api_key)
      
          code = result.get("code")
          if code != 2000:
              print(f"[warn] 获取作品详情失败: code={code}, msg={result.get('msg', '未知')}", file=sys.stderr)
              return {}
      
          data = result.get("data") or {}
          if not data:
              return {}
      
          # 发布时间(时间戳转字符串)
          publish_time = data.get("publishTime") or ""
          if isinstance(publish_time, (int, float, str)):
              try:
                  ts = int(publish_time)
                  if ts > 1000000000:
                      publish_time = datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
              except (ValueError, TypeError):
                  publish_time = str(publish_time)
      
          # 时长(秒转 MM:SS)
          duration = data.get("duration") or 0
          if isinstance(duration, (int, float)):
              mins = int(duration) // 60
              secs = int(duration) % 60
              duration_str = f"{mins}:{secs:02d}"
          else:
              duration_str = str(duration)
      
          owner = data.get("owner") or {}
          stats = data.get("stats") or {}
      
          return {
              "title": data.get("title") or "",
              "author_name": owner.get("nickname") or "",
              "author_uid": str(owner.get("uid") or ""),
              "author_avatar": owner.get("avatar") or "",
              "cover": data.get("cover") or "",
              "publish_time": publish_time,
              "duration": duration_str,
              "view_count": stats.get("viewCount") or 0,
              "like_count": stats.get("likeCount") or 0,
              "coin_count": stats.get("coinCount") or 0,
              "favorite_count": stats.get("favoriteCount") or 0,
              "share_count": stats.get("shareCount") or 0,
              "reply_count": stats.get("replyCount") or 0,
              "danmaku_count": stats.get("danmakuCount") or 0,
          }
      
      
      def api_request(url: str, payload: dict, api_key: str) -> dict:
          """通用 API 请求函数"""
          data = json.dumps(payload).encode("utf-8")
          req = urllib.request.Request(
              url,
              data=data,
              headers={
                  "Content-Type": "application/json",
                  "X-API-Key": api_key,
                  "User-Agent": "QoderWork/1.0",
              },
              method="POST",
          )
      
          try:
              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")
              print(f"[error] HTTP {e.code}: {body}", file=sys.stderr)
              sys.exit(1)
          except urllib.error.URLError as e:
              print(f"[error] 网络请求失败: {e.reason}", file=sys.stderr)
              sys.exit(1)
          except (json.JSONDecodeError, KeyError, TypeError) as e:
              print(f"[error] 数据解析异常: {e}", file=sys.stderr)
              sys.exit(1)
      
          return result
      
      
      def submit_comment_task(bv_id: str, offset: int, api_key: str, sort_type: str = "1", data_num: int = PAGE_SIZE) -> str:
          """提交评论查询任务,返回 taskId
          
          API 必填参数:opusId(视频标识)、sortType(排序方式)、dataNum(每页条数)
          """
          payload = {
              "opusId": bv_id,
              "sortType": sort_type,
              "dataNum": str(data_num),
              "offset": str(offset),
              "source": "B站评论分析-GitHub",
          }
      
          result = api_request(SUBMIT_API, payload, api_key)
      
          code = result.get("code")
          if code != 2000:
              print(f"[error] 提交任务失败: code={code}, msg={result.get('msg', '未知')}", file=sys.stderr)
              sys.exit(1)
      
          data = result.get("data") or {}
          task_id = data.get("taskId") or data.get("task_id") or ""
          if not task_id:
              # 某些接口可能直接在 data 中返回结果(非异步),将完整 data 作为结果返回
              return "__direct__"
          return task_id
      
      
      def poll_comment_result(task_id: str, api_key: str) -> dict:
          """轮询评论结果(POST + form-urlencoded),直到数据就绪或超时。
          
          commentResult 接口要求 POST + application/x-www-form-urlencoded 格式。
          """
          for attempt in range(MAX_POLL_ATTEMPTS):
              form_data = urllib.parse.urlencode({
                  "taskId": task_id,
                  "source": "B站评论分析-GitHub",
              }).encode("utf-8")
              req = urllib.request.Request(
                  RESULT_API,
                  data=form_data,
                  headers={
                      "Content-Type": "application/x-www-form-urlencoded",
                      "X-API-Key": api_key,
                      "User-Agent": "QoderWork/1.0",
                  },
                  method="POST",
              )
      
              try:
                  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")
                  print(f"[error] HTTP {e.code}: {body}", file=sys.stderr)
                  sys.exit(1)
              except urllib.error.URLError as e:
                  print(f"[error] 网络请求失败: {e.reason}", file=sys.stderr)
                  sys.exit(1)
              except (json.JSONDecodeError, KeyError, TypeError) as e:
                  print(f"[error] 数据解析异常: {e}", file=sys.stderr)
                  sys.exit(1)
      
              code = result.get("code")
              if code != 2000:
                  print(f"[error] 查询结果失败: code={code}, msg={result.get('msg', '未知')}", file=sys.stderr)
                  sys.exit(1)
      
              data = result.get("data") or {}
      
              # 检查任务状态
              status = data.get("status") or data.get("state") or ""
              if status in ("pending", "processing", "running"):
                  print(f"[poll] 第 {attempt + 1} 次轮询,任务状态: {status},等待 {POLL_INTERVAL}s...", file=sys.stderr)
                  time.sleep(POLL_INTERVAL)
                  continue
      
              # 任务完成或数据已就绪
              return result
      
          print(f"[error] 评论数据获取超时(已轮询 {MAX_POLL_ATTEMPTS} 次),请稍后重试", file=sys.stderr)
          sys.exit(1)
      
      
      def format_comment(raw: dict) -> dict:
          """将 API 返回的原始评论格式化为统一结构
      
          commentResult 实际返回字段:
          commentId, content, likeNum, createTime, ipLocation,
          nickname, commenterUid, avatar, avId, isPinned, pictures
          
          输出字段:用户昵称、用户ID、评论内容、点赞数、评论时间、IP属地
          """
          user_name = (raw.get("nickname") or raw.get("authorName") or "").strip()
          user_id = str(raw.get("commenterUid") or raw.get("authorUid") or "")
      
          content = raw.get("content") or raw.get("message") or raw.get("text") or ""
          if isinstance(content, dict):
              content = content.get("message", "") or content.get("content", "")
      
          like_count = raw.get("likeNum") or raw.get("like") or raw.get("likeCount") or 0
      
          create_time = raw.get("createTime") or raw.get("ctime") or raw.get("publishTime") or ""
          if isinstance(create_time, (int, float)) and create_time > 1000000000:
              try:
                  create_time = datetime.fromtimestamp(int(create_time)).strftime("%Y-%m-%d %H:%M:%S")
              except Exception:
                  create_time = str(create_time)
      
          ip_raw = raw.get("ipLocation") or ""
          ip_location = ip_raw.replace("IP属地:", "").replace("IP属地:", "").strip()
      
          return {
              "user_name": user_name,
              "user_id": user_id,
              "content": str(content).strip(),
              "like_count": int(like_count) if like_count else 0,
              "create_time": str(create_time),
              "ip_location": ip_location,
          }
      
      
      def fetch_comments(bv_id: str, page: int, api_key: str, sort_type: str = "1") -> tuple:
          """
          两步获取评论:提交任务 → 轮询结果。
          返回 (comments_list, has_next, total_count)
          """
          offset = (page - 1) * PAGE_SIZE
      
          # Step 1: 提交任务
          task_id = submit_comment_task(bv_id, offset, api_key, sort_type=sort_type)
      
          # Step 2: 获取结果
          if task_id == "__direct__":
              payload = {
                  "opusId": bv_id,
                  "sortType": sort_type,
                  "dataNum": str(PAGE_SIZE),
                  "offset": str(offset),
                  "source": "B站评论分析-GitHub",
              }
              result = api_request(SUBMIT_API, payload, api_key)
          else:
              result = poll_comment_result(task_id, api_key)
      
          data = result.get("data") or {}
      
          # 评论列表
          comment_list = data.get("commentList") or data.get("comments") or []
          if not isinstance(comment_list, list):
              comment_list = []
      
          all_comments = [format_comment(c) for c in comment_list]
      
          # 分页判断:基于 total/received 字段
          total_count = data.get("total", 0) or 0
          received = data.get("received", 0) or 0
          has_next = bool(data.get("hasMore") or data.get("has_next") or False)
          if not has_next:
              # 如果 offset + 本页数量 < 总评论数,说明还有下一页
              has_next = (offset + len(all_comments)) < total_count
      
          return all_comments, has_next, total_count
      
      
      def escape_html(text: str) -> str:
          """HTML 实体转义"""
          return (
              (text or "")
              .replace("&", "&amp;")
              .replace("<", "&lt;")
              .replace(">", "&gt;")
              .replace('"', "&quot;")
          )
      
      
      def build_comment_rows(comments: list) -> str:
          """根据评论列表生成 HTML 表格行"""
          rows = []
          for c in comments:
              name = escape_html(c.get("user_name", ""))
              uid = escape_html(c.get("user_id", ""))
              content = escape_html(c.get("content", ""))
              like = c.get("like_count", 0) or 0
              time_str = (c.get("create_time", "") or "")[5:16]  # MM-DD HH:MM
              ip = escape_html(c.get("ip_location", ""))
      
              user_url = f"https://space.bilibili.com/{uid}" if uid and uid != "0" else "#"
      
              row = (
                  f'<tr>'
                  f'<td><a href="{user_url}" target="_blank" class="user-name">{name}</a></td>'
                  f'<td class="uid-cell">{uid}</td>'
                  f'<td class="content-cell">{content}</td>'
                  f'<td class="num-cell">{like}</td>'
                  f'<td class="time-cell">{time_str}</td>'
                  f'<td class="ip-cell">{ip}</td>'
                  f'</tr>'
              )
              rows.append(row)
          return "\n".join(rows)
      
      
      def generate_html_report(bv_id: str, current_page: int, comments: list, work_detail: dict = None, output_dir: str = None) -> str:
          """读取 HTML 模板,填充评论数据,生成报告文件。返回生成的 HTML 文件绝对路径。"""
          template_path = os.path.normpath(TEMPLATE_PATH)
          if not os.path.exists(template_path):
              print(f"[warn] 模板文件不存在: {template_path},跳过 HTML 生成", file=sys.stderr)
              return ""
      
          with open(template_path, "r", encoding="utf-8") as f:
              html = f.read()
      
          total = len(comments)
          now = datetime.now()
          total_likes = sum(c.get("like_count", 0) or 0 for c in comments)
      
          wd = work_detail or {}
          replacements = {
              "{{VIDEO_ID}}": escape_html(bv_id),
              "{{DATE}}": now.strftime("%Y-%m-%d"),
              "{{TOTAL_COMMENTS}}": str(total),
              "{{COMMENT_ROWS}}": build_comment_rows(comments),
              "{{TIMESTAMP}}": now.strftime("%Y-%m-%d %H:%M:%S"),
              "{{TOTAL_LIKES}}": str(total_likes),
              "{{PAGE}}": str(current_page),
              "{{TITLE}}": escape_html(wd.get("title") or ""),
              "{{AUTHOR_NAME}}": escape_html(wd.get("author_name") or ""),
              "{{AUTHOR_UID}}": escape_html(wd.get("author_uid") or ""),
              "{{AUTHOR_AVATAR}}": wd.get("author_avatar") or "",
              "{{COVER}}": wd.get("cover") or "",
              "{{PUBLISH_TIME}}": escape_html(wd.get("publish_time") or ""),
              "{{DURATION}}": escape_html(wd.get("duration") or ""),
              "{{VIEW_COUNT}}": str(wd.get("view_count") or 0),
              "{{LIKE_COUNT}}": str(wd.get("like_count") or 0),
              "{{COIN_COUNT}}": str(wd.get("coin_count") or 0),
              "{{FAVORITE_COUNT}}": str(wd.get("favorite_count") or 0),
              "{{SHARE_COUNT}}": str(wd.get("share_count") or 0),
              "{{REPLY_COUNT}}": str(wd.get("reply_count") or 0),
              "{{DANMAKU_COUNT}}": str(wd.get("danmaku_count") or 0),
          }
      
          for key, val in replacements.items():
              html = html.replace(key, val)
      
          # 确定输出目录
          if output_dir:
              out_dir = os.path.expanduser(output_dir)
          else:
              out_dir = os.path.expanduser("~/Downloads/QoderReports")
          os.makedirs(out_dir, exist_ok=True)
      
          filename = f"B站评论分析_{bv_id}_p{current_page}.html"
          file_path = os.path.join(out_dir, filename)
      
          with open(file_path, "w", encoding="utf-8") as f:
              f.write(html)
      
          print(f"[html] HTML 报告已生成: {file_path}", file=sys.stderr)
          return file_path
      
      
      def main():
          parser = argparse.ArgumentParser(description="B站视频评论查询")
          parser.add_argument("bv_id", help="B站视频 BV号、AV号或完整链接")
          parser.add_argument(
              "--page", dest="page", type=int, default=1,
              help="页码,从1开始(默认1,每页20条)",
          )
          parser.add_argument(
              "--sort", dest="sort_type", default="1", choices=["1", "2", "3"],
              help="排序方式:1-按时间 2-按热度 3-按回复数(默认1)",
          )
          parser.add_argument(
              "--no-html", dest="no_html", action="store_true",
              help="跳过 HTML 报告生成",
          )
          parser.add_argument(
              "--output-dir", dest="output_dir", type=str, default=None,
              help="HTML 输出目录(默认 ~/Downloads/QoderReports)",
          )
      
          args = parser.parse_args()
      
          bv_id = extract_bv_id(args.bv_id)
          if not bv_id:
              print("[error] 视频ID不能为空", file=sys.stderr)
              sys.exit(1)
          if args.page < 1:
              print("[error] 页码必须为正整数", file=sys.stderr)
              sys.exit(1)
      
          api_key = get_api_key()
      
          # 获取作品详情(同步接口,与评论获取并行逻辑但顺序执行)
          work_detail = fetch_work_detail(bv_id, api_key)
      
          comments, has_next, total_count = fetch_comments(bv_id, args.page, api_key, sort_type=args.sort_type)
      
          total = len(comments)
      
          output = {
              "work_detail": work_detail,
              "total_count": total_count,
              "total_fetched": total,
              "has_next": has_next,
              "comments": comments,
          }
      
          # HTML 报告生成
          if not args.no_html:
              html_path = generate_html_report(
                  bv_id=bv_id,
                  current_page=args.page,
                  comments=comments,
                  work_detail=work_detail,
                  output_dir=args.output_dir,
              )
              output["html_path"] = html_path
      
          print(json.dumps(output, ensure_ascii=False, indent=2))
      
      
      if __name__ == "__main__":
          main()
      
  • README.en.md 5.1 KB
    # Bilibili Comment Analyzer / bilibili-comment
    
    ---
    
    ## Overview
    
    Enter any Bilibili video link or BV ID to **instantly retrieve comment data**. AI automatically performs four-dimension sentiment analysis (positive / negative / demand / competitor) and generates an interactive HTML report for offline saving.
    
    **Feature Overview**
    
    Bilibili Comment Analyzer is an intelligent comment insight tool built for content creators, UP owners, and brand operators. It pulls first-level comments in real time via the RedFox API — 20 comments per page with pagination support. The AI deeply understands Bilibili meme culture (awsl / yyds / 爷青回 and other barrage slang) and delivers four-dimension analysis with representative comment citations, then generates a dark-themed interactive HTML report for easy saving and sharing.
    
    **Core Value**
    
    - **Real-time comment retrieval**: Paste a link and get the latest comments instantly — no manual scrolling through the comment section.
    - **Bilibili meme culture understanding**: AI identifies barrage slang and meme context for more accurate analysis results.
    - **Structured four-dimension analysis**: Positive / negative / demand / competitor layers clearly separated, each with representative comment citations to capture the core of public sentiment quickly.
    
    **Intended Users**
    
    - 🎬 **UP owners** — Review audience feedback and refine topic and content strategy.
    - 🏢 **Brand operators** — Monitor public sentiment and detect user voices and risk signals promptly.
    - 📊 **Content planners / product managers** — Mine competitor comments and research genuine user needs.
    
    ---
    
    ## Features
    
    ### Core Capabilities
    
    - **Comment retrieval**: Enter a BV ID or video link to automatically pull first-level comments, 20 per page
    - **Pagination**: Navigate with natural language — "next page", "page 3", etc. — to browse large volumes of comments progressively
    - **Four-dimension AI analysis**: Positive / negative / demand / competitor sentiment analysis, each with representative comment citations and percentage breakdown
    - **Pinned comment marking**: Pinned comments are specially highlighted for quick identification
    - **HTML report**: Dark-themed interactive report for offline saving and sharing
    
    ### Highlights
    
    - **Bilibili meme culture understanding**: Recognizes awsl / yyds / xswl / 爷青回 / 下次一定 and other barrage slang in their real context
    - **Complete data display**: Work details (views / likes / coins / favorites / danmaku, etc.) and full comment table — no truncation
    - **Encoding-safe backfill**: Intelligent encoding ensures Chinese analysis content is injected into reports without corruption
    
    ---
    
    ## API Key Acquisition & Security
    
    - This skill requires the environment variable: `REDFOX_API_KEY`.
    - `REDFOX_API_KEY` is issued by [RedFox Hub](https://redfox.hk/settings/api-keys?source=github) (`https://redfox.hk`).
    - Register at [RedFox Hub](https://redfox.hk?source=github) to obtain `REDFOX_API_KEY`.
    - Configure `REDFOX_API_KEY` as a device environment variable 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 video in natural language — no fixed commands to memorize.
    
    ### Quick Reference
    
    | Intent | Example phrase | Result |
    |--------|---------------|--------|
    | View video comments | "Show me the comments for BV1xx411c7mD" | Fetches page 1 comments + AI summary |
    | Query via link | Paste `https://www.bilibili.com/video/BV1xx411c7mD` | Auto-extracts BV ID and retrieves comments |
    | Paginate | "Next page" / "Page 3" | Reuses current video BV ID, fetches specified page |
    | Generate report | "Yes" / "Generate HTML" | Backfills AI analysis, generates interactive HTML report |
    
    ### Output Example
    
    After a successful query, you receive in sequence:
    
    **Work Details**
    
    > 🎬 **Video Title**
    >
    > UP: [Username](profile link) | Published: 2024-01-01 | Duration: 12:34
    >
    > ▶ 12.5w 👍 3.2w 🪙 1.8w ⭐ 2.1w 🔄 5.6k 💬 1.2k 📝 8.9k
    
    **Comment Table** (all comments on current page)
    
    | # | Username | Comment | 👍 | Time | IP |
    |---|---------|---------|-----|------|-----|
    | 1 | [Username](profile) | Comment content... | 1223 | 01-12 15:30 | Guangdong |
    
    **Four-dimension Sentiment Analysis** (AI summary with representative citations)
    
    **Prompt asking whether to generate an HTML visualization report**
    
    ---
    
    ## Use Cases
    
    | Scenario | Role | Example question | Benefit |
    |----------|------|-----------------|---------|
    | Content review | UP owner | "How are the comments on this video?" | Quickly understand audience feedback and refine content strategy |
    | Sentiment monitoring | Brand operator | "Analyze the negative comments on this video" | Detect crisis signals early and plan response |
    | Competitor analysis | Content planner | "Analyze user comments on a competitor's video" | Understand competitor strengths and weaknesses to find differentiation |
    | User research | Product manager | "What user needs are mentioned in the comments?" | Uncover genuine needs to guide product iteration |
    
    ---
    
  • README.md 4.4 KB
    # B站评论分析 / bilibili-comment
    
    ---
    
    ## 简介
    
    输入任意B站视频链接或BV号,**一键获取评论数据**,AI 自动完成四维情感分析(积极/负面/需求/竞品),同时生成可离线保存的交互式 HTML 报告。
    
    **功能介绍**
    
    B站评论分析是专为内容创作者、UP主和品牌运营打造的智能评论洞察工具。基于红狐 API 实时拉取视频一级评论,每页20条,支持分页浏览;AI 深度理解B站梗文化(awsl / yyds / 爷青回 等弹幕术语),完成积极/负面/需求/竞品四维分析并引用代表评论;最终生成深色主题交互式 HTML 报告,便于保存与分享。
    
    **核心价值**
    
    - **实时评论拉取**:粘贴链接即可获取最新评论,无需手动翻找评论区。
    - **B站梗文化理解**:AI 识别弹幕术语和梗的真实语境,分析结果更准确。
    - **结构化四维分析**:积极/负面/需求/竞品清晰分层,各维度附代表评论引用,快速抓住舆情核心。
    
    **适用对象**
    
    - 🎬 **UP主** — 复盘视频反馈,优化选题和内容策略。
    - 🏢 **品牌运营** — 监测舆情,及时发现用户声音和风险信号。
    - 📊 **内容策划 / 产品经理** — 挖掘竞品评论,研究用户真实需求。
    
    ---
    
    ## 功能特性
    
    ### 核心功能
    
    - **评论获取**:输入BV号或视频链接,自动拉取一级评论,每页20条
    - **分页浏览**:支持「下一页」「第N页」等自然语言翻页,逐步浏览大量评论
    - **四维 AI 分析**:积极/负面/需求/竞品四类情感分析,各附代表评论引用,百分比展示
    - **置顶标记**:置顶评论特殊标识,一眼识别重要内容
    - **HTML 报告**:深色主题交互式报告,支持离线保存与分享
    
    ### 特色亮点
    
    - **B站梗文化理解**:识别 awsl / yyds / xswl / 爷青回 / 下次一定 等弹幕术语及梗的真实含义
    - **数据完整展示**:作品详情(播放/点赞/投币/收藏/弹幕等)与评论表格全量呈现
    - **编码安全回填**:智能编码保障,中文分析内容完整无误地注入报告
    
    ---
    
    ## 密钥获取与安全说明
    
    - 本技能需要使用环境变量:`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` 后使用本技能。
    - 在提供密钥前,请先确认密钥来源、可用范围、有效期及是否支持重置/撤销。
    - 禁止在代码、提示词、日志或输出文件中硬编码/明文暴露密钥。
    
    ---
    
    ## 使用指南
    
    直接用自然语言说出视频链接或BV号即可,无需记忆固定命令。
    
    ### 常用说法速查
    
    | 意图 | 示例话术 | 效果 |
    |------|---------|------|
    | 查看视频评论 | 「查看B站视频 BV1xx411c7mD 的评论」 | 获取第1页评论 + AI总结 |
    | 通过链接查询 | 粘贴 `https://www.bilibili.com/video/BV1xx411c7mD` | 自动提取BV号并拉取评论 |
    | 翻页 | 「下一页」「第3页」 | 沿用当前视频,获取指定页评论 |
    | 生成报告 | 「需要」「生成HTML」 | 回填AI分析,生成交互式HTML报告 |
    
    ### 输出示例
    
    完成查询后,你将依次收到:
    
    **作品详情**
    
    > 🎬 **视频标题**
    >
    > UP主:[昵称](主页链接) | 发布:2024-01-01 | 时长:12:34
    >
    > ▶ 12.5w 👍 3.2w 🪙 1.8w ⭐ 2.1w 🔄 5.6k 💬 1.2k 📝 8.9k
    
    **评论表格**(当前页全部评论)
    
    | # | 用户昵称 | 评论内容 | 👍 | 时间 | IP |
    |---|---------|---------|-----|------|-----|
    | 1 | [用户名](主页) | 评论内容... | 1223 | 01-12 15:30 | 广东 |
    
    **四维情感分析**(AI总结,含代表评论引用)
    
    **询问是否生成 HTML 可视化报告**
    
    ---
    
    ## 使用场景
    
    | 场景 | 角色 | 示例问法 | 收益 |
    |------|------|---------|------|
    | 内容复盘 | UP主 | 「看看这个视频的评论怎么样」 | 快速了解观众反馈,优化选题策略 |
    | 舆情监测 | 品牌运营 | 「分析这条视频的负面评论」 | 及时发现危机信号,制定应对方案 |
    | 竞品分析 | 内容策划 | 「分析竞品视频的用户评论」 | 了解竞品优劣势,找准差异化方向 |
    | 用户研究 | 产品经理 | 「看看用户在评论区提了哪些需求」 | 挖掘真实需求,指导产品迭代 |
    
    ---
    
  • SKILL.md 5.8 KB
    ---
    name: bilibili-comment
    description: B站评论分析工具。输入B站视频链接或BV号即可获取一级评论数据,支持分页浏览、评论情感分析(积极/负面/需求/竞品),生成精美 HTML 报告。当用户需要查看B站视频评论、分析评论舆情、了解用户反馈时使用。触发词:B站评论、B站视频评论、评论查询、评论分析、评论舆情、看评论、bilibili评论。
    ---
    
    # B站评论分析
    
    ## 简介
    
    B站评论分析是一款专为内容创作者、UP主、品牌运营和研究人员设计的智能评论洞察工具。输入任意B站视频链接或BV号,即可一键获取评论数据,并通过四维情感分析(积极/负面/需求/竞品)快速了解用户真实反馈,同时生成可离线保存的交互式 HTML 报告。
    
    通过本技能,你可以:
    - 📊 逐页获取视频一级评论(每页20条,支持翻页)
    - 🤖 AI 自动完成四维情感分析,理解B站梗文化
    - 📋 生成深色主题交互式 HTML 报告,便于保存与分享
    
    适用于 UP主复盘、品牌舆情监测、竞品分析、内容策略研究等场景。
    
    ## 功能特性
    
    ### 核心功能
    
    - **评论获取**:粘贴视频链接或BV号即可拉取最新评论数据
    - **分页浏览**:每页20条,支持前后翻页,逐步浏览大量评论
    - **四维 AI 分析**:积极/负面/需求/竞品四类情感分析,各维度附代表评论引用
    - **置顶标记**:置顶评论特殊标识,一眼识别重要内容
    - **HTML 报告**:深色主题交互式报告,支持离线保存与分享
    
    ### 特色亮点
    
    - **B站梗文化理解**:识别弹幕术语、缩写(awsl / yyds / xswl / 爷青回 等)及热门梗的真实语境
    - **数据完整展示**:作品详情(播放/点赞/投币/收藏/弹幕等)与评论表格全量展示,不截断
    - **编码安全回填**:智能编码保障,中文分析内容完整无误地注入报告
    
    ## 鉴权
    
    - 获取 API Key:前往 [红狐hub](https://redfox.hk/settings/api-keys?source=github)
    - 配置方式1:写入 `~/.openclaw/openclaw.json` → `{ "env": { "REDFOX_API_KEY": "ak_xxxx..." } }`
    - 配置方式2:终端执行 `export REDFOX_API_KEY="ak_xxxx..."`
    
    ## 工作流程
    
    > 核心执行流程详见 `references/core_workflow.md`
    
    ## 使用指南
    
    直接用自然语言说出视频链接或BV号即可,无需记忆固定命令。
    
    ### 常用说法速查
    
    | 意图 | 示例话术 | 效果 |
    |------|---------|------|
    | 查看视频评论 | 「查看B站视频 BV1xx411c7mD 的评论」 | 获取第1页评论 + AI总结 |
    | 通过链接查询 | 粘贴 `https://www.bilibili.com/video/BV1xx411c7mD` | 自动提取BV号并拉取评论 |
    | 翻页 | 「下一页」「第3页」 | 沿用当前视频,获取指定页评论 |
    | 生成报告 | 「需要」「生成HTML」 | 回填AI分析,生成交互式HTML报告 |
    
    ### 输出示例
    
    完成查询后,你将依次收到:
    
    1. **作品详情**(标题、UP主、播放量、点赞等核心数据)
    2. **评论表格**(当前页全部评论,含昵称链接、内容、点赞数、时间、IP属地)
    3. **四维情感分析**(积极/负面/需求/竞品,各附代表评论)
    4. **询问是否生成 HTML 报告**
    
    ## 使用场景
    
    | 场景 | 角色 | 示例问法 | 收益 |
    |------|------|---------|------|
    | 内容复盘 | UP主 | 「看看这个视频的评论怎么样」 | 快速了解观众反馈,优化选题策略 |
    | 舆情监测 | 品牌运营 | 「分析这条视频的负面评论」 | 及时发现危机信号,制定应对方案 |
    | 竞品分析 | 内容策划 | 「分析竞品视频的用户评论」 | 了解竞品优劣势,找准差异化方向 |
    | 用户研究 | 产品经理 | 「看看用户在评论区提了哪些需求」 | 挖掘真实需求,指导产品迭代 |
    
    ## 项目架构
    
    ```
    bilibili-comment/
    ├── SKILL.md                    # 技能配置与使用说明
    ├── references/
    │   └── core_workflow.md        # Agent 核心执行流程
    ├── assets/
    │   └── report_template.html    # HTML 报告模板
    └── scripts/
        ├── bili_comment_search.py  # 评论获取脚本(调用 API,自动生成 HTML)
        └── backfill_html.py        # AI 分析回填脚本(将分析结果写入 HTML)
    ```
    
    | 模块 | 职责 |
    |------|------|
    | `bili_comment_search.py` | 调用红狐 API 获取评论数据,生成含占位符的 HTML 报告 |
    | `backfill_html.py` | 将 AI 四维分析 JSON 安全回填至 HTML 报告,支持文件直读模式 |
    | `report_template.html` | 深色主题交互式报告模板 |
    
    技术栈:Python 标准库(`urllib`),无需额外安装依赖。
    
    ## 常见问答
    
    ### 安装相关
    
    **Q1: 如何获取 REDFOX_API_KEY?**
    
    A: 前往 [红狐hub](https://redfox.hk/settings/api-keys?source=github) 注册账号并申请 API Key,按鉴权章节说明配置到本地环境变量。
    
    **Q2: 需要安装额外依赖吗?**
    
    A: 不需要。脚本使用 Python 标准库 `urllib`,Python 3.6+ 环境即可直接运行。
    
    ### 使用相关
    
    **Q3: 一次能获取多少条评论?**
    
    A: 每次调用获取1页(20条)。如需更多数据,通过翻页命令逐页获取,或前往 [红狐平台](https://redfox.hk?source=github) 联系客服获取批量能力。
    
    **Q4: 支持获取二级评论(回复)吗?**
    
    A: 当前版本仅支持一级评论,二级回复暂不支持。
    
    ### 故障排除
    
    **Q5: HTML 报告中部分中文显示乱码(问号)怎么办?**
    
    A: 这是编码回填环节的兼容性问题。解决方案:用 Python 写入分析数据为 UTF-8 JSON 文件,再使用 `backfill_html.py --json-file` 直接读取回填。详见 `references/core_workflow.md` Step 3。
    
    **Q6: 如有其他问题如何获取帮助?**
    
    A: 前往 [红狐平台](https://redfox.hk?source=github) 联系客服,或查阅技能文档。
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related