You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Steam评论爬虫提前终止、抓取量不稳定问题排查与解决咨询

解决Steam爬虫提前终止与Cursor动态变化的问题

我来帮你拆解这个问题,结合Steam API的机制和你用的aesuli/steam-crawler脚本的问题点,一步步分析原因和解决方案:

一、为什么会随机提前终止?

你用的正则endre = re.compile(r'({"success":2})|(no_more_reviews)')是核心问题所在:

  • {"success":2}并不是真的没有更多评论了,Steam API返回这个值通常是临时限流、服务器负载过高或者请求参数异常,属于可恢复的错误,不是终止信号。
  • 用正则匹配JSON字符串本身就不可靠,Steam的API返回格式可能有细微变化(比如空格、转义符差异),会导致误判no_more_reviews或者success:2,从而提前终止抓取。
  • 对于CS:GO这种百万级评论的游戏,请求频率很容易触发Steam的限流机制,这时候脚本直接终止,而不是重试,就会出现抓取页数随机的情况。

二、为什么Cursor会随机变化?

Steam的cursor不是固定的页码,而是一个动态生成的加密标记,它指向评论列表中的具体位置,并且会受到以下因素影响:

  • 评论的实时更新(新评论发布、旧评论被删除);
  • 服务器的负载均衡策略;
  • 请求的时间窗口和用户代理等参数。

它的作用是让API准确返回下一页的评论,而不是基于固定页码——因为百万级的评论列表如果用页码,会因为实时更新导致数据重复或遗漏。所以每次请求返回的cursor都是唯一的,不能复用之前的,必须用当前页返回的cursor请求下一页。如果脚本没有正确提取和传递最新的cursor,就会请求到错误的页面,触发终止条件。

三、可行的解决方案

1. 替换正则判断,改用JSON解析终止条件

不要用正则匹配字符串,直接解析API返回的JSON数据,这是最可靠的方式:

import json
import time

# 假设你获取到了API的response文本
try:
    resp_data = json.loads(response.text)
except json.JSONDecodeError:
    # 解析失败,重试当前页
    time.sleep(3)
    continue

# 处理不同的success状态
if resp_data.get("success") == 2:
    # 临时限流/错误,指数退避重试
    time.sleep(5)  # 可以根据情况递增等待时间
    continue
elif resp_data.get("success") != 1:
    # 其他错误,记录日志后跳过
    print(f"Unexpected success code: {resp_data.get('success')}")
    continue

# 判断是否真的没有更多评论
reviews = resp_data.get("reviews", [])
next_cursor = resp_data.get("cursor")
if not reviews or not next_cursor:
    # 没有评论或没有下一页cursor,终止抓取
    break

# 处理当前页的评论数据(日期、内容、用户ID等)
# ...

# 用最新的cursor请求下一页
next_url = f"https://store.steampowered.com/appreviews/{app_id}?cursor={next_cursor}&..."

2. 正确处理Cursor的传递

每次请求必须使用上一页返回的cursor参数,不能复用旧的URL或cursor。Steam的cursor是一次性的,用过之后就会失效,所以必须从当前页的返回数据中提取最新的cursor,作为下一页请求的参数。

3. 添加请求频率控制与重试机制

  • 请求间隔:每页请求后添加1-2秒的等待时间,避免触发Steam的限流。对于百万级评论的游戏,甚至可以适当延长等待时间,降低被ban的风险。
  • 指数退避重试:遇到success:2或者请求失败时,不要直接终止,而是等待一段时间后重试,等待时间可以递增(比如第一次等3秒,第二次等6秒,最多重试5次)。

4. 放弃“保存已请求URL重复循环”的思路

这个方法不可行,因为每个URL的cursor是唯一的,重复请求同一个URL只会得到相同的内容,而且会增加触发限流的概率。正确的做法是跟踪当前的cursor,逐步推进抓取。

总结

你的核心问题是终止条件判断不准确,加上没有正确处理Steam API的动态cursor和限流机制。改用JSON解析判断终止状态、正确传递cursor、添加重试和请求间隔,就能解决CS:GO这类大评论量游戏的提前终止问题。

内容的提问来源于stack exchange,提问作者Jauhnax

火山引擎 最新活动