Python调用YouTube Data API v3出现KeyError: 'access_token'问题求助
问题:YouTube批量订阅程序触发KeyError: 'access_token'
我正在编写Python程序批量管理YouTube账户,已在代码中配置好YouTube Data API密钥、Client ID、Client Secret,但运行时触发如下错误:
Traceback (most recent call last): File "/data/user/0/ru.iiec.pydroid3/files/temp_iiec_codefile.py", line 56, in <module> main() File "/data/user/0/ru.iiec.pydroid3/files/temp_iiec_codefile.py", line 51, in main access_token = login_google(email, password) File "/data/user/0/ru.iiec.pydroid3/files/temp_iiec_codefile.py", line 35, in login_google return json.loads(response.text)["access_token"] KeyError: 'access_token'
程序本该在选择账户文件后提示输入频道ID进行订阅,却直接报错,附上代码如下:
import os import json import requests from tkinter import Tk from tkinter.filedialog import askopenfilename # Google API 配置信息 API_KEY = "hided" CLIENT_ID = "hided" CLIENT_SECRET = "hided" REDIRECT_URI = "hided" # 读取账户文件 def read_file(): Tk().withdraw() filename = askopenfilename() with open(filename, 'r') as file: accounts = file.readlines() return accounts # 尝试通过邮箱密码登录Google获取token def login_google(email, password): data = { "email": email, "password": password, "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET, "redirect_uri": REDIRECT_URI, "grant_type": "password" } headers = { "Content-Type": "application/x-www-form-urlencoded" } response = requests.post("https://accounts.google.com/o/oauth2/token", data=data, headers=headers) return json.loads(response.text)["access_token"] # 订阅YouTube频道 def subscribe_youtube(channel_id, access_token): headers = { "Authorization": "Bearer " + access_token, "Content-Length": "0" } response = requests.post("https://www.googleapis.com/youtube/v3/subscriptions?part=snippet&key=" + API_KEY, headers=headers) print(response.text) # 主函数 def main(): accounts = read_file() for account in accounts: email, password = account.split(":") access_token = login_google(email, password) channel_id = input("Enter the channel ID: ") subscribe_youtube(channel_id, access_token) if __name__ == "__main__": main()
解决方案
1. 根本问题:密码授权模式已被Google废弃
你当前使用的grant_type: password是OAuth 2.0的密码授权模式,Google早在多年前就禁用了该模式,无法再通过邮箱密码直接获取access_token,这是触发KeyError: 'access_token'的核心原因。
2. 改用官方推荐的授权码模式
必须使用OAuth 2.0授权码模式(Authorization Code Flow),流程如下:
- 引导用户打开Google授权页面,获取授权码
- 用授权码交换access_token和refresh_token
- 后续可通过refresh_token刷新过期的access_token
3. 修正后的代码示例
import json import requests from tkinter import Tk from tkinter.filedialog import askopenfilename import webbrowser # Google API 配置 API_KEY = "你的API密钥" CLIENT_ID = "你的Client ID" CLIENT_SECRET = "你的Client Secret" REDIRECT_URI = "http://localhost:8080" # 需在Google Cloud控制台配置为已授权重定向URI SCOPE = "https://www.googleapis.com/auth/youtube.force-ssl" # 读取存储refresh_token的文件 def read_refresh_tokens(): Tk().withdraw() filename = askopenfilename() with open(filename, 'r') as file: refresh_tokens = [line.strip() for line in file.readlines()] return refresh_tokens # 获取授权码(首次授权用) def get_authorization_code(): auth_url = ( f"https://accounts.google.com/o/oauth2/v2/auth?response_type=code" f"&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&scope={SCOPE}" f"&access_type=offline&prompt=consent" ) webbrowser.open(auth_url) return input("请输入授权页面跳转后URL中的code参数: ") # 用授权码交换token(首次授权用) def exchange_code_for_token(code): data = { "code": code, "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET, "redirect_uri": REDIRECT_URI, "grant_type": "authorization_code" } response = requests.post("https://oauth2.googleapis.com/token", data=data) return response.json() # 用refresh_token刷新access_token def refresh_access_token(refresh_token): data = { "refresh_token": refresh_token, "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET, "grant_type": "refresh_token" } response = requests.post("https://oauth2.googleapis.com/token", data=data) return response.json()["access_token"] # 订阅YouTube频道 def subscribe_youtube(channel_id, access_token): url = f"https://www.googleapis.com/youtube/v3/subscriptions?part=snippet" headers = { "Authorization": f"Bearer {access_token}", "Content-Type": "application/json" } payload = { "snippet": { "resourceId": { "kind": "youtube#channel", "channelId": channel_id } } } response = requests.post(url, headers=headers, json=payload) print("订阅响应:", response.text) # 主函数 def main(): # 首次授权获取refresh_token,执行一次后注释,将token保存到文件 # code = get_authorization_code() # token_data = exchange_code_for_token(code) # print("保存此refresh_token到文件:", token_data["refresh_token"]) # 读取已保存的refresh_token列表 refresh_tokens = read_refresh_tokens() channel_id = input("请输入要订阅的YouTube频道ID: ") for token in refresh_tokens: try: access_token = refresh_access_token(token) subscribe_youtube(channel_id, access_token) print(f"当前账户订阅成功") except Exception as e: print(f"当前账户订阅失败: {str(e)}") if __name__ == "__main__": main()
4. 额外注意事项
- 在Google Cloud控制台的OAuth同意屏幕中,添加
https://www.googleapis.com/auth/youtube.force-ssl权限范围 - 确保重定向URI
http://localhost:8080已添加到项目的授权重定向URI列表中 - 首次运行时取消注释授权相关代码,获取refresh_token并保存到文件,后续直接读取该文件即可批量操作
内容的提问来源于stack exchange,提问作者Raskoln
相关产品推荐
相关产品推荐

