如何通过YouTube Data API v3提取频道内超2万条视频的元数据
YouTube Data API v3 提取频道超2万条视频元数据方案
限制原因说明
YouTube Data API v3 对playlistItems接口有内置硬限制:任何公开播放列表(包含频道默认的「上传视频」系统播放列表)单次分页拉取最多仅能返回2万条结果,该限制无法通过修改请求参数或申请更高权限突破,因此直接调整原接口配置拉取全量数据的思路不可行,只能采用按上传时间段拆分拉取的方案。
可行实现方案
使用search.list接口替代原playlistItems接口,指定查询范围为目标频道、资源类型为视频,再按上传时间拆分多个时间区间,逐个区间拉取数据后合并结果即可覆盖全量视频。
- 时间区间拆分规则:可以从频道创立时间开始,按3个月/6个月为周期拆分,如果某个区间返回结果仍达到2万条上限,再把该区间拆分为更小的时间颗粒度(比如1个月)重新拉取即可。
- 配额消耗说明:
search.list接口每次请求消耗100单位配额,远高于playlistItems的1单位,建议根据自己的配额额度合理调整时间区间大小,减少不必要的请求。
改进后代码示例
from googleapiclient.discovery import build from datetime import datetime, timedelta YOUTUBE_API_KEY = "你的API密钥" CHANNEL_ID = "目标频道ID" # 时间区间步长,可根据频道发片密度调整,发片越多步长越短 TIME_STEP = timedelta(days=180) # 此处设为6个月 youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY) # 先获取频道创立时间作为拉取起始点 channel_info = youtube.channels().list( id=CHANNEL_ID, part='snippet' ).execute() channel_created_at = datetime.fromisoformat(channel_info['items'][0]['snippet']['publishedAt'].replace('Z', '+00:00')) current_start = channel_created_at current_end = current_start + TIME_STEP all_videos = [] while current_start < datetime.now(current_start.tzinfo): next_page_token = None while True: res = youtube.search().list( channelId=CHANNEL_ID, part='snippet', type='video', publishedAfter=current_start.isoformat().replace('+00:00', 'Z'), publishedBefore=current_end.isoformat().replace('+00:00', 'Z'), maxResults=50, pageToken=next_page_token ).execute() # 提取需要的元数据 for item in res['items']: video_info = { 'video_id': item['id']['videoId'], 'title': item['snippet']['title'], 'published_at': item['snippet']['publishedAt'] } all_videos.append(video_info) next_page_token = res.get('nextPageToken') if not next_page_token: break # 移动时间窗口 current_start = current_end current_end = current_start + TIME_STEP # 去重(避免跨区间边界的视频被重复拉取) unique_videos = list({v['video_id']:v for v in all_videos}.values()) print(f"共拉取到{len(unique_videos)}条视频元数据")
注意事项
- 拉取到的结果需要做去重处理,避免时间区间边界的视频被多次计入
- 如果频道累计视频量极大,可以进一步缩短TIME_STEP的时长,确保单个时间区间内的视频数量不超过2万条
- 若仅需要视频标题和发布时间,直接从
search.list返回的snippet字段即可提取,不需要再额外调用其他接口,可节省配额
内容的提问来源于stack exchange,提问作者pmohanty
相关产品推荐
相关产品推荐

