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

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权限范围
  • 确保重定向URIhttp://localhost:8080已添加到项目的授权重定向URI列表中
  • 首次运行时取消注释授权相关代码,获取refresh_token并保存到文件,后续直接读取该文件即可批量操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 21:41:11