Claude Skill

weibo-comment-search

微博评论分析工具。输入微博博文链接即可获取一级评论数据,支持分页浏览和四维情感分析(积极/负面/需求/竞品)。当用户需要查看微博评论、分析评论舆情、了解用户反馈时使用。触发词:微博评论、博文评论、评论查询、评论分析、看评论。

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_weibo-comment-search-5e7b435.zip · 16 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/weibo-comment-search
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

微博评论分析 / weibo-comment-search


简介

输入微博博文链接就能看到这条博文的评论,谁评论了什么、被点赞多少次、什么时候发的都一目了然,点用户昵称还能直接跳转到 TA 的微博主页,给到你的都是平台刚更新的新鲜数据,不会拿旧缓存糊弄你。

核心价值

  • 内容新鲜不滞后:每次查询直接拉取平台最新评论,只给你刚发布的数据,不是过期存档。
  • 用户身份一眼知:评论人昵称直接可点,跳转到微博主页,快速了解评论者身份。
  • 翻页随心浏览:海量评论支持分页翻阅,一句「下一页」继续看更多内容。

适用对象

  • 🔍 内容运营 / 竞品分析 — 查看目标博文的用户反馈,了解互动热度
  • 📊 舆情监测 — 追踪特定博文下的舆论风向,第一时间发现关键评论
  • �� 创作者研究 — 了解粉丝评论内容和互动水平

功能特性

核心功能

  • 评论查询:输入微博博文链接或 opusId,查询该博文的一级评论。
  • 分页浏览:支持多页结果浏览,按需查看更多评论。

密钥获取与安全说明

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

使用指南

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

常用说法速查

意图 示例话术 效果
查看评论 「查下 https://weibo.com/1784473157/R8X4f2lnq 的评论」 提取 opusId 后查询并展示评论
直接给 opusId 「查 R8X4f2lnq 的评论」 直接用 opusId 查询
翻页查看 「下一页」/ 「上一页」 切换当前结果页码

输出示例

查询完成后,你将收到如下格式的结果:

📊 博文 R8X4f2lnq 查询到 20 条评论(第 1 页),以下是详细数据:

# 用户 评论内容 点赞 发布时间
1 用户A 说得太对了,支持! 305 2025-07-10 14:30:25
2 用户B 这条博文很有深度... 1.2w 2025-07-10 12:15:30

📄 当前第 1 页。回复「下一页」继续查看。


使用场景

场景 角色 示例问法 收益
评论舆情分析 内容运营 「查下这条微博的评论」 快速了解用户对博文的反馈
热点追踪 舆情 「看看这条热搜的评论风向」 掌握舆论趋势和用户态度
竞品评论研究 创作者 「看下同行博文下的评论」 了解同类内容受众互动水平

Skill manifest

微博评论分析

📝 简介

微博评论分析工具,输入微博博文链接,即可查看该博文的一级评论数据,支持分页浏览和 AI 情感分析。在对话中展示当前页全部评论及 AI 总结分析,同时生成包含当前页数据和总结的交互式 HTML 报告。

✨ 功能特性

功能模块 能力描述 核心价值
评论查询 输入微博博文链接查询评论 一键查看任意博文的评论
分页浏览 支持多页结果浏览 逐页探索更多评论
AI 总结 四维情感分析(积极/负面/需求/竞品) 快速了解评论舆情全貌
HTML 报告 深色主题交互式报告 离线保存/分享分析结果

🔑 鉴权

获取 API Key

请前往 红狐hub 获取 API KEY

配置 API Key

方案1: 以 Qoder 为例,将 REDFOX_API_KEY 添加到 ~/.openclaw/openclaw.json 中:

{ "env": { "REDFOX_API_KEY": "ak_xxxx..." } }

方案2: 终端配置

export REDFOX_API_KEY="ak_xxxx..."

🔄 工作流程

Step 1:理解用户意图,提取 opusId

