# Steam 社区监控一期计划 ## 目标 第一阶段先接入 Steam 两个信息源: 1. Steam 评测信息 2. Steam 讨论社区信息:`https://steamcommunity.com/app/3774440/discussions` 系统每 30 分钟刷新一次。第一轮全量抓取 Steam 评测、讨论区主题和讨论区回复;后续只做增量更新。所有新增内容调用 OpenRouter 的 `deepseek/deepseek-v4-pro` 做分类和回复必要性评估,并在 dashboard 中展示、筛选、高亮和追踪人工处理状态。 ## 已确认事实 | 判断 | 类型 | 证据 | 决策影响 | |---|---|---|---| | AppID 为 `3774440` 的 Steam 评测 API 当前有数据 | 当前事实 | 本地请求 `https://store.steampowered.com/appreviews/3774440?...` 成功,返回 `total_reviews=130`、`review_score_desc=Very Positive` | 一期可以直接接入评测 API | | Steam 讨论区页面当前可访问 | 当前事实 | 本地请求 `https://steamcommunity.com/app/3774440/discussions/` 返回 HTTP 200,页面包含 forum/topic 内容 | 一期可以用 HTTP + HTML 解析抓讨论区 | | `deepseek/deepseek-v4-pro` 当前存在于 OpenRouter 模型列表 | 当前事实 | 本地请求 OpenRouter models API 返回该模型,支持 `response_format` 和 `structured_outputs` | 一期可按结构化 JSON 分类设计 | | Steam 评测数量存在口径差异风险 | 经验事实 | 用户级经验记录:Steam `appreviews` 受缓存、语言、购买类型和索引延迟影响 | 统计口径不能只依赖单一请求 | ## 一期范围 ### 做 - 每 30 分钟刷新 Steam 评测和 Steam 讨论区。 - 第一轮全量抓取;后续增量抓取新增或更新内容。 - 对 Steam 评测、讨论区主题、讨论区回复分别去重入库。 - 调用 OpenRouter 模型输出结构化分类结果。 - Dashboard 展示评论/帖子/回复列表、分类结果、原始链接、回复建议和人工处理状态。 - 支持本机运行,架构上预留服务器部署。 ### 暂不做 - 暂不接入 Steam 以外社区。 - 暂不做复杂账号权限系统;服务器部署前再补认证方案。 - 暂不自动回复玩家,只做信息发现、分类和处理追踪。 - 暂不做语言筛选;所有语言统一进入采集和模型评估。 ## 采集流程 ### Steam 评测 使用 Steam Store Reviews API: ```text GET https://store.steampowered.com/appreviews/3774440 ``` 基础参数: - `json=1` - `num_per_page=100` - `language=all` - `filter=recent` - `purchase_type=all` - `cursor=*` 起步,后续使用响应中的 cursor 翻页 评测去重主键: - `steam_review:{recommendationid}` 评测建议保留字段: - `recommendationid` - `voted_up` - `review` - `language` - `timestamp_created` - `timestamp_updated` - `author.steamid` - `author.personaname` - `author.profile_url` - `author.playtime_forever` - `votes_up` - `comment_count` - `steam_purchase` - `received_for_free` - `source_url` 评测链接可由 `recommendationid` 构造: ```text https://steamcommunity.com/profiles/{steamid}/recommended/3774440/#developer_response ``` 若用户 profile URL 可用,也应保留原始 `profile_url` 作为辅助追溯字段。 ### Steam 讨论区 使用 HTTP 请求讨论区列表页: ```text https://steamcommunity.com/app/3774440/discussions/ ``` 翻页参数: ```text ?fp=2 ?fp=3 ``` 第一轮抓取所有可访问讨论页和所有可访问回复。后续增量刷新时,从最新列表页开始向后翻页,直到遇到本地已存在且未更新的主题为止;若 Steam 页面无法稳定判断更新时间,则以最近若干页作为增量窗口,并保留手动全量重扫入口。 讨论区去重主键: - 主题:`steam_discussion_topic:{topic_id}` - 回复:`steam_discussion_reply:{topic_id}:{reply_id}`,如果页面拿不到稳定 reply id,则用 `topic_id + author + timestamp + content_hash` 讨论区建议保留字段: - `topic_id` - `topic_url` - `title` - `author` - `published_at_text` - `content` - `reply_count` - `reply_author` - `reply_time_text` - `reply_content` - `reply_url` - `source_url` ## 数据模型 建议先用 SQLite 跑通本机版本;部署服务器时可迁移 PostgreSQL。 核心表可以先压成三类: ### `raw_items` 保存原始社区内容及来源信息。 关键字段: - `id` - `source` - `source_item_id` - `source_url` - `content_type` - `author_id` - `author_name` - `published_at` - `collected_at` - `content` - `raw_json` - `content_hash` ### `analysis_results` 保存模型分类结果。 关键字段: - `raw_item_id` - `model` - `sentiment` - `is_positive` - `is_negative` - `has_actionable_feedback` - `feedback_types` - `reply_recommended` - `reply_priority` - `reply_suggestion` - `summary` - `priority` - `confidence` - `model_json` - `analyzed_at` ### `work_items` 保存人工处理状态。 关键字段: - `raw_item_id` - `status` - `owner` - `notes` - `last_handled_at` - `created_at` - `updated_at` 状态枚举建议: - `new` - `read` - `needs_reply` - `replied` - `needs_fix` - `archived` ## OpenRouter 分类方案 模型: ```text deepseek/deepseek-v4-pro ``` OpenRouter Key: - 本机和服务器都使用 `.env` / 环境变量读取,不在项目文件中明文保存。 - 用户级 `auth.json` 只作为本机开发时迁移 key 的来源,不作为项目运行时依赖。 - 推荐变量名:`OPENROUTER_API_KEY`。 目标输出 JSON: ```json { "sentiment": "positive | negative | mixed | neutral", "is_positive": true, "is_negative": false, "has_actionable_feedback": true, "feedback_types": ["bug", "suggestion", "balance", "ui", "localization", "performance", "pricing", "content", "question", "other"], "reply_recommended": true, "reply_priority": "none | low | medium | high", "reply_suggestion": "建议运营或开发如何回复;不需要回复时为空字符串", "summary": "一句话摘要", "priority": "low | medium | high", "confidence": 0.0, "reason": "简短分类依据" } ``` 分类规则: - `is_positive` / `is_negative` 对应用户要求的好评、差评展示。 - `has_actionable_feedback=true` 表示包含具体建议、问题反馈、bug、平衡性、UI、翻译、本地化、性能、价格、内容量等可处理信息。 - `reply_recommended=true` 表示建议人工回复或处理,高优先级内容需要在 dashboard 高亮。 - 讨论区主题和回复都必须进入模型评估;不能只评估主题原帖。 - Steam 评测本身的 `voted_up` 作为强信号,但不要覆盖文本判断;例如推荐评测里也可能包含具体差评点。 - 每条结果必须保留 `source_url`,dashboard 中直接跳转原始评论或讨论帖。 ## Dashboard 一期页面 第一版页面不追求复杂,重点是运营处理效率。 建议视图: - 总览指标:新增数量、未处理数量、差评数量、具体反馈数量、高优先级数量、已分析数量、待补跑数量、最近更新时间。 - 内容列表:来源、内容类型、时间、作者、摘要、情绪、反馈类型、优先级、是否建议回复、处理状态、原始链接。 - 筛选:信息源、内容类型、情绪、是否具体反馈、是否建议回复、反馈类型、处理状态、时间范围。 - 高亮:`reply_recommended=true` 或 `priority=high` 的帖子/回复。 - 详情:原文、模型分类、回复建议、原始链接、备注、负责人、状态变更。 - 排序:建议回复优先;同组内按发布时间新到旧。 ## 定时与失败处理 定时: - 默认每 30 分钟执行一次采集任务。 - 第一轮执行全量抓取;全量完成后记录同步游标、已见主题、已见回复和评测 cursor/时间水位。 - 首轮全量建议支持断点续跑:每完成一页讨论列表、一个主题详情、一个评测分页后写入进度,失败后从最近进度恢复。 - 首轮全量不建议设置过小页数上限,否则会破坏“全抓”目标;建议设置安全保护,例如单次最多连续运行 2 小时或最多抓取 500 页,并允许下次继续。 - 本机先用应用内 scheduler 或命令行手动触发验证;服务器部署时再选 systemd timer、cron 或队列 worker。 失败处理: - Steam 请求失败:记录错误,下一轮重试,不删除旧数据。 - OpenRouter 请求失败:保留 raw item,标记 `analysis_pending`,下一轮或手动补跑。 - JSON 解析失败:保存模型原始输出,进入待复核状态。 - 重复采集:通过 source item id 和 content hash 去重。 ## 部署前提 本机 MVP: - 本地数据库 - 本地 dashboard - 从 `.env` 读取 OpenRouter API Key - 手动或定时刷新 服务器部署前需要补充: - 访问认证 - 持久化数据库位置和备份策略 - 后台任务运行方式 - 日志与错误告警 - OpenRouter 调用预算和速率控制 - Steam 抓取频率和 User-Agent 策略 ## 已定实现决策 - 密钥配置:使用 `.env` / 环境变量,变量名 `OPENROUTER_API_KEY`。 - 首轮抓取:全量抓取,支持断点续跑;用运行时间或高页数阈值做安全保护,不用小页数上限替代全量目标。 - 负责人字段:按小团队制作人/处理人文本字段设计,暂不接用户账号系统。 ## 当前实现状态 - 已实现 Python/FastAPI + SQLite MVP。 - 已实现 Steam 评测 API 抓取。 - 已实现 Steam 讨论区主题与回复抓取。 - 已实现 OpenRouter `deepseek/deepseek-v4-pro` 结构化分类。 - 已实现 dashboard、手动同步、后台 30 分钟增量同步、处理状态更新。 - 已实现局域网服务监听 `0.0.0.0:8000`。 - 已实现 Steam 讨论区中文时间解析,支持 `x 小时以前`、`3 月 7 日 下午 4:52`、`2025 年 8 月 9 日 下午 3:29`。 - 已补跑完成 2026-05-01 之后 209 条内容的 AI 分析。 ## 后续平台接入约束 - 新平台不要复制 Steam 私有逻辑;应新增平台采集器,输出统一 `RawItem`。 - 新平台继续复用 `raw_items`、`analysis_results`、`work_items`。 - 每个平台必须明确稳定去重主键、原始链接、发布时间解析、首轮全量和后续增量策略。 - 需要登录态或浏览器自动化的平台,先单独做方案和当前事实验证,再接入同步链路。