Google Ads API刷新令牌(refresh token)生成与续期自动化实现方案咨询
Google Ads API刷新令牌(refresh token)生成与续期自动化实现方案咨询
兄弟,我太懂你这种手动操作的痛苦了——每次要跑定时任务还得先手动弄一遍refresh token,完全不符合自动化的初衷对吧?别慌,我给你整理了一套可行的方案,从首次获取refresh token到后续自动续期,再到定时调度,全给你安排明白。
一、前置准备工作
在动手写代码之前,得先把基础配置搞定:
- 先去Google Cloud Console创建好OAuth 2.0客户端ID,选桌面应用类型(这个类型的refresh token有效期更长,适合自动化场景)
- 把客户端密钥下载成
client_secret.json文件,存到项目目录里 - 安装必要的依赖包,执行这条命令就行:
pip install google-auth google-auth-oauthlib google-auth-httplib2 google-ads apscheduler
二、首次获取并持久化Refresh Token
这一步需要你手动操作一次(毕竟得用户授权),但之后就彻底解放双手了。下面是Python代码示例,运行后会引导你完成授权,然后自动把refresh token保存到本地文件:
from google_auth_oauthlib.flow import InstalledAppFlow import json # 配置路径和权限 CLIENT_SECRETS_FILE = 'client_secret.json' SCOPES = ['https://www.googleapis.com/auth/adwords'] # Google Ads API的核心权限 TOKEN_STORE_FILE = 'saved_refresh_token.json' def get_and_save_initial_refresh_token(): # 初始化授权流 flow = InstalledAppFlow.from_client_secrets_file( CLIENT_SECRETS_FILE, scopes=SCOPES, redirect_uri='urn:ietf:wg:oauth:2.0:oob' ) # 生成授权链接,让用户手动授权 auth_url, _ = flow.authorization_url(prompt='consent', access_type='offline') print("麻烦你复制下面的链接到浏览器打开,完成授权后复制授权码回来:") print(auth_url) auth_code = input("请输入获取到的授权码:") # 用授权码交换token flow.fetch_token(code=auth_code) credentials = flow.credentials # 把关键信息保存到本地文件,方便后续调用 token_info = { 'refresh_token': credentials.refresh_token, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'token_uri': credentials.token_uri, 'scopes': credentials.scopes } with open(TOKEN_STORE_FILE, 'w') as f: json.dump(token_info, f) print(f"搞定!Refresh Token已经存到{TOKEN_STORE_FILE}里了") if __name__ == '__main__': get_and_save_initial_refresh_token()
三、自动化续期Refresh Token
其实Google的OAuth2机制里,用refresh token换取access token的时候,系统可能会返回一个新的refresh token(用来替换旧的),所以我们要做的就是每次刷新token时,把最新的refresh token保存下来,这样就能实现自动续期。代码示例如下:
import json from google.oauth2.credentials import Credentials from google.auth.transport.requests import Request TOKEN_STORE_FILE = 'saved_refresh_token.json' def refresh_and_update_token(): # 读取之前保存的token信息 with open(TOKEN_STORE_FILE, 'r') as f: saved_token = json.load(f) # 创建Credentials对象 creds = Credentials( None, # 初始access token设为None,让系统自动刷新 refresh_token=saved_token['refresh_token'], client_id=saved_token['client_id'], client_secret=saved_token['client_secret'], token_uri=saved_token['token_uri'], scopes=saved_token['scopes'] ) # 检查token是否过期,需要刷新 if creds.expired and creds.refresh_token: # 执行刷新操作 creds.refresh(Request()) # 如果返回了新的refresh token,就更新保存的文件 if creds.refresh_token: saved_token['refresh_token'] = creds.refresh_token with open(TOKEN_STORE_FILE, 'w') as f: json.dump(saved_token, f) print("Refresh Token已经自动更新并保存啦") else: print("成功获取新的Access Token,Refresh Token暂时不用更新") else: print("当前Access Token还没过期,不用刷新") # 这里可以直接用刷新后的creds调用Google Ads API # 比如初始化Google Ads客户端: from google.ads.googleads.client import GoogleAdsClient ads_client = GoogleAdsClient.load_from_credentials(creds, version='v15') # 接下来就可以写你的 campaign 数据查询逻辑了 # ... 你的业务代码 ... if __name__ == '__main__': refresh_and_update_token()
四、定时调度全自动化
要实现定时跑脚本,比如每天自动刷新token并获取广告数据,用APScheduler或者系统自带的cron都可以。这里给你个APScheduler的示例,直接整合到脚本里:
from apscheduler.schedulers.blocking import BlockingScheduler import time from refresh_token_script import refresh_and_update_token # 刚才写的刷新token的函数 # 初始化调度器 scheduler = BlockingScheduler(timezone='Asia/Shanghai') # 配置定时任务:比如每天凌晨1点执行一次 @scheduler.scheduled_job('cron', hour=1, minute=0) def daily_ads_task(): print(f"===== 开始执行定时任务:{time.strftime('%Y-%m-%d %H:%M:%S')} =====") refresh_and_update_token() # 这里加上你获取和处理Google Ads campaign数据的代码 # ... 你的业务逻辑 ... print("===== 定时任务执行完成 =====") if __name__ == '__main__': try: print("定时任务已启动,按Ctrl+C可停止") scheduler.start() except KeyboardInterrupt: print("定时任务已手动停止")
几个关键注意事项
- 如果你用的是Google Workspace账号,也可以试试服务账号授权,这种方式不需要refresh token,直接用服务账号密钥就能授权,完全不用手动干预,适合企业级的自动化场景(不过得在Workspace后台给服务账号开权限)
- 敏感信息(比如客户端密钥、refresh token)绝对不能硬编码,要么用环境变量,要么用加密配置文件,别给自己埋雷
- 如果refresh token超过6个月没使用,或者用户取消了授权,那就得重新手动授权获取新的了,这个是Google的规则,没法绕过去
- 记得保持Google Ads API的版本和依赖包版本一致,避免出现兼容性问题
备注:内容来源于stack exchange,提问作者Disha Sood




