用 Go 实现的 Google Play 应用版本号抓取 SDK,解析逻辑参考 facundoolano/google-play-scraper。
原理:抓取应用详情页(https://play.google.com/store/apps/details?id=<包名>),从页面内嵌脚本的 AF_initDataCallback 数据块中提取版本号,无需任何 API 密钥。
go get github.com/blockdancez/google-play-scraperpackage main
import (
"context"
"errors"
"fmt"
googleplay "github.com/blockdancez/google-play-scraper"
)
func main() {
ctx := context.Background()
// 方式一:包级便捷函数
version, err := googleplay.AppVersion(ctx, "com.shapley.wishly")
if err != nil {
panic(err)
}
fmt.Println(version) // 例如 "1.0.0"
// 方式二:创建客户端(可复用、可配置)
client := googleplay.NewClient(
googleplay.WithLanguage("zh"), // 页面语言,默认 "en"
googleplay.WithCountry("us"), // 商店地区,默认 "us"(不同地区版本可能不同)
)
version, err = client.AppVersion(ctx, "com.mi.ai.music")
// 错误处理
switch {
case errors.Is(err, googleplay.ErrAppNotFound):
fmt.Println("应用未上线(Google Play 上不存在)")
case errors.Is(err, googleplay.ErrVersionUnavailable):
// 大型应用(如 WhatsApp)普遍显示“因设备而异”,页面上确实没有具体版本号
fmt.Println("版本号因设备而异")
case errors.Is(err, googleplay.ErrVersionExtractFailed):
// 应用已上线但解析不到版本号 → Google 可能改版了页面,抓取逻辑需要更新
fmt.Println("解析失败,需要检查抓取逻辑")
case errors.Is(err, googleplay.ErrUnexpectedPage):
fmt.Println("拿到的不是详情页(可能被限流),建议稍后重试")
case err != nil:
fmt.Println("请求失败:", err)
default:
fmt.Println(version)
}
}| 错误 | 含义 | 应对 |
|---|---|---|
ErrAppNotFound |
应用未上线(详情页 404) | 确认包名是否正确 |
ErrVersionUnavailable |
应用已上线,版本号“因设备而异” | 正常现象,页面上就没有具体版本号 |
ErrVersionExtractFailed |
应用已上线,但解析不到版本号 | Google 可能改版了页面,需要更新抓取逻辑 |
ErrUnexpectedPage |
返回内容不是该应用的详情页 | 可能被限流,稍后重试 |
| 选项 | 说明 | 默认值 |
|---|---|---|
WithLanguage(hl) |
页面语言 | en |
WithCountry(gl) |
商店地区 | us |
WithHTTPClient(c) |
自定义 HTTP 客户端(代理、超时等) | 15 秒超时的默认客户端 |
WithBaseURL(u) |
覆盖基础地址(测试用) | https://play.google.com |
go test -short ./... # 仅本地单元测试
go test ./... # 含联网集成测试联网集成测试内置了一份 22 个包名的验证清单(googleplay_test.go 中的 validationApps),覆盖中小型应用、浏览器、游戏、大型应用(因设备而异)和不存在的应用。Google Play 页面改版后,跑一遍该测试即可确认抓取逻辑是否仍然有效。
- 本 SDK 依赖 Google Play 网页结构,Google 调整页面后可能需要适配(已兼容目前已知的两种结构)。
- 部分使用 App Bundle 分发的应用版本号显示为“因设备而异”,此时返回
ErrVersionUnavailable,属正常现象。 - 请控制请求频率,避免被 Google 限流。