企业环境Jupyter调用Google Analytics Data API遇SSL验证问题求助
问题描述
代码在Google Colab中运行正常,但本地Jupyter Notebook环境下出现以下问题:
- 初始报错:
DeadlineExceeded: 504 Deadline Exceeded
- 设置企业代理
os.environ['HTTPS_PROXY'] = proxy后,出现SSL握手错误:
google.api_core.exceptions.ServiceUnavailable: 503 failed to connect to all addresses; last error: UNKNOWN: ipv4:192.168.152.200:8080: Ssl handshake failed: SSL_ERROR_SSL: error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED
排查过程
- 运行不含代理的测试代码时,出现超时错误
TimeoutError: [WinError 10060],确认必须通过代理访问Google服务。 - 添加代理后,测试代码出现SSL证书验证失败:
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1002)
- 给
httplib2.Http添加disable_ssl_certificate_validation=True后测试代码正常运行,但无法找到Google Analytics Data API客户端BetaAnalyticsDataClient的SSL验证禁用方式。 - 尝试设置
GRPC_DEFAULT_SSL_ROOTS_FILE_PATH、CURL_CA_BUNDLE等环境变量均无效,问题根源为企业代理/杀毒软件的SSL证书拦截。
解决方案
方法1:为gRPC客户端配置不安全SSL上下文(跳过证书验证)
Google Analytics Data API默认使用gRPC协议,需自定义gRPC通道以禁用SSL证书验证:
import pandas as pd import numpy as np import os import grpc from google.analytics.data_v1beta import BetaAnalyticsDataClient from google.analytics.data_v1beta.types import DateRange, Dimension, Metric, RunReportRequest, OrderBy from google.oauth2 import service_account # 配置代理与服务账号凭证 proxy = "http://192.168.152.200:8080" os.environ['https_proxy'] = proxy os.environ['HTTPS_PROXY'] = proxy cred_path = 'D:\***\scripts\credentials\***f.json' os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = cred_path # 加载服务账号凭证 credentials = service_account.Credentials.from_service_account_file( cred_path, scopes=["https://www.googleapis.com/auth/analytics.readonly"] ) # 创建跳过SSL验证的gRPC通道 channel = grpc.secure_channel( "analyticsdata.googleapis.com:443", # 传入空的SSL凭证表示跳过验证 credentials.with_channel_credentials(grpc.ssl_channel_credentials(None, None, None)), options=[ ("grpc.proxy_target", proxy), ("grpc.ssl_target_name_override", "analyticsdata.googleapis.com"), ("grpc.default_authority", "analyticsdata.googleapis.com") ] ) # 使用自定义通道初始化API客户端 client = BetaAnalyticsDataClient(channel=channel) # 原报告格式化函数与请求逻辑保持不变 def format_report(request): response = client.run_report(request) row_index_names = [header.name for header in response.dimension_headers] row_header = [] for i in range(len(row_index_names)): row_header.append([row.dimension_values[i].value for row in response.rows]) row_index_named = pd.MultiIndex.from_arrays(np.array(row_header), names=np.array(row_index_names)) metric_names = [header.name for header in response.metric_headers] data_values = [] for i in range(len(metric_names)): data_values.append([row.metric_values[i].value for row in response.rows]) output = pd.DataFrame( data=np.transpose(np.array(data_values, dtype='f')), index=row_index_named, columns=metric_names ) return output property_id = '***' request = RunReportRequest( property='properties/'+property_id, dimensions=[Dimension(name="month"), Dimension(name="sessionMedium")], metrics=[Metric(name="averageSessionDuration"), Metric(name="activeUsers")], order_bys=[ OrderBy(dimension={'dimension_name': 'month'}), OrderBy(dimension={'dimension_name': 'sessionMedium'}) ], date_ranges=[DateRange(start_date="2023-01-01", end_date="today")], ) format_report(request)
方法2:导入企业根证书到Python信任库(推荐)
如果不想禁用SSL验证,可将企业代理的根证书添加到Python的信任体系:
- 导出企业代理的根证书为PEM格式(通常可从代理管理界面或浏览器证书导出功能获取)。
- 找到Python的默认CA证书路径:
import certifi print(certifi.where())
- 将企业根证书的内容追加到上述路径的文件中,或设置环境变量指定证书路径:
os.environ['GRPC_DEFAULT_SSL_ROOTS_FILE_PATH'] = 'path/to/your/enterprise-ca.pem'
方法3:强制API使用REST协议而非gRPC
部分Google API支持强制使用REST协议,可通过环境变量切换,之后可复用httplib2的SSL处理逻辑:
# 强制使用REST协议 os.environ['GOOGLE_API_USE_GRPC'] = 'False' # 若需禁用SSL验证,添加以下环境变量(不推荐) os.environ['REQUESTS_CA_BUNDLE'] = '' os.environ['CURL_CA_BUNDLE'] = ''
设置后初始化BetaAnalyticsDataClient即可使用REST方式调用,代理配置保持不变。
内容的提问来源于stack exchange,提问作者YURIY ALEKSEEV

