抓取 App Store 和 Google Play 评论:端点、限制、地理位置

应用评论是您能买到的最便宜的产品研究——如果您能突破分页限制、令牌墙和按国家的店面。这里是完整的地图。

应用评论是最便宜的客户研究:未过滤的功能请求、与特定版本相关的错误报告,以及对您类别中每个竞争对手的持续情感读取。问题在于访问。两个商店在页面上显示少量评论,并将其余的隐藏在提要、令牌和按国家的店面后面。本指南绘制了如何抓取 App Store 和 Google Play 评论的地图——真实的端点、没人警告您的分页限制,以及决定您的管道能否在几百行后幸存的地理和速率限制现实。

Apple,简单的方法:RSS 提要

Apple 公开了一个无需令牌的客户评论 JSON 提要。这是最快的开始方式,返回干净、结构化的记录——评分、标题、正文、作者、应用版本。限制是硬性上限:提要最多提供约 10 页、每页约 50 条评论,因此每个应用每个店面约 500 条评论,偏向最新的。对于监控新反馈,这通常足够;对于完整历史记录则不然。

import requests

def apple_rss_reviews(app_id, country="us", pages=10):
    out = []
    for page in range(1, pages + 1):  # feed caps out around page 10
        url = (f"https://itunes.apple.com/{country}/rss/customerreviews/"
               f"page={page}/id={app_id}/sortby=mostrecent/json")
        # route through a residential exit in the target storefront's country
        proxy = f"http://USER-country-{country}:PASS@gate.quantumproxies.io:8000"
        r = requests.get(url, proxies={"https": proxy}, timeout=20)
        entries = r.json().get("feed", {}).get("entry", [])
        for e in entries[1:]:  # first entry is app metadata, skip it
            out.append({
                "rating":  e["im:rating"]["label"],
                "version": e["im:version"]["label"],
                "title":   e["title"]["label"],
                "text":    e["content"]["label"],
                "author":  e["author"]["name"]["label"],
            })
        if len(entries) <= 1:
            break
    return out

Apple,深入的方法:app-store API 及其令牌

要超过 500 条,您使用与 App Store 网页调用相同的端点(AMP / MZStore API)。它返回更丰富的记录——评论 ID、编辑标志、开发者响应——但需要您首先从应用的公共网页抓取承载令牌,然后重放。评论以大约二十条为一批,您通过offset分页更深;偏移量越大,评论往往越旧,因为 Apple 不允许此端点直接按日期排序。

这里的真正限制是速率限制,并且从单个 IP 快速到来。解决方法不是魔法——是故意的延迟加上指数回退,并跨 IP 分布请求。添加了这两者的从业者已经为一个应用提取了大约 15,000 条评论而没有触发限制器。这正是旋转住宅池的价值所在:每批可以从不同的干净 IP 退出,因此每个 IP 的计数器永远不会攀升到封锁区域。

import time, requests

# token is scraped once from the app's App Store web page, then reused
HEADERS = {"Authorization": "Bearer TOKEN_FROM_APP_PAGE",
           "Origin": "https://apps.apple.com"}

def apple_deep_reviews(app_id, country="us", target=2000):
    reviews, offset = [], None
    while len(reviews) < target:
        params = {"l": "en-US", "offset": offset} if offset else {"l": "en-US"}
        url = (f"https://amp-api.apps.apple.com/v1/catalog/{country}/apps/"
               f"{app_id}/reviews")
        proxy = f"http://USER:PASS@rotating.quantumproxies.io:8000"
        r = requests.get(url, headers=HEADERS, params=params,
                         proxies={"https": proxy}, timeout=25)
        if r.status_code == 429:            # rate limited
            time.sleep(8); continue          # back off, gateway rotates the IP
        data = r.json()
        reviews += data.get("data", [])
        offset = data.get("next", "").split("offset=")[-1] or None
        if not offset:
            break
        time.sleep(1.5)                      # be a polite client
    return reviews
Apple 的 RSS 客户评论提要与 AMP app-store API 的比较,显示分页限制和令牌要求
RSS 提要快速但限制在约 500;令牌 API 深入但从一个 IP 严格速率限制。

Google Play:已填充的 JSON,而不是 HTML

