1. 为什么需要实时追踪Steam好友状态最近我发现一个很有意思的现象身边不少朋友在Steam上玩游戏时喜欢开隐身模式。这让我想起上周约好一起开黑的场景明明说好晚上8点上线结果等到9点都没见人影。后来才知道这家伙早就上线了只是开了隐身模式在单排。这种信息不对称的情况其实很常见。你可能遇到过好友明明在线却显示离线错过组队机会想找朋友一起玩新游戏却不知道对方已经在玩了朋友说最近没怎么玩游戏结果发现他偷偷上了王者段位传统的Steam好友列表只能显示简单的在线状态而且很容易被隐身功能绕过。更糟的是Steam的手机推送经常延迟等收到通知时可能已经错过最佳游戏时间。这就是为什么我们需要一个更智能的解决方案——通过Steam Web API直接获取好友的真实游戏状态再配合钉钉的即时推送功能打造一个专属的游戏状态监控系统。相比手动刷新好友列表这种自动化方案有三大优势第一是实时性。API可以获取到毫秒级的在线状态变化不像客户端有时会有缓存延迟。第二是可靠性。API数据直接来自Steam服务器不会被本地隐身设置影响。第三是灵活性。你可以自定义监控规则比如只关注特定游戏的上线提醒或者在好友游戏时长超过阈值时收到警告。2. Steam Web API入门指南要获取Steam好友的实时数据我们需要先了解Steam Web API的基本使用方法。这个由Valve官方提供的接口允许开发者查询各种Steam平台数据从用户信息到游戏详情应有尽有。2.1 申请API密钥使用API的第一步是获取开发者密钥。这个过程非常简单访问Steam社区开发者页面使用你的Steam账号登录在Web API密钥部分填写申请表单域名可以填写localhost除非你要部署到服务器提交后立即获得一个32位的API密钥这个密钥是你访问所有API的通行证务必妥善保管。我建议不要直接写在代码里而是存放在环境变量或配置文件中。2.2 理解SteamID体系Steam使用几种不同的ID标识用户SteamID传统的数字ID如STEAM_0:0:12345678SteamID3带中括号的版本如[U:1:24691356]SteamID6464位版本如76561197960287930要获取好友的游戏状态我们需要他的SteamID64。获取方法很简单打开好友的Steam个人资料页URL最后那串17位数字就是。比如https://steamcommunity.com/profiles/76561197960287930中的76561197960287930。2.3 关键API接口介绍对于好友状态监控这几个API特别有用GetPlayerSummaries获取用户基础信息包括在线状态、最后在线时间、当前游戏等请求示例http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?keyYOUR_KEYsteamids76561197960287930GetFriendList获取用户的好友列表可以筛选在线好友请求示例http://api.steampowered.com/ISteamUser/GetFriendList/v1/?keyYOUR_KEYsteamid76561197960287930GetRecentlyPlayedGames获取最近游玩的游戏列表包含每个游戏的时长数据请求示例http://api.steampowered.com/IPlayerService/GetRecentlyPlayedGames/v1/?keyYOUR_KEYsteamid765611979602879303. Python监控脚本编写现在我们来编写核心的监控脚本。这个Python程序会定期检查好友状态发现变化时通过钉钉机器人发送通知。3.1 环境准备首先安装必要的Python库pip install requests python-dotenv dingtalkchatbot我建议使用python-dotenv管理API密钥等敏感信息。创建一个.env文件STEAM_API_KEY你的Steam_API密钥 STEAM_FRIEND_ID要监控的好友SteamID64 DINGTALK_WEBHOOK你的钉钉机器人Webhook地址3.2 基础监控脚本以下是基础版本的监控脚本import os import time import requests from dotenv import load_dotenv from dingtalkchatbot.chatbot import DingtalkChatbot # 加载环境变量 load_dotenv() # 初始化钉钉机器人 ding DingtalkChatbot(os.getenv(DINGTALK_WEBHOOK)) def get_player_summary(): url fhttp://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key{os.getenv(STEAM_API_KEY)}steamids{os.getenv(STEAM_FRIEND_ID)} response requests.get(url) data response.json() return data[response][players][0] def monitor_steam_friend(): last_state None last_game None while True: try: player get_player_summary() current_state 在线 if player[personastate] 0 else 离线 current_game player.get(gameextrainfo, 未在游戏中) # 状态变化检测 if current_state ! last_state or current_game ! last_game: message fSteam状态更新{player[personaname]}当前状态{current_state} if current_game ! 未在游戏中: message f正在玩{current_game} ding.send_text(msgmessage) last_state current_state last_game current_game time.sleep(60) # 每分钟检查一次 except Exception as e: print(f监控出错{e}) time.sleep(300) # 出错时等待5分钟再重试 if __name__ __main__: monitor_steam_friend()这个脚本会每分钟检查一次好友状态当检测到在线状态变化或游戏切换时通过钉钉发送通知。3.3 高级功能扩展基础版本已经能用但我们可以做得更好游戏时长监控def get_recent_games(): url fhttp://api.steampowered.com/IPlayerService/GetRecentlyPlayedGames/v1/?key{os.getenv(STEAM_API_KEY)}steamid{os.getenv(STEAM_FRIEND_ID)} response requests.get(url) data response.json() return data[response][games][0] if data[response].get(games) else None # 在monitor_steam_friend中添加 recent_game get_recent_games() if recent_game: playtime_hours recent_game[playtime_forever] / 60 message f\n总游戏时长{playtime_hours:.1f}小时特定游戏提醒TARGET_GAMES [Dota 2, Counter-Strike 2] if current_game in TARGET_GAMES and last_game not in TARGET_GAMES: message \n提醒他正在玩你关注的游戏异常游戏时长报警if playtime_hours 5: # 5小时以上 message \n警告今日游戏时间过长4. 钉钉机器人集成钉钉机器人是实现实时推送的关键环节。下面详细介绍如何配置和使用。4.1 创建钉钉机器人打开钉钉群设置选择智能群助手点击添加机器人 → 自定义设置机器人名称和头像安全设置建议选择加签(更安全)或IP白名单完成创建后复制webhook地址4.2 消息格式优化基础文本消息已经能用但钉钉支持更丰富的消息格式Markdown消息def send_markdown(title, text): ding.send_markdown(titletitle, texttext) # 示例使用 send_markdown( titleSteam状态更新, textf**{player[personaname]}** 状态变化\n\n f- 当前状态{current_state}\n f- 正在游戏{current_game}\n f- 头像![]({player[avatarfull]}) )消息卡片def send_action_card(): ding.send_action_card( title游戏状态变化, textf{player[personaname]}开始玩{current_game}了, btns[{ title: 查看Steam资料, actionURL: player[profileurl] }] )定时推送摘要def send_daily_summary(): games get_recent_games() total_hours sum(g[playtime_2weeks]/60 for g in games) if games else 0 ding.send_markdown( title每日游戏报告, textf**{player[personaname]}** 24小时游戏记录\n\n f- 总游戏时长{total_hours:.1f}小时\n f- 最常玩游戏{games[0][name] if games else 无}\n f- 最后上线{player[lastlogoff]} )4.3 推送频率控制为了避免消息轰炸建议实现这些控制策略状态变化去重只有状态真正改变时才发送通知静默时段凌晨2点到早上8点不发送普通通知重要消息分级游戏上线通知立即发送时长提醒可以汇总发送频率限制相同游戏状态变化每小时最多提醒一次5. 部署与优化建议完成开发后我们需要让脚本长期稳定运行。以下是几个实用建议。5.1 运行环境选择本地运行最简单的方式是在个人电脑上运行使用nohup python monitor.py 保持后台运行缺点是电脑关机时监控会中断云服务器推荐使用轻量级VPS使用systemd或supervisor管理进程示例systemd服务配置[Unit] DescriptionSteam Monitor Afternetwork.target [Service] Userubuntu WorkingDirectory/path/to/script ExecStart/usr/bin/python3 monitor.py Restartalways [Install] WantedBymulti-user.target无服务器方案使用AWS Lambda或阿里云函数计算按需运行成本更低需要改造脚本为定时触发模式5.2 错误处理与日志健壮的监控脚本需要完善的错误处理API限流处理def safe_api_call(url): try: response requests.get(url, timeout10) if response.status_code 429: time.sleep(60) # 遇到限流等待1分钟 return safe_api_call(url) return response except requests.exceptions.RequestException: time.sleep(300) return None详细日志记录import logging logging.basicConfig( levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(monitor.log), logging.StreamHandler() ] ) # 在关键位置添加日志 logging.info(f状态变化{last_state} → {current_state}) logging.warning(fAPI响应异常{response.status_code})钉钉报警通知def send_error_alert(error): ding.send_text( msgf监控脚本异常{str(error)}, is_at_allTrue )5.3 性能优化技巧请求合并如果需要监控多个好友不要为每个好友单独调用API而是使用steamids参数一次查询多个用户steamids76561197960287930,76561197960287931缓存策略对不常变化的数据如好友列表进行本地缓存减少API调用增量更新只获取发生变化的数据而不是每次都拉取完整信息智能休眠在好友通常不在线的时间段如工作日上午延长检查间隔数据压缩如果部署在云函数上可以压缩传输数据减少流量消耗6. 隐私与使用规范在实现这样一个监控系统时我们必须考虑隐私和道德问题。6.1 Steam API使用限制Valve的API使用条款明确规定不得用于商业监控目的每天每个密钥的调用上限为100,000次禁止绕过隐私设置获取用户明确隐藏的信息不得对Steam服务器造成过大负荷建议遵守这些最佳实践设置合理的检查间隔不低于1分钟缓存API响应减少重复调用使用官方API而非网页爬虫只监控已经同意的好友状态6.2 钉钉消息规范钉钉机器人也有发送限制每个机器人每分钟最多发送20条消息相同内容的消息会被限流避免发送垃圾信息或广告建议合并相似通知批量发送重要消息和非重要消息使用不同机器人提供退订或静音选项6.3 道德考量虽然技术可行但监控他人游戏活动可能涉及隐私问题。建议只监控已经明确同意的好友不要将数据用于非游戏目的提供透明的退出机制不要存储或分享敏感数据在实际项目中我为好友开发这个系统时首先征得了他的同意并且让他可以随时通过特定命令查看哪些数据被收集。这种透明做法让工具既实用又不会影响友谊。