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

Spotipy调用.track(track_id)无报错阻塞 无法获取曲目数据问题

故障根因

你遇到的无响应不抛错问题,90%以上是以下几个原因导致的:

  • Spotipy默认封装的requests请求没有设置超时时间,当出现网络链路抖动、目标接口节点连接挂死、个别资源查询请求不回包也不断开连接时,程序会永久阻塞在IO等待阶段,根本不会触发异常,你写的外层try-except完全接不住这类阻塞。之所以其他接口正常,是因为Spotify不同API对应的后端服务、CDN节点是独立部署的,track接口关联预览音频资源的节点近期路由调整、节点故障都可能触发这类挂死。
  • 代码里用了裸except:,就算是有可捕获的异常(比如部分失效ID返回的格式错误)也会被直接吞掉,连错误日志都打不出来,根本没法定位问题。
  • 批量高频请求触发了Spotify的软限流:这类限流不会返回标准429错误码,只会直接hold住连接不返回任何数据,之前你能跑通是因为请求频次、总量还没到触发阈值。
  • 你当前处理的批次里刚好存在区域受限、已下架的异常track_id,这类ID查询时偶发接口不响应的已知bug,之前批次里这类ID占比低没触发问题。
排查步骤

按顺序测试即可快速定位问题:

  1. 先用公开可访问的测试track_id(比如4uLU6hMCjMI75M1A2tKUQC)单独写测试调用,手动给sp.track加10秒超时参数,看能不能正常返回,先排除全量服务故障。
  2. 打印你当前读取文件拿到的第一个track_id,单独调用接口测试,确认是不是某一个特定ID触发的挂死。
  3. 换个出口网络(比如切手机热点、换代理节点)跑同样的请求,如果恢复正常就是本地到Spotify节点的路由故障。
  4. 给请求加上日志,看请求发出后有没有收到响应头、响应体,确认是请求没发出去,还是发出去了没收到回包。
修复方案

核心要补超时、重试、错误日志三个能力,不要裸吞异常:

  1. 初始化Spotipy客户端时必须显式设置请求超时,避免永久挂死
  2. 配置自动重试和退避逻辑,应对偶发的网络抖动、限流
  3. 替换裸except,明确捕获超时、请求异常,打印错误信息方便排查
  4. 文件操作改用上下文管理器,避免异常时文件句柄泄漏,加实时刷盘避免程序中断丢数据

修复后的可运行代码:

import spotipy
import time
import requests
from spotipy.oauth2 import SpotifyClientCredentials
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# 构造带重试、超时配置的请求会话
def init_spotify_session():
    session = requests.Session()
    # 重试规则:总重试3次,退避间隔0.5s/1s/2s,遇到服务端错误、限流自动重试
    retry_config = Retry(
        total=3,
        backoff_factor=0.5,
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods=["GET"]
    )
    adapter = HTTPAdapter(max_retries=retry_config)
    session.mount("https://", adapter)
    return session

# 替换成你自己的密钥,建议不要硬编码在代码里
cid = '121e03d3acd1440188ae4c0f58b844d4'
secret = '431a5e56bcd544c3aefce8166a9c3703'
client_credentials_manager = SpotifyClientCredentials(client_id=cid, client_secret=secret)
sp = spotipy.Spotify(
    client_credentials_manager=client_credentials_manager,
    requests_session=init_spotify_session(),
    requests_timeout=10 # 核心配置:单请求10秒超时,避免永久挂死
)

number = 2
input_file = f'data/25k_data/track_url_{number}.txt'
output_file = f'data/25k_data_preview/track_url_preview_{number}.txt'

# 上下文管理器自动处理文件打开/关闭
with open(input_file, 'r', encoding='utf-8') as f_in, open(output_file, 'a', encoding='utf-8') as f_out:
    for line in f_in:
        track_id = line.strip()
        if not track_id:
            continue
        print(f"处理track_id: {track_id}")
        try:
            track_data = sp.track(track_id)
            preview_url = track_data.get('preview_url')
            if preview_url:
                f_out.write(f"{track_id} {preview_url}\n")
                f_out.flush() # 实时写入磁盘,避免程序崩溃丢已爬取的数据
            # 加100ms请求间隔,避免触发限流
            time.sleep(0.1)
        except requests.exceptions.Timeout:
            print(f"track {track_id} 请求超时,跳过")
            continue
        except Exception as e:
            print(f"track {track_id} 处理失败: {str(e)},跳过")
            continue

补充注意点:

  • 如果加了超时后出现大量超时错误,优先换网络/代理节点,基本是本地到Spotify音频CDN的路由不通导致的
  • 如果出现大量429错误,就把sleep间隔调大到0.5-1秒,降低请求频率
  • 绝对不要用不指定异常类型的裸except:,会吞掉所有错误包括键盘中断,排查问题的时候根本看不到报错信息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 04:31:04