Play 评论不在页面 HTML 中。商店通过返回嵌套 JSON 的内部批处理端点加载它们,使用延续令牌而不是页码分页,并按排序顺序(最新、评分、帮助)过滤。手动重建这些请求很麻烦,因此大多数团队依赖于维护良好的开源google-play-scraper库(Node 和 Python),它们包装了端点并公开countrylang参数。与 Apple 一样,按国家的结果不同,因此要明确设置两者。

# pip install google-play-scraper
from google_play_scraper import reviews, Sort

result, token = reviews(
    "com.example.app",
    lang="en",       # review language
    country="us",    # storefront
    sort=Sort.NEWEST,
    count=200,       # per call; loop with continuation_token for more
)
for r in result[:3]:
    print(r["score"], r["reviewCreatedVersion"], r["content"][:80])

在实际体量下,Play 端点也按 IP 节流,并且 JSON 结构会定期变化。如果您不想承担该维护责任,Scraper API可以将填充的数据呈现并返回为干净的 JSON,解决这两个问题——它负责代理和解析,因此您可以消费稳定的形状。我们为大规模抓取产品评论描述的相同权衡逻辑直接适用于此。

一个字段对让人困惑:语言和国家不是同一个旋钮。店面(国家)决定哪些评论存在;语言参数决定您获得哪些。在加拿大或瑞士这样的双语市场中,您通常需要两种语言,因此要独立设置它们,而不是假设一个国家意味着一种语言。在 Apple 的一边,更丰富的记录还显示开发者响应——供应商在评论下发布的公开回复——这是一个安静而有价值的信号,显示竞争对手如何分流投诉以及他们选择公开回答哪些问题。

地理店面是关键

两个商店都按国家店面组织,以两字母代码为键。一个应用在美国的评论无法告诉您它在德国、日本或巴西的表现——不同的语言、不同的投诉、不同的功能缺口。要诚实地阅读每个店面,您需要从该国的出口 IP 请求;错误区域的数据中心 IP 会给您不一致或被封锁的响应。通过遍布 200 多个国家的住宅出口,您可以将同一个应用循环通过每个市场,构建一个按国家的情感地图——严肃 ASO 工作的原材料。

从选择店面到获取评论再到应用商店优化信号的管道
价值在下游:解析评分和版本,然后将评论汇总成主题和按版本回归。

从评论到 ASO 信号

提取是无聊的一半。回报是您在其上计算的内容:将评论文本聚类成重复主题,按应用版本跟踪情感以捕捉降低您评分的发布,观察竞争对手的功能请求您的产品已经回答,并比较各店面的投诉模式。将每条评论与其version字段关联,您将获得没有分析仪表盘提供的回归时间线。相关的声誉工作——Trustpilot 评论挖掘——与应用商店数据整齐地堆叠在一起,形成完整的客户声音画面。

为每个应用店面获取住宅 IP

常见问题

如何用 Python 抓取 App Store 评论?

从 Apple 的公共 RSS 客户评论 JSON 提要开始——无需令牌,结构化输出,但限制在每个应用每个店面约 500 条最近评论。要更深入,请使用从应用网页抓取的承载令牌调用 AMP app-store API,使用offset分页,并添加延迟加上回退。通过该国的住宅 IP 路由每个店面。

是否有官方的 App Store 评论 API?

Apple 的公共 RSS 提要是最接近官方的、无令牌的评论来源,但它有上限。更丰富的 AMP 端点是商店自己的网页使用的,并需要抓取的承载令牌。两者都不是用于大规模第三方评论收集的文档化开发者产品,因此请谨慎对待速率限制和条款。

如何抓取 Google Play 评论?

Play 从返回嵌套 JSON 的内部批处理端点提供评论,按延续令牌分页并可按排序顺序过滤。维护良好的开源google-play-scraper库包装了它并公开countrylang。设置两者,循环延续令牌以获取体量,并跨 IP 分布请求,因为端点按地址节流。

为什么需要代理来抓取应用评论?

两个原因。速率限制:两个商店快速限制单个 IP,因此旋转住宅出口保持每个 IP 的计数器足够低以提取数千条评论。地理位置:评论是店面特定的,因此准确读取一个国家的评论意味着从该国的 IP 请求。错误区域的数据中心 IP 会得到不一致或被封锁的响应。

应用商店数据是一个被三个简单障碍——限制、令牌和店面——封锁的金矿。知道要命中哪个端点,正确分页,并从正确国家的干净 IP 退出,您就可以将分散的星级评分转化为按版本、按市场的客户声音提要。

让 Scraper API 将评论数据返回为 JSON