Reputation: 25
I am trying to collect YouTube metadata. However, I am unable to paginate. I only get 50 records but I would like to get as many instances as possible.
How do I get more results?
This my code so far.
function YoutubeScraper2() {
var search = YouTube.Search.list("snippet, id", {
q: "pizza",
maxResults: 50
});
var last_row = 0;
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet()
var activeSheet = spreadSheet.getActiveSheet();
for (var i = 0; i < search.items.length; i++){
var results = search.items.map((item) => [item.id.channelId, item.id.videoId, item.snippet.title, item.snippet.publishedAt, item.snippet.thumbnails.default.url]);
// Retrieve channel IDs and video IDs.
var {channelIds, videoIds} = results.reduce((o, [channelId, videoId]) => {
o.channelIds.push(channelId);
o.videoIds.push(videoId);
return o;
}, {channelIds: [], videoIds: []});
// Retrieve YouTube.Videos.list.
var videoList = YouTube.Videos.list("statistics", {id: videoIds.join(",")});
var videoStats = videoList.items.map((item) => [item.id, item.statistics.viewCount, item.statistics.likeCount, item.statistics.dislikeCount]).reduce((o, [id, ...v]) => Object.assign(o, {[id]: v}), {});
// Retrieve YouTube.Channels.list
var channelList = YouTube.Channels.list("statistics", { id: channelIds.join(",") });
var channelStats = channelList.items.map((item) => [item.id, item.statistics.viewCount, item.statistics.subscriberCount]).reduce((o, [id, ...v]) => Object.assign(o, {[id]: v}), {});
// Create an array for putting values and put the values to Spreadsheet.
results = results.map(e => channelStats[e[0]] ? e.concat(channelStats[e[0]]) : e.concat(Array(2).fill("")));
results = results.map(e => videoStats[e[1]] ? e.concat(videoStats[e[1]]) : e.concat(Array(3).fill("")));
last_row = activeSheet.getLastRow() + 1;
activeSheet.getRange(1, 1, results.length, results[0].length).setValues(results);
last_row++;
}
}
Upvotes: 1
Views: 518
Reputation: 201378
I believe your goal as follows.
pageToken
.YouTube.Videos.list
and YouTube.Channels.list
, 50 ids can be used for one API call. So it is required to request several times for these methods.When above points are reflected to your script, it becomes as follows.
function YoutubeScraper2() {
var spreadSheet = SpreadsheetApp.getActiveSpreadsheet()
var activeSheet = spreadSheet.getActiveSheet();
var numberOfData = 200; // When 0 is set, all values are retrieved.
// Retrieve YouTube.Search.list.
var data = [];
var pageToken = "";
do {
var search = YouTube.Search.list("snippet", { q: "pizza", maxResults: 50, pageToken: pageToken });
data = data.concat(search.items);
pageToken = search.nextPageToken;
if (numberOfData != 0 && data.length > numberOfData) break;
} while (pageToken);
if (numberOfData != 0) data = data.splice(0, numberOfData);
var results = data.map((item) => [item.snippet.channelId, item.id.videoId, item.snippet.title, item.snippet.publishedAt, item.snippet.thumbnails.default.url]);
// Retrieve channel IDs and video IDs.
var { channelIds, videoIds } = results.reduce((o, [channelId, videoId]) => {
o.channelIds.push(channelId);
o.videoIds.push(videoId);
return o;
}, { channelIds: [], videoIds: [] });
// Retrieve YouTube.Videos.list.
var videoList = [];
while (videoIds.length > 0) {
var temp = YouTube.Videos.list("statistics", { id: videoIds.splice(0, 50).join(",") });
videoList = videoList.concat(temp.items);
}
var videoStats = videoList.map((item) => [item.id, item.statistics.viewCount, item.statistics.likeCount, item.statistics.dislikeCount]).reduce((o, [id, ...v]) => Object.assign(o, { [id]: v }), {});
// Retrieve YouTube.Channels.list
var channelList = [];
while (channelIds.length > 0) {
var temp = YouTube.Channels.list("statistics", { id: channelIds.splice(0, 50).join(",") });
channelList = channelList.concat(temp.items);
}
var channelStats = channelList.map((item) => [item.id, item.statistics.viewCount, item.statistics.subscriberCount]).reduce((o, [id, ...v]) => Object.assign(o, { [id]: v }), {});
// Create an array for putting values and put the values to Spreadsheet.
results = results.map(e => channelStats[e[0]] ? e.concat(channelStats[e[0]]) : e.concat(Array(2).fill("")));
results = results.map(e => videoStats[e[1]] ? e.concat(videoStats[e[1]]) : e.concat(Array(3).fill("")));
var header = ["channelId", "videoId", "title", "publishedAt", "thumbnails", "viewCount", "subscriberCount", "viewCount", "likeCount", "dislikeCount"];
results.unshift(header);
activeSheet.getRange(1, 1, results.length, results[0].length).setValues(results);
}
var numberOfData = 200;
, you can retrieve the values of number you want to retrive. When var numberOfData = 0;
is used, all values which can retrieve using YouTube.Search.list
are retrieved.var numberOfData = 0;
is used for above script, 707 values were obtained.Upvotes: 3