我正在研究一个小型项目,该项目必须在YouTube频道上查询每个视频,并返回该视频的视频标题和总视图。我已经找到了一种处理此问题的方法,但是对于1500多个视频(约300个配额点(的频道来说,配额成本相当陡峭,所以我很好奇是否有一种更有效的方法来查询此类信息。
我目前必须采取的步骤是三倍:
- 查询当前用户,并使用
channels
查找其上传播放列表ID - 使用播放列表ID查询使用
playlistItems
中的播放列表中的视频(此步骤返回视频信息,例如标题和videoid(
(
- 从第2步中解析视频ID,并查询使用
videos
返回每个视频的统计信息的视频列表
{
videoId: 'abc1-345dgh'
title: 'Video Title',
thumbnail: {
img: 'image information'
},
views: 12345567
}
是否有更好的方法可以返回带有视频信息并查看统计信息的视频列表?
这是我必须采取的步骤:
const channel = await youtubeAPI.channels.list({
part: 'contentDetails',
mine: true
});
const playlistId = channel.data.items[0].contentDetails.relatedPlaylists.uploads;
const videos = await getPlaylistVideos(playlistId);
用户的playlistId
上传播放列表发送到getPlaylistVideos()
,该列表在playlistItems
查询的每个页面上都迭代。
var videos = [];
var videoStats = [];
async function getPlaylistVideos(playlistId, pageToken = null) {
const res = await youtubeAPI.playlistItems.list({
part: 'snippet',
playlistId: playlistId,
maxResults: 50,
pageToken: pageToken
});
const mappedVideos = res.data.items.map((item) => {
return {
title: item.snippet.title,
thumbnail: item.snippet.thumbnails.maxres,
videoId: item.snippet.resourceId.videoId
}
})
videos.push(...mappedVideos);
// if there's another page to get results from
if ('nextPageToken' in res.data) {
return await getPlaylistVideos(playlistId, res.data.nextPageToken)
} else {
// we've queried for everything, return the videos
return videos;
}
}
接下来,我滤除了从videos
数组返回的视频ID
const videoIds = videos.map((video) => {
return video.videoId
});
videoIdArray.push(...videoIds);
const videoStats = await getVideoStats(videoIdArray);
这些ID被发送到getVideoStats()
,我通过所有视频ID进行迭代,并返回每个视频的统计信息
var minId = 0;
var maxId = 50;
async function getVideoStats(videoIds) {
// since we can only return 50 videos per query, I have to slice the
// videoId array into segments
const videoIdLength = videoIds.length;
const subsetIds = videoIds.slice(minId, maxId);
const res = await youtubeAPI.videos.list({
part: 'statistics',
id: subsetIds.join(","),
maxResults: 50
});
const mappedVideoStats = res.data.items.map((item) => {
return {
videoId: item.id,
views: item.statistics.viewCount
}
});
videoStats.push(...mappedVideoStats);
const diff = videoIdLength - (maxId + 1);
if (diff > 0) {
// if there are more videos to query, update the variables used
// in slice() to take 50 more videos
minId += 50;
maxId += 50;
return await getVideoStats(videoIds);
} else {
return videoStats;
}
}
最后,我通过在每个对象中寻找匹配的 videoId
属性来将视频信息与视频统计信息合并:
let mergedArray = [];
videos.forEach((video, index) => {
mergedArray.push(Object.assign({}, video, videoStats[index]))
})
mergedArray
最终存储我需要的信息。
这是我需要的信息,我只是觉得我不得不跳过篮球才能到达它。是否有更有效的方法来完成相同的任务?谢谢!
- 您可以通过更改用于从给定频道检索"上传"播放列表的代码来保存一些配额。检查我有关您在
channel_id
中必须做出的更改以获取uploads
播放列表的答案。 - 我的第二个选项是使用Google自定义搜索API(我在其他答案中描述的( - 因为在YouTube数据中,API dwill始终消耗相同的配额 - 无论您是多少参数/术语在每个请求中使用。
这些只是我的两分钱,但值得一试。