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

如何用Python无需浏览器获取Spotify API认证重定向的最终URL

解决Spotify API授权码流程无浏览器获取回调URL的问题

问题本质

你拿到的登录URL属于Spotify OAuth2授权码流程的用户授权环节,这个环节必须经过用户登录+授权操作才能生成带code的回调URL。纯urllib或requests的HTTP请求无法模拟浏览器的登录交互(比如输入账号密码、处理Session/Cookie、验证码验证),所以直接请求只会返回登录页面,拿不到最终的回调链接。

可行解决方案

方案1:用无头浏览器模拟交互(推荐,适合本地开发)

用Playwright或Selenium这类无头浏览器工具,模拟真实浏览器的登录、授权操作,自动获取回调URL中的code。

以Playwright为例:

  1. 安装依赖:
pip install playwright
playwright install chromium
  1. 示例代码:
from playwright.sync_api import sync_playwright
import urllib.parse

def get_spotify_code():
    AUTH_URL = "你获取到的登录URL"
    REDIRECT_URI = "http://localhost:5000/"
    
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)  # 设为False可看到浏览器窗口
        page = browser.new_page()
        page.goto(AUTH_URL)
        
        # 填写Spotify账号密码(替换为你的账号信息)
        page.fill('input[name="username"]', "你的Spotify邮箱/用户名")
        page.fill('input[name="password"]', "你的Spotify密码")
        page.click('button[type="submit"]')
        
        # 等待授权页面加载并点击授权按钮(首次授权会出现)
        page.wait_for_selector('button[data-testid="auth-accept"]')
        page.click('button[data-testid="auth-accept"]')
        
        # 等待跳转到回调URL
        page.wait_for_url(f"{REDIRECT_URI}*")
        
        # 提取URL中的code参数
        current_url = page.url
        parsed_url = urllib.parse.urlparse(current_url)
        code = urllib.parse.parse_qs(parsed_url.query)['code'][0]
        
        browser.close()
        return code

# 使用示例
spotify_code = get_spotify_code()
print(f"获取到的授权code:{spotify_code}")

注意:如果Spotify触发验证码验证,需手动处理,或提前在浏览器登录后导出Cookie,让无头浏览器复用Cookie跳过登录步骤。

方案2:改用设备授权流程(无UI环境首选)

如果运行环境没有浏览器界面,推荐使用Spotify的设备授权流程(Device Authorization Flow),无需浏览器,仅需用户在其他设备上完成验证:

  1. 流程步骤:

    • 向https://accounts.spotify.com/api/device-authorization发送POST请求,携带client_id和scope
    • 获取user_code(用户需输入的验证码)和verification_uri(用户验证的URL)
    • 提示用户访问verification_uri并输入user_code
    • 轮询https://accounts.spotify.com/api/token,直到拿到授权code或access_token
  2. 示例代码:

import requests
import time

CLIENT_ID = "你的Spotify Client ID"
SCOPE = "playlist-modify-private"

def device_auth_flow():
    # 1. 获取设备授权信息
    device_auth_url = "https://accounts.spotify.com/api/device-authorization"
    payload = {
        "client_id": CLIENT_ID,
        "scope": SCOPE
    }
    response = requests.post(device_auth_url, data=payload)
    device_data = response.json()
    
    user_code = device_data['user_code']
    verification_uri = device_data['verification_uri']
    interval = device_data['interval']
    device_code = device_data['device_code']
    
    print(f"请访问:{verification_uri}")
    print(f"输入验证码:{user_code}")
    
    # 2. 轮询获取授权
    token_url = "https://accounts.spotify.com/api/token"
    while True:
        token_payload = {
            "client_id": CLIENT_ID,
            "device_code": device_code,
            "grant_type": "urn:ietf:params:oauth:grant-type:device_code"
        }
        token_response = requests.post(token_url, data=token_payload)
        token_data = token_response.json()
        
        if token_response.status_code == 200:
            print(f"授权成功!access_token:{token_data['access_token']}")
            break
        elif token_data['error'] == "authorization_pending":
            time.sleep(interval)
        elif token_data['error'] == "expired_token":
            print("验证码已过期,请重新发起请求")
            break
        else:
            print(f"授权失败:{token_data['error']}")
            break

# 使用示例
device_auth_flow()

方案3:手动模拟登录(不推荐)

尝试用requests.Session保存Cookie,手动提取登录页面的CSRF token并模拟登录,但Spotify的登录页面有动态验证逻辑(比如reCAPTCHA),这个方法极易失效,仅作参考:

import requests
import urllib.parse
from bs4 import BeautifulSoup

def simulate_login():
    AUTH_URL = "你获取到的登录URL"
    SESSION = requests.Session()
    
    # 1. 获取登录页面,提取CSRF token
    login_page = SESSION.get(AUTH_URL)
    soup = BeautifulSoup(login_page.text, 'html.parser')
    csrf_token = soup.find('input', {'name': 'csrf_token'})['value']
    
    # 2. 模拟登录请求
    login_payload = {
        'username': '你的账号',
        'password': '你的密码',
        'csrf_token': csrf_token,
        'remember': 'true'
    }
    login_response = SESSION.post("https://accounts.spotify.com/login", data=login_payload)
    
    # 3. 访问授权页面,获取回调URL
    parsed_auth_url = urllib.parse.urlparse(AUTH_URL)
    continue_url = urllib.parse.parse_qs(parsed_auth_url.query)['continue'][0]
    authorize_response = SESSION.get(continue_url)
    
    # 检查是否跳转到回调URL
    if authorize_response.url.startswith("http://localhost:5000/"):
        parsed_callback = urllib.parse.urlparse(authorize_response.url)
        code = urllib.parse.parse_qs(parsed_callback.query)['code'][0]
        print(f"获取到code:{code}")
    else:
        print("登录失败或需要验证码")

# 使用示例
simulate_login()

为什么之前的方法无效

urllib.request.urlopen(auth_request.url)只会发送一次HTTP请求,获取登录页面的内容,不会处理后续的用户登录、授权交互。Spotify的授权流程必须经过用户确认,纯HTTP请求无法完成这个环节,所以无法拿到带code的回调URL。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 04:54:56