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

Python YouTube API脚本调试:解决KeyError及优化需求

问题分析与解决方案

错误原因

你的KeyError: 'videoId'是因为YouTube Data API的search.list接口返回的结果不仅包含视频,还可能包含频道、播放列表等类型条目,这些条目的id字段里没有videoId,只有channelId或playlistId,直接提取会报错。

另外原脚本还有几个逻辑问题:

  • youtube_search函数中,return videos_with_view_counts之后的代码永远不会执行
  • 返回的videos_with_view_counts仅包含视频ID和观看数,但main函数里试图访问snippet等不存在的字段,会引发新错误
  • 当前用search.list是搜索特定关键词的结果,并非全平台热门视频

修复与优化方案

1. 核心修复:过滤视频类型条目

在提取videoId前,先判断条目类型为youtube#video:

ids = [item["id"]["videoId"] for item in search_response["items"] if item["id"]["kind"] == "youtube#video"]

2. 全平台热门视频抓取

改用videos.list接口,指定chart="mostPopular"参数,直接获取全YouTube热门视频,无需搜索关键词:

videos_response = youtube.videos().list(
    part="snippet,statistics,channelStatistics",
    chart="mostPopular",
    maxResults=options.max_results,
    regionCode="US"  # 可指定地区,默认全球
).execute()

3. 加权排序实现

自定义权重公式(可按需调整),例如:
加权分 = 观看数*0.5 + 点赞数*0.3 + 频道订阅数*0.2
对视频列表按加权分降序排序(热门内容在前)

4. 其他优化

  • 将API密钥改为命令行参数传入,避免硬编码
  • 处理缺失字段(如部分视频无点赞数,设默认值0)
  • 写入总观看数到单独文件
  • 完善API请求错误处理

完整优化脚本

import csv
import os
import argparse
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

def get_top_youtube_videos(api_key, max_results, region_code="US"):
    youtube = build(
        "youtube", "v3",
        developerKey=api_key
    )

    try:
        # 获取全平台热门视频,包含标题、统计数据、频道订阅数
        videos_response = youtube.videos().list(
            part="snippet,statistics,channelStatistics",
            chart="mostPopular",
            maxResults=max_results,
            regionCode=region_code
        ).execute()
    except HttpError as e:
        print(f"API请求错误: {e}")
        return []

    videos_data = []
    total_views = 0

    for item in videos_response["items"]:
        # 提取基础信息
        video_id = item["id"]
        title = item["snippet"]["title"]
        view_count = int(item["statistics"].get("viewCount", 0))
        like_count = int(item["statistics"].get("likeCount", 0))
        # 频道订阅数
        subscriber_count = int(item["channelStatistics"].get("subscriberCount", 0))

        total_views += view_count

        # 计算加权分(权重可自定义)
        weighted_score = (view_count * 0.5) + (like_count * 0.3) + (subscriber_count * 0.2)

        videos_data.append({
            "title": title,
            "videoId": video_id,
            "viewCount": view_count,
            "likeCount": like_count,
            "subscriberCount": subscriber_count,
            "weightedScore": weighted_score
        })

    # 按加权分降序排序
    videos_data.sort(key=lambda x: x["weightedScore"], reverse=True)

    return videos_data, total_views

def main():
    parser = argparse.ArgumentParser(description='抓取YouTube热门视频并分析')
    parser.add_argument("--api-key", required=True, help="YouTube Data API密钥")
    parser.add_argument("--max-results", type=int, default=25, help="返回结果数量")
    parser.add_argument("--region-code", default="US", help="地区代码,如CN、US")
    args = parser.parse_args()

    # 获取视频数据
    videos_data, total_views = get_top_youtube_videos(args.api_key, args.max_results, args.region_code)

    if not videos_data:
        print("未获取到视频数据")
        return

    # 写入CSV文件
    csv_path = 'top_youtube_videos.csv'
    try:
        if os.path.exists(csv_path):
            os.remove(csv_path)
    except OSError:
        pass

    with open(csv_path, 'w', encoding='utf-8', newline='') as csvfile:
        fieldnames = ['title', 'videoId', 'viewCount', 'likeCount', 'subscriberCount', 'weightedScore']
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

        writer.writeheader()
        for video in videos_data:
            print(f"标题: {video['title']}")
            print(f"观看数: {video['viewCount']:,}")
            print(f"点赞数: {video['likeCount']:,}")
            print(f"频道订阅数: {video['subscriberCount']:,}")
            print(f"加权分: {video['weightedScore']:.2f}")
            print(f"视频ID: {video['videoId']}\n")

            writer.writerow(video)

    # 写入总观看数到文件
    with open('total_views.txt', 'w') as f:
        f.write(f"总观看数: {total_views:,}")

    print(f"数据已写入 {csv_path} 和 total_views.txt")

if __name__ == "__main__":
    main()

关键说明

  • API调用:使用videos.list的chart=mostPopular直接获取热门视频,比search.list更匹配你的需求
  • 字段处理:用.get()方法处理可能缺失的统计字段,避免KeyError
  • 加权排序:权重比例可根据分析需求调整,比如若更看重订阅数,可提高其权重占比
  • 命令行参数:通过--api-key传入密钥,更安全灵活
  • 编码处理:写入CSV时指定encoding='utf-8',避免非ASCII字符乱码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 00:30:57