You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Python调用GA4 API获取数据时的gRPC反序列化错误

问题

我使用以下Python代码从GA4获取数据:

credentials = service_account.Credentials.from_service_account_info(self.credential_info)
client = BetaAnalyticsDataAsyncClient(credentials=credentials)
offset = 0  # Start at the first row
limit = 100000  # Maximum number of rows to return per request
request = RunReportRequest(
                  property=f"properties/{self.property_id}",
                  date_ranges=[DateRange(start_date=start, end_date=end)],
                  dimensions=[some_dimensions],
                  metrics=[some_metrics],
                  dimension_filter=None,
                  keep_empty_rows=True,
                  limit=limit,
                  offset=offset,
             )
response = await client.run_report(request)

部分Property ID对应的请求能正常运行,但有时会触发gRPC反序列化错误导致程序崩溃,错误栈如下:

ERROR:grpc._common:Exception deserializing message!
Traceback (most recent call last):

  File "C:\Users\TM-USER\Desktop\henry\datascience\.venv\Lib\site-packages\grpc\_common.py", line 89, in _transform
    return transformer(message)
           ^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\TM-USER\Desktop\henry\datascience\.venv\Lib\site-packages\proto\message.py", line 370, in deserialize
    return cls.wrap(cls.pb().FromString(payload))
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

google.protobuf.message.DecodeError: Error parsing message

测试发现将offset改为2000即可正常运行,说明前2000行数据存在异常。已更新google-analytics-data至最新版本,但问题仍未解决,求修复方法。

解决方案

1. 分段遍历数据,定位并跳过异常区间

既然已知前2000行触发问题,可以用小批量拉取的方式定位具体异常行,同时避免程序崩溃:

# 处理前2000行,用小批量尝试
offset = 0
batch_size = 100
while offset < 2000:
    try:
        request = RunReportRequest(
            property=f"properties/{self.property_id}",
            date_ranges=[DateRange(start_date=start, end_date=end)],
            dimensions=[some_dimensions],
            metrics=[some_metrics],
            dimension_filter=None,
            keep_empty_rows=True,
            limit=batch_size,
            offset=offset,
        )
        response = await client.run_report(request)
        # 处理当前批量数据
        offset += batch_size
    except google.protobuf.message.DecodeError:
        # 跳过当前异常批量,记录位置
        print(f"跳过异常行区间: {offset}-{offset+batch_size}")
        offset += batch_size

# 处理2000行之后的数据,用正常批量
offset = 2000
limit = 100000
while True:
    request = RunReportRequest(
        property=f"properties/{self.property_id}",
        date_ranges=[DateRange(start_date=start, end_date=end)],
        dimensions=[some_dimensions],
        metrics=[some_metrics],
        dimension_filter=None,
        keep_empty_rows=True,
        limit=limit,
        offset=offset,
    )
    response = await client.run_report(request)
    # 处理数据
    if len(response.rows) < limit:
        break
    offset += limit

2. 禁用gRPC,改用HTTP/1.1传输

gRPC反序列化问题可能和传输协议有关,强制客户端使用HTTP/1.1绕过gRPC解析:

from google.api_core import client_options

client_options = client_options.ClientOptions(api_endpoint="analyticsdata.googleapis.com:443", use_grpc=False)
client = BetaAnalyticsDataAsyncClient(credentials=credentials, client_options=client_options)

3. 排查维度/指标中的特殊字符

异常行可能包含非标准字符导致protobuf解析失败,可通过以下方式排查:

  • 先只保留核心维度(如date)和指标(如activeUsers),如果请求正常,再逐个添加原维度/指标,定位触发错误的字段。
  • 对可能包含特殊字符的维度(如pageTitle、eventName)添加过滤规则,排除非UTF-8字符:
from google.analytics.data_v1beta.types import FilterExpression, Filter, StringFilter

# 过滤包含非ASCII字符的pageTitle
dimension_filter = FilterExpression(
    filter=Filter(
        field_name="pageTitle",
        string_filter=StringFilter(
            match_type=StringFilter.MatchType.NOT_CONTAINS,
            value=r"[^\x00-\x7F]"
        )
    )
)

request = RunReportRequest(
    # 其他参数不变
    dimension_filter=dimension_filter
)

4. 上报问题到官方渠道

如果以上方法都无效,大概率是GA4后端存在异常数据,需要:

  • 记录触发问题的Property ID、日期范围、维度指标组合。
  • 通过Google Cloud支持或GA4官方反馈渠道提交问题,提供完整错误栈和复现步骤,请求官方排查修复。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:35:04