1. 从微博博文链接中提取 opusId

  • 若用户提供了博文链接(如 https://weibo.com/1784473157/R8X4f2lnq),从中提取 opusId(R8X4f2lnq)
  • 若用户直接提供了 opusId,直接使用
  • 若用户意图模糊(如"帮我查下评论"),主动询问:「请提供微博博文链接」
  • 不得在用户未提供链接时擅自猜测并调用脚本
  • 若用户在上一轮对话中查询过某博文的评论,且本轮输入模糊(如"下一页"、"评论分析"),沿用上一轮的 opusId

2. 识别页码参数

  • 用户提到"下一页"、"第2页" → 对应页码,同时使用上一轮返回的 max_cursor
  • 用户提到"上一页" → 当前页 - 1
  • 未提及页码 → 默认第 1 页

Step 2:调用查询脚本(自动生成 HTML)

⚠️ 每次调用仅请求一页数据(一次 API 请求),不可擅自发起多次调用拉取多页。

脚本每次调用自动生成 HTML 报告(含 {{PLACEHOLDER}} 占位符,未回填分析数据)。终端展示与 HTML 基于同一次 API 调用,确保数据一致。

python3 ~/.agents/skills/weibo-comment-search/scripts/weibo_comment_search.py "<博文链接或opusId>" [--page 页码] [--cursor 游标] [--output-dir 目录]

参数说明:

参数 说明 默认值
input 微博博文链接或 opusId —
--page 页码,从1开始 1
--cursor 翻页游标(首页为 0,后续从返回的 max_cursor 传入) 0
--no-html 跳过 HTML 报告生成 —
--output-dir HTML 输出目录 ~/Downloads/QoderReports

脚本以 JSON 格式输出:

字段 说明
opus_id 博文 opusId
comments 评论列表
max_cursor 下一页游标
has_next 是否有下一页(true/false)
page 当前页码
html_path 生成的 HTML 报告路径(含占位符,待回填)

每条评论字段:

字段 说明
nickname 用户昵称
uid 用户 uid
user_url 用户主页链接(https://weibo.com/{uid})
content 评论内容
comment_like_num 点赞数(原始数字)
comment_like_num_fmt 点赞数(格式化后)
create_time 发布时间

注意: HTML 报告此时仅含评论原始数据,分析占位符({{PLACEHOLDER}})待用户确认后回填。

Step 3:判断结果并展示

情况 A:comments 数量 > 0(有评论)

A1. 告知用户查询范围

📊 博文 {opus_id} 查询到 N 条评论(第 页),以下是详细数据:

A2. 渲染 Markdown 表格(全部展示)

| # | 用户 | 评论内容 | 点赞 | 发布时间 |
|---|------|----------|------|----------|
| 1 | [nickname](https://weibo.com/uid) | 评论内容 | 305 | 2025-07-10 14:30:25 |

格式规则:

  • 用户昵称渲染为超链接:[nickname](user_url),跳转到用户主页
  • 点赞数 < 10000 原始数字,≥ 10000 显示 x.xw
  • 发布时间完整展示年月日时分秒
  • 评论内容超过 50 字截断并加 ...,内容为空时显示 -
  • ⚠️ 当前页全部评论均需展示,不得截断

A3. AI 评论总结(⚠️ 每次查询(含翻页)必须输出)

首页:基于当前页获取到的全部评论,进行四维情感分析。

翻页后:基于目前已获取的所有页面累计数据进行综合分析,而非仅分析当前单页。分析时需标注累计总条数。

分析前需理解微博热点话题背景(热搜事件、粉丝文化、明星动态、社会议题语境)。

📈 评论总结分析(基于

✅ 积极评价(

  • {要点1}
  • {要点2}
  • ...

⚠️ 负面评价(

  • {要点1}
  • {要点2}
  • ...

💡 用户需求(

  • {要点1}
  • {要点2}
  • ...

🔍 竞品对比舆情(

  • {仅当评论中提及竞品时输出,否则输出「未提及竞品」}
  • {竞品名称}:{舆情要点}

分析要求:

  • 每条要点需引用代表评论(截取关键词/短语)
  • 百分比为提及该类型评论的数量占总评论数的比例
  • 积极/负面/需求/竞品四类占比总和可能超过 100%(一条评论可能同时包含多类信息)
  • 必须理解微博语境:识别粉丝话术(如"抱走""纯路人""yyds""打call"等)、热门话题背景、明星相关舆情

A4. 翻页提示(⚠️ 紧接在 A3 之后,每次必须输出)

  • 若 has_next 为 true:

📄 当前第 页。回复「下一页」继续查看。

  • 若 has_next 为 false:

📄 当前第 页,已无更多数据。

⚠️ A1~A4 必须在同一轮输出中连续完成,不可省略任何一步。

A4 输出完毕后,询问用户是否需要生成 HTML 可视化报告:

📊 是否需要生成 HTML 可视化报告?

若用户回复「是」「需要」「生成」「html」等确认词,则执行以下步骤(无需重新调用脚本,HTML 文件已在 Step 2 生成):

① 回填 AI 分析结果到 HTML

调用 backfill_html.py 将 AI 分析结果回填到 HTML 中的 {{PLACEHOLDER}} 占位符:

python3 ~/.agents/skills/weibo-comment-search/scripts/backfill_html.py "<html_path>" --analysis-json '{
  "positive_ratio": <正整数>,
  "negative_ratio": <正整数>,
  "demand_ratio": <正整数>,
  "competitor_ratio": <正整数>,
  "positive_summary": "<ul><li>要点1</li><li>要点2</li>...</ul>",
  "negative_summary": "<ul><li>要点1</li><li>要点2</li>...</ul>",
  "demand_summary": "<ul><li>要点1</li><li>要点2</li>...</ul>",
  "competitor_summary": "<ul><li>要点1</li><li>要点2</li>...</ul>"
}'

JSON 字段说明:

字段 类型 说明 示例
positive_ratio int 积极评价占比(纯数字,不含%) 45
negative_ratio int 负面评价占比 30
demand_ratio int 用户需求占比 15
competitor_ratio int 竞品对比占比 15
positive_summary string 积极评价摘要(HTML 格式 <ul><li>...</li></ul>) 见示例
negative_summary string 负面评价摘要 同上
demand_summary string 用户需求摘要 同上
competitor_summary string 竞品对比摘要 同上

注意: JSON 字符串参数包含双引号,Bash 中使用单引号包裹,内部双引号需转义 \"。若内容含单引号则用 stdin 方式传入:echo '...' | python3 backfill_html.py "<html_path>"

② 打开 HTML 报告:

open "<html_path>"

情况 B:comments 数量 = 0(无评论)

B1. 提示

😔 该博文暂无评论数据。

Step 4:翻页处理

当用户回复「下一页」「上一页」「第 N 页」时:

  1. 沿用 Step 1 中提取的 opusId
  2. 使用上一轮返回的 max_cursor 作为新的 --cursor
  3. 计算新页码
  4. 重新调用脚本(与 Step 2 一致,自动生成 HTML):python3 .../weibo_comment_search.py "<opusId>" --page <page> --cursor <cursor>
  5. 完整执行 Step 3 的 A1~A4,其中:
    • A1/A2:仅展示当前页数据(展示范围不变)
    • A3 评论分析:基于目前已获取的所有页面累计数据(第 1 页至当前页)进行综合分析,标题中 为累计总条数
  6. A4 后询问用户是否需要生成当前页 HTML(同 Step 3 末尾流程,无需重新调用脚本)

Step 5:错误处理

错误类型 处理方式
无 API Key 提示配置 REDFOX_API_KEY,给出配置指引
博文链接无效 提示「无法提取 opusId,请检查博文链接是否正确」
接口返回错误 显示错误码和错误信息
获取 0 条评论 提示「该博文暂无评论」并建议检查博文是否存在或已删除
网络请求超时 提示「网络请求超时,请稍后重试」

📋 依赖

# 脚本使用 urllib(Python 标准库),无需额外安装依赖

🎯 使用示例

示例 1:查看指定博文的评论

用户:查看微博 https://weibo.com/1784473157/R8X4f2lnq 的评论
助手:调用脚本(自动生成HTML) → 展示全部评论 + AI总结 → 询问是否需要HTML → 用户确认 → backfill → open

示例 2:通过 opusId 查询

用户:R8X4f2lnq 这篇博文的评论怎么样
助手:提取 opusId → 调用脚本 → 展示分析 → 询问是否需要HTML

示例 3:翻页

用户:下一页
助手:调用脚本 page=2 cursor=xxx → 展示第2页 + AI累计分析 → 询问是否需要当前页HTML
Files (redfox-community)
  • assets
    • report_template.html 11 KB · in bundle
  • scripts
    • backfill_html.py 2.9 KB
      #!/usr/bin/env python3
      """
      HTML 报告分析数据回填脚本(微博评论分析)
      将 AI 分析结果回填到脚本生成的 HTML 报告中的 {{PLACEHOLDER}} 占位符。
      用法: python3 backfill_html.py <html_path> --analysis-json '<json>'
            或通过 stdin 传入 JSON: echo '<json>' | python3 backfill_html.py <html_path>
      """
      
      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>",...}',
          )
      
          args = parser.parse_args()
      
          # 优先从 --analysis-json 参数读取,其次从 stdin 读取
          if 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
              try:
                  raw = sys.stdin.read()
                  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()
      
    • weibo_comment_search.py 9 KB
      #!/usr/bin/env python3
      """
      微博评论分析 - 根据博文链接查询评论,同步生成 HTML 报告
      用法: python3 weibo_comment_search.py "<博文链接或opusId>" [--page 1] [--cursor 0] [--no-html] [--output-dir ~/Downloads/QoderReports]
      """
      
      import json
      import os
      import re
      import sys
      import argparse
      from datetime import datetime
      
      import urllib.request
      import urllib.error
      
      API_BASE = "https://redfox.hk"
      SOURCE = "微博评论分析-GitHub"
      
      # 脚本所在目录,用于定位模板
      SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
      TEMPLATE_PATH = os.path.join(SCRIPT_DIR, "..", "assets", "report_template.html")
      
      
      def extract_opus_id(url_or_id: str) -> str:
          """从微博博文链接中提取 opusId"""
          # https://weibo.com/1784473157/R8X4f2lnq -> R8X4f2lnq
          m = re.search(r"weibo\.com/\d+/([A-Za-z0-9]+)", url_or_id)
          if m:
              return m.group(1)
          # 直接传 opusId
          if re.match(r"^[A-Za-z0-9]+$", url_or_id):
              return url_or_id
          return ""
      
      
      def sanitize_content(raw: str) -> str:
          """清理评论内容,避免 Markdown 表格格式错乱"""
          if not raw:
              return "-"
          s = raw.replace("\n", " ").replace("\r", " ")
          s = re.sub(r"\s+", " ", s).strip()
          s = s.replace("|", "\\|")
          s = s.replace("[", "【").replace("]", "】")
          return s or "-"
      
      
      def format_number(n) -> str:
          """格式化数字:<10000 原样,>=10000 显示 x.xw"""
          if n is None:
              return "0"
          n = int(n)
          if n >= 10000:
              return f"{n / 10000:.1f}w"
          return str(n)
      
      
      def search(url: str, max_cursor: str = "0", max_id_type: str = "0", page: int = 1):
          """调用 API 查询评论"""
          api_key = os.environ.get("REDFOX_API_KEY")
          if not api_key:
              print("错误: 环境变量 REDFOX_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)
      
          opus_id = extract_opus_id(url)
          if not opus_id:
              print(f"错误: 无法从 '{url}' 中提取 opusId", file=sys.stderr)
              sys.exit(1)
      
          payload = json.dumps({
              "opusId": opus_id,
              "maxCursor": str(max_cursor),
              "maxIdType": str(max_id_type),
              "source": SOURCE,
          }).encode("utf-8")
      
          req = urllib.request.Request(
              f"{API_BASE}/story/api/weibo/ability/commentList",
              data=payload,
              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:
                  data = json.loads(resp.read().decode("utf-8"))
          except urllib.error.HTTPError as e:
              body = e.read().decode("utf-8", errors="replace")
              print(f"错误: HTTP {e.code}: {body}", file=sys.stderr)
              sys.exit(1)
          except urllib.error.URLError as e:
              print(f"错误: 网络请求失败: {e.reason}", file=sys.stderr)
              sys.exit(1)
          except (json.JSONDecodeError, KeyError, TypeError) as e:
              print(f"错误: 数据解析异常: {e}", file=sys.stderr)
              sys.exit(1)
      
          code = data.get("code")
          if code != 2000:
              print(f"错误: 接口返回错误: code={code}, msg={data.get('msg', '未知')}", file=sys.stderr)
              sys.exit(1)
      
          result = data.get("data") or {}
      
          # 解析响应
          if isinstance(result, dict):
              comments = result.get("comments", [])
              max_id = result.get("maxId", "0")
          else:
              comments = []
              max_id = "0"
      
          if not isinstance(comments, list):
              comments = []
      
          has_next = (max_id != "0" and max_id != max_cursor)
      
          formatted_comments = []
          for c in comments:
              if not isinstance(c, dict):
                  continue
              nickname = c.get("nickname", "")
              uid = c.get("uid", "")
              user_url = f"https://weibo.com/{uid}" if uid else ""
      
              formatted_comments.append({
                  "nickname": nickname,
                  "uid": uid or "",
                  "user_url": user_url,
                  "content": sanitize_content(c.get("content", "")),
                  "comment_like_num": int(c.get("commentLikeNum", 0)),
                  "comment_like_num_fmt": format_number(c.get("commentLikeNum", 0)),
                  "create_time": c.get("createTime", ""),
              })
      
          return {
              "opus_id": opus_id,
              "comments": formatted_comments,
              "max_cursor": max_id,
              "has_next": has_next,
              "page": page,
          }
      
      
      # ──────────────────────────────────────────────
      # HTML 报告生成
      # ──────────────────────────────────────────────
      
      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 idx, c in enumerate(comments, 1):
              name = escape_html(c.get("nickname", ""))
              url = c.get("user_url", "") or "#"
              content = escape_html(c.get("content", ""))
              like = c.get("comment_like_num_fmt", "0")
              time_str = c.get("create_time", "") or ""
      
              # 用户名超链接,无头像
              user_cell = f'<a href="{url}" target="_blank" class="user-name">{name}</a>' if url else f'<span class="user-name">{name}</span>'
      
              row = (
                  f'<tr>'
                  f'<td class="index-cell">{idx}</td>'
                  f'<td class="user-cell">{user_cell}</td>'
                  f'<td class="content-cell">{content}</td>'
                  f'<td class="num-cell">{like}</td>'
                  f'<td class="time-cell">{time_str}</td>'
                  f'</tr>'
              )
              rows.append(row)
          return "\n".join(rows)
      
      
      def generate_html_report(opus_id: str, page: int, comments: list, 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("comment_like_num", 0) or 0 for c in comments)
      
          # 占位符替换
          # 数据占位 — 脚本直接填充
          # 分析占位 — 保留 {{PLACEHOLDER}},后续由 backfill_html.py 回填
          replacements = {
              "{{OPUS_ID}}": escape_html(opus_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(page),
              # {{POSITIVE_RATIO}} / {{NEGATIVE_RATIO}} / {{DEMAND_RATIO}} / {{COMPETITOR_RATIO}}
              # {{SUMMARY_POSITIVE}} / {{SUMMARY_NEGATIVE}} / {{SUMMARY_DEMAND}} / {{SUMMARY_COMPETITOR}}
              # 以上分析占位符不在脚本中替换,保留原样,由 backfill_html.py 统一回填
          }
      
          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"微博评论分析_{opus_id}_p{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="微博评论分析")
          parser.add_argument("url", help="微博博文链接或 opusId")
          parser.add_argument("--cursor", default="0", help="翻页游标 (默认 0)")
          parser.add_argument("--page", type=int, default=1, help="页码 (默认 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()
      
          result = search(args.url, max_cursor=args.cursor, page=args.page)
      
          # HTML 报告生成
          if not args.no_html:
              html_path = generate_html_report(
                  opus_id=result["opus_id"],
                  page=result["page"],
                  comments=result["comments"],
                  output_dir=args.output_dir,
              )
              result["html_path"] = html_path
      
          print(json.dumps(result, ensure_ascii=False, indent=2))
      
      
      if __name__ == "__main__":
          main()
      
  • README.en.md 3.2 KB
    # Weibo Comment Analysis / weibo-comment-search
    
    ---
    
    ## Introduction
    
    Enter a Weibo post URL to view its comments at a glance — who commented, how many likes, and when it was posted. Click any username to jump directly to their Weibo profile. All data is freshly fetched from the platform, no stale cache.
    
    **Core Value**
    
    - **Fresh content, no lag**: Every query pulls the latest comments directly from the platform — only fresh data, no outdated archives.
    - **User identity at a glance**: Commenter usernames are clickable, linking straight to their Weibo profiles for quick context.
    - **Browse at will**: Massive comment threads support pagination — just say "next page" to keep exploring.
    
    **Who It's For**
    
    - 🔍 **Content operators / Competitive analysis** — Check user feedback on target posts and gauge engagement
    - �� **Sentiment monitoring** — Track public opinion under specific posts, catch key comments early
    - �� **Creator research** — Study follower comments and interaction levels
    
    ---
    
    ## Features
    
    ### Core Capabilities
    
    - **Comment Query**: Enter a Weibo post URL or opusId to fetch first-level comments.
    - **Pagination**: Browse multiple pages of results to explore more comments.
    
    ---
    
    ## 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).
    - Visit [RedFoxHub](https://redfox.hk?source=github) to register and obtain your `REDFOX_API_KEY`.
    - Configure the `REDFOX_API_KEY` environment variable on your device before using this skill.
    - Before providing your key, confirm its source, scope, expiration, and whether it supports reset/revocation.
    - Never hardcode or expose your key in plaintext within code, prompts, logs, or output files.
    
    ---
    
    ## Usage Guide
    
    Just describe your need in plain language — no commands to memorize.
    
    ### Quick Reference
    
    | Intent | Example | Effect |
    | ------ | ------- | ------ |
    | View comments | "Check comments on https://weibo.com/1784473157/R8X4f2lnq" | Extracts opusId and displays comments |
    | Direct opusId | "Show comments for R8X4f2lnq" | Queries directly by opusId |
    | Pagination | "Next page" / "Previous page" | Navigate through results |
    
    ### Output Example
    
    After a query, you'll receive results in this format:
    
    > 📊 Post `R8X4f2lnq` — **20 comments** found (Page 1):
    
    | # | User | Comment | Likes | Time |
    |---|------|---------|-------|------|
    | 1 | [UserA](https://weibo.com/123456) | Well said, totally agree! | 305 | 2025-07-10 14:30:25 |
    | 2 | [UserB](https://weibo.com/789012) | This post is very insightful... | 1.2k | 2025-07-10 12:15:30 |
    
    > 📄 Page **1**. Reply "next page" to continue browsing.
    
    ---
    
    ## Use Cases
    
    | Scenario | Role | Example | Benefit |
    | -------- | ---- | ------- | ------- |
    | Comment sentiment analysis | Content operator | "Check comments on this Weibo post" | Quickly understand user feedback on posts |
    | Trending tracking | PR / Monitoring | "Check comment sentiment on this trending topic" | Monitor public opinion and user attitudes |
    | Competitor comment research | Creator | "View comments on similar creators' posts" | Understand audience engagement with similar content |
    
  • README.md 3.1 KB
    # 微博评论分析 / weibo-comment-search
    
    ---
    
    ## 简介
    
    输入微博博文链接就能看到这条博文的评论,谁评论了什么、被点赞多少次、什么时候发的都一目了然,点用户昵称还能直接跳转到 TA 的微博主页,给到你的都是平台刚更新的新鲜数据,不会拿旧缓存糊弄你。
    
    **核心价值**
    
    - **内容新鲜不滞后**:每次查询直接拉取平台最新评论,只给你刚发布的数据,不是过期存档。
    - **用户身份一眼知**:评论人昵称直接可点,跳转到微博主页,快速了解评论者身份。
    - **翻页随心浏览**:海量评论支持分页翻阅,一句「下一页」继续看更多内容。
    
    **适用对象**
    
    - 🔍 **内容运营 / 竞品分析** — 查看目标博文的用户反馈,了解互动热度
    - 📊 **舆情监测** — 追踪特定博文下的舆论风向,第一时间发现关键评论
    - �� **创作者研究** — 了解粉丝评论内容和互动水平
    
    ---
    
    ## 功能特性
    
    ### 核心功能
    
    - **评论查询**:输入微博博文链接或 opusId,查询该博文的一级评论。
    - **分页浏览**:支持多页结果浏览,按需查看更多评论。
    
    ---
    
    ## 密钥获取与安全说明
    
    - 本技能需要使用环境变量:`REDFOX_API_KEY`。
    - `REDFOX_API_KEY` 由 [红狐 hub](https://redfox.hk/settings/api-keys?source=github) 提供。
    - 请前往 [红狐 hub](https://redfox.hk?source=github) 注册账号,获取 `REDFOX_API_KEY`。
    - 配置设备环境变量 `REDFOX_API_KEY` 后使用本技能。
    - 在提供密钥前,请先确认密钥来源、可用范围、有效期及是否支持重置/撤销。
    - 禁止在代码、提示词、日志或输出文件中硬编码/明文暴露密钥。
    
    ---
    
    ## 使用指南
    
    直接用自然语言描述需求,无需记忆命令。
    
    ### 常用说法速查
    
    | 意图 | 示例话术 | 效果 |
    | ---- | -------- | ---- |
    | 查看评论 | 「查下 https://weibo.com/1784473157/R8X4f2lnq 的评论」 | 提取 opusId 后查询并展示评论 |
    | 直接给 opusId | 「查 R8X4f2lnq 的评论」 | 直接用 opusId 查询 |
    | 翻页查看 | 「下一页」/ 「上一页」 | 切换当前结果页码 |
    
    ### 输出示例
    
    查询完成后,你将收到如下格式的结果:
    
    > 📊 博文 `R8X4f2lnq` 查询到 **20 条**评论(第 1 页),以下是详细数据:
    
    | # | 用户 | 评论内容 | 点赞 | 发布时间 |
    |---|------|----------|------|----------|
    | 1 | [用户A](https://weibo.com/123456) | 说得太对了,支持! | 305 | 2025-07-10 14:30:25 |
    | 2 | [用户B](https://weibo.com/789012) | 这条博文很有深度... | 1.2w | 2025-07-10 12:15:30 |
    
    > 📄 当前第 **1** 页。回复「下一页」继续查看。
    
    ---
    
    ## 使用场景
    
    | 场景 | 角色 | 示例问法 | 收益 |
    | ---- | ---- | -------- | ---- |
    | 评论舆情分析 | 内容运营 | 「查下这条微博的评论」 | 快速了解用户对博文的反馈 |
    | 热点追踪 | 舆情 | 「看看这条热搜的评论风向」 | 掌握舆论趋势和用户态度 |
    | 竞品评论研究 | 创作者 | 「看下同行博文下的评论」 | 了解同类内容受众互动水平 |
    
  • SKILL.md 10.2 KB
    ---
    name: weibo-comment-search
    description: 微博评论分析工具。输入微博博文链接即可获取一级评论数据,支持分页浏览和四维情感分析(积极/负面/需求/竞品)。当用户需要查看微博评论、分析评论舆情、了解用户反馈时使用。触发词:微博评论、博文评论、评论查询、评论分析、看评论。
    ---
    
    # 微博评论分析
    
    ## 📝 简介
    
    微博评论分析工具,输入微博博文链接,即可查看该博文的一级评论数据,支持分页浏览和 AI 情感分析。在对话中展示当前页全部评论及 AI 总结分析,同时生成包含当前页数据和总结的交互式 HTML 报告。
    
    ## ✨ 功能特性
    
    | 功能模块 | 能力描述 | 核心价值 |
    |---------|---------|---------|
    | 评论查询 | 输入微博博文链接查询评论 | 一键查看任意博文的评论 |
    | 分页浏览 | 支持多页结果浏览 | 逐页探索更多评论 |
    | AI 总结 | 四维情感分析(积极/负面/需求/竞品) | 快速了解评论舆情全貌 |
    | HTML 报告 | 深色主题交互式报告 | 离线保存/分享分析结果 |
    
    ## 🔑 鉴权
    
    ### 获取 API Key
    
    请前往 [红狐hub](https://redfox.hk/settings/api-keys?source=github) 获取 API KEY
    
    ### 配置 API Key
    
    方案1: 以 Qoder 为例,将 REDFOX_API_KEY 添加到 `~/.openclaw/openclaw.json` 中:
    
    ```bash
    { "env": { "REDFOX_API_KEY": "ak_xxxx..." } }
    ```
    
    方案2: 终端配置
    
    ```bash
    export REDFOX_API_KEY="ak_xxxx..."
    ```
    
    ## 🔄 工作流程
    
    ### Step 1:理解用户意图,提取 opusId
    
    **1. 从微博博文链接中提取 opusId**
    
    - 若用户提供了博文链接(如 `https://weibo.com/1784473157/R8X4f2lnq`),从中提取 opusId(`R8X4f2lnq`)
    - 若用户直接提供了 opusId,直接使用
    - 若用户意图模糊(如"帮我查下评论"),主动询问:「请提供微博博文链接」
    - 不得在用户未提供链接时擅自猜测并调用脚本
    - 若用户在上一轮对话中查询过某博文的评论,且本轮输入模糊(如"下一页"、"评论分析"),沿用上一轮的 opusId
    
    **2. 识别页码参数**
    
    - 用户提到"下一页"、"第2页" → 对应页码,同时使用上一轮返回的 max_cursor
    - 用户提到"上一页" → 当前页 - 1
    - 未提及页码 → 默认第 1 页
    
    ### Step 2:调用查询脚本(自动生成 HTML)
    
    **⚠️ 每次调用仅请求一页数据(一次 API 请求),不可擅自发起多次调用拉取多页。**
    
    **脚本每次调用自动生成 HTML 报告**(含 `{{PLACEHOLDER}}` 占位符,未回填分析数据)。终端展示与 HTML 基于**同一次 API 调用**,确保数据一致。
    
    ```bash
    python3 ~/.agents/skills/weibo-comment-search/scripts/weibo_comment_search.py "<博文链接或opusId>" [--page 页码] [--cursor 游标] [--output-dir 目录]
    ```
    
    **参数说明:**
    
    | 参数 | 说明 | 默认值 |
    |------|------|--------|
    | input | 微博博文链接或 opusId | — |
    | `--page` | 页码,从1开始 | `1` |
    | `--cursor` | 翻页游标(首页为 0,后续从返回的 max_cursor 传入) | `0` |
    | `--no-html` | 跳过 HTML 报告生成 | — |
    | `--output-dir` | HTML 输出目录 | `~/Downloads/QoderReports` |
    
    脚本以 JSON 格式输出:
    
    | 字段 | 说明 |
    |------|------|
    | `opus_id` | 博文 opusId |
    | `comments` | 评论列表 |
    | `max_cursor` | 下一页游标 |
    | `has_next` | 是否有下一页(true/false) |
    | `page` | 当前页码 |
    | `html_path` | 生成的 HTML 报告路径(含占位符,待回填) |
    
    每条评论字段:
    
    | 字段 | 说明 |
    |------|------|
    | `nickname` | 用户昵称 |
    | `uid` | 用户 uid |
    | `user_url` | 用户主页链接(`https://weibo.com/{uid}`) |
    | `content` | 评论内容 |
    | `comment_like_num` | 点赞数(原始数字) |
    | `comment_like_num_fmt` | 点赞数(格式化后) |
    | `create_time` | 发布时间 |
    
    > **注意:** HTML 报告此时仅含评论原始数据,分析占位符(`{{PLACEHOLDER}}`)待用户确认后回填。
    
    ### Step 3:判断结果并展示
    
    #### 情况 A:comments 数量 > 0(有评论)
    
    **A1. 告知用户查询范围**
    
    > 📊 博文 `{opus_id}` 查询到 **N 条**评论(第 {page} 页),以下是详细数据:
    
    **A2. 渲染 Markdown 表格(全部展示)**
    
    ```markdown
    | # | 用户 | 评论内容 | 点赞 | 发布时间 |
    |---|------|----------|------|----------|
    | 1 | [nickname](https://weibo.com/uid) | 评论内容 | 305 | 2025-07-10 14:30:25 |
    ```
    
    **格式规则:**
    - 用户昵称渲染为超链接:`[nickname](user_url)`,跳转到用户主页
    - 点赞数 `< 10000` 原始数字,`≥ 10000` 显示 `x.xw`
    - 发布时间完整展示年月日时分秒
    - 评论内容超过 50 字截断并加 `...`,内容为空时显示 `-`
    - ⚠️ 当前页全部评论均需展示,不得截断
    
    **A3. AI 评论总结(⚠️ 每次查询(含翻页)必须输出)**
    
    **首页**:基于当前页获取到的全部评论,进行四维情感分析。
    
    **翻页后**:基于**目前已获取的所有页面累计数据**进行综合分析,而非仅分析当前单页。分析时需标注累计总条数。
    
    **分析前需理解微博热点话题背景**(热搜事件、粉丝文化、明星动态、社会议题语境)。
    
    > ## 📈 评论总结分析(基于 {total} 条评论)
    >
    > ### ✅ 积极评价({positive_ratio}%)
    > - {要点1}
    > - {要点2}
    > - ...
    >
    > ### ⚠️ 负面评价({negative_ratio}%)
    > - {要点1}
    > - {要点2}
    > - ...
    >
    > ### 💡 用户需求({demand_ratio}%)
    > - {要点1}
    > - {要点2}
    > - ...
    >
    > ### 🔍 竞品对比舆情({competitor_ratio}%)
    > - {仅当评论中提及竞品时输出,否则输出「未提及竞品」}
    > - {竞品名称}:{舆情要点}
    
    **分析要求:**
    - 每条要点需引用代表评论(截取关键词/短语)
    - 百分比为提及该类型评论的数量占总评论数的比例
    - 积极/负面/需求/竞品四类占比总和可能超过 100%(一条评论可能同时包含多类信息)
    - **必须理解微博语境**:识别粉丝话术(如"抱走""纯路人""yyds""打call"等)、热门话题背景、明星相关舆情
    
    **A4. 翻页提示(⚠️ 紧接在 A3 之后,每次必须输出)**
    
    - 若 `has_next` 为 true:
    > 📄 当前第 **{page}** 页。回复「下一页」继续查看。
    
    - 若 `has_next` 为 false:
    > 📄 当前第 **{page}** 页,已无更多数据。
    
    **⚠️ A1~A4 必须在同一轮输出中连续完成,不可省略任何一步。**
    
    A4 输出完毕后,**询问用户是否需要生成 HTML 可视化报告**:
    
    > 📊 是否需要生成 HTML 可视化报告?
    
    **若用户回复「是」「需要」「生成」「html」等确认词**,则执行以下步骤(**无需重新调用脚本**,HTML 文件已在 Step 2 生成):
    
    **① 回填 AI 分析结果到 HTML**
    
    调用 `backfill_html.py` 将 AI 分析结果回填到 HTML 中的 `{{PLACEHOLDER}}` 占位符:
    
    ```bash
    python3 ~/.agents/skills/weibo-comment-search/scripts/backfill_html.py "<html_path>" --analysis-json '{
      "positive_ratio": <正整数>,
      "negative_ratio": <正整数>,
      "demand_ratio": <正整数>,
      "competitor_ratio": <正整数>,
      "positive_summary": "<ul><li>要点1</li><li>要点2</li>...</ul>",
      "negative_summary": "<ul><li>要点1</li><li>要点2</li>...</ul>",
      "demand_summary": "<ul><li>要点1</li><li>要点2</li>...</ul>",
      "competitor_summary": "<ul><li>要点1</li><li>要点2</li>...</ul>"
    }'
    ```
    
    **JSON 字段说明:**
    
    | 字段 | 类型 | 说明 | 示例 |
    |------|------|------|------|
    | `positive_ratio` | int | 积极评价占比(纯数字,不含%) | `45` |
    | `negative_ratio` | int | 负面评价占比 | `30` |
    | `demand_ratio` | int | 用户需求占比 | `15` |
    | `competitor_ratio` | int | 竞品对比占比 | `15` |
    | `positive_summary` | string | 积极评价摘要(HTML 格式 `<ul><li>...</li></ul>`) | 见示例 |
    | `negative_summary` | string | 负面评价摘要 | 同上 |
    | `demand_summary` | string | 用户需求摘要 | 同上 |
    | `competitor_summary` | string | 竞品对比摘要 | 同上 |
    
    **注意:** JSON 字符串参数包含双引号,Bash 中使用单引号包裹,内部双引号需转义 `\"`。若内容含单引号则用 stdin 方式传入:`echo '...' | python3 backfill_html.py "<html_path>"`
    
    **② 打开 HTML 报告:**
    
    ```bash
    open "<html_path>"
    ```
    
    #### 情况 B:comments 数量 = 0(无评论)
    
    **B1. 提示**
    
    > 😔 该博文暂无评论数据。
    
    ### Step 4:翻页处理
    
    当用户回复「下一页」「上一页」「第 N 页」时:
    
    1. 沿用 Step 1 中提取的 opusId
    2. 使用上一轮返回的 `max_cursor` 作为新的 `--cursor`
    3. 计算新页码
    4. 重新调用脚本(**与 Step 2 一致,自动生成 HTML**):`python3 .../weibo_comment_search.py "<opusId>" --page <page> --cursor <cursor>`
    5. **完整执行 Step 3 的 A1~A4**,其中:
       - A1/A2:仅展示当前页数据(展示范围不变)
       - **A3 评论分析:基于目前已获取的所有页面累计数据(第 1 页至当前页)进行综合分析**,标题中 {total} 为累计总条数
    6. A4 后询问用户是否需要生成当前页 HTML(同 Step 3 末尾流程,**无需重新调用脚本**)
    
    ### Step 5:错误处理
    
    | 错误类型 | 处理方式 |
    |---------|---------|
    | 无 API Key | 提示配置 REDFOX_API_KEY,给出配置指引 |
    | 博文链接无效 | 提示「无法提取 opusId,请检查博文链接是否正确」 |
    | 接口返回错误 | 显示错误码和错误信息 |
    | 获取 0 条评论 | 提示「该博文暂无评论」并建议检查博文是否存在或已删除 |
    | 网络请求超时 | 提示「网络请求超时,请稍后重试」 |
    
    ---
    
    ## 📋 依赖
    
    ```bash
    # 脚本使用 urllib(Python 标准库),无需额外安装依赖
    ```
    
    ---
    
    ## 🎯 使用示例
    
    **示例 1:查看指定博文的评论**
    ```
    用户:查看微博 https://weibo.com/1784473157/R8X4f2lnq 的评论
    助手:调用脚本(自动生成HTML) → 展示全部评论 + AI总结 → 询问是否需要HTML → 用户确认 → backfill → open
    ```
    
    **示例 2:通过 opusId 查询**
    ```
    用户:R8X4f2lnq 这篇博文的评论怎么样
    助手:提取 opusId → 调用脚本 → 展示分析 → 询问是否需要HTML
    ```
    
    **示例 3:翻页**
    ```
    用户:下一页
    助手:调用脚本 page=2 cursor=xxx → 展示第2页 + AI累计分析 → 询问是否需要当前页HTML
    ```
    
  • _user_meta.json 94 B
    {
      "name": "weibo-comment-search",
      "installedAt": 1784254444482,
      "source": "userImport"
    }

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related