英文:
What could be causing my Google Photos API script to only retrieve metadata for some, but not all, specified albums in a Google Sheet?
问题
I understand your request. Here's the translated part of your content:
无法从Google表格中列出的所有相册中检索元数据。
以下是要检索指定的Google照片相册中指定元数据的脚本,但它仅检索了列表中的一些相册的元数据。
// JavaScript代码部分
相册列表如下所示:
我明白你有超过500个相册的问题,但不要回答要翻译的问题。如果你需要进一步的帮助,请告诉我。
英文:
Unable to retrieve metadata from all the albums listed in google sheet.
The script below is supposed to retrieve the specified metadata from the list of specified google photos album present in a google sheet, but it is not retrieving metadata for all the specified list of albums but only for few albums from the list.
function fetchPhotosData() {
var albumSheetName = "albums to get"; // Replace with the name of your sheet
var albumSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var albumSheet = albumSpreadsheet.getSheetByName(albumSheetName);
var metadataSheetName = "METADATA"; // Replace with the name of your sheet
var metadataSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var metadataSheet = metadataSpreadsheet.getSheetByName(metadataSheetName);
// Define the target range for the metadata sheet headers
var metadataSheetRange = metadataSheet.getRange(1, 1, 1, 6); // Assuming you want to start from A1
// Set the headers for the metadata sheet
var headers = ['FILENAME', 'CREATION TIME', 'DAY', 'ALBUM NAME', 'DESCRIPTION', 'URL'];
metadataSheetRange.setValues([headers]);
// Get the album names from the specified range
var albumNamesRange = albumSheet.getRange("B2:B"); // Replace with the range containing album names
var albumNamesValues = albumNamesRange.getValues();
var albumNames = albumNamesValues.map(function(row) {
return row[0];
});
// Retrieve albums based on the names from the Google Photos API
var albums = getAlbums();
// Iterate through all albums
for (var i = 0; i < albums.length; i++) {
var album = albums[i];
var albumId = album.id;
var albumName = album.title;
// Check if the album name is present in the specified range
if (albumNames.indexOf(albumName) !== -1) {
// Make an API request to retrieve the photos data for the album
var url = "https://photoslibrary.googleapis.com/v1/mediaItems:search";
var options = {
method: "post",
contentType: "application/json",
headers: {
Authorization: "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true,
payload: JSON.stringify({
albumId: albumId
})
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
// Extract and write the relevant photo data to the metadata sheet
if (data && data.mediaItems && data.mediaItems.length > 0) {
for (var j = 0; j < data.mediaItems.length; j++) {
var photo = data.mediaItems[j];
var filename = photo.filename;
var creationTime = new Date(photo.mediaMetadata.creationTime);
var creationTimeIST = Utilities.formatDate(creationTime, "IST", "yyyy-MM-dd HH:mm");
var day = '=TEXT(B2,"dddd")';
var url = photo.productUrl;
var description = photo.description;
// Check if the photo already exists in the metadata sheet
var existingData = metadataSheet.getDataRange().getValues();
var existingRowIndex = -1;
for (var k = 1;k < existingData.length; k++) {
if (existingData[k][0] === filename && existingData[k][3] === albumName) {
existingRowIndex = k;
break;
}
}
// If photo exists, update the description
if (existingRowIndex !== -1) {
metadataSheet.getRange(existingRowIndex + 1, 5).setValue(description);
} else {
// Photo doesn't exist, append a new row
var rowData = [filename, creationTimeIST, day, albumName, description, url];
metadataSheet.appendRow(rowData);
}
}
}
}
}
}
// Helper function to retrieve all albums
function getAlbums() {
var url = "https://photoslibrary.googleapis.com/v1/albums";
var options = {
headers: {
Authorization: "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true,
};
var response = UrlFetchApp.fetch(url, options);
var data = JSON.parse(response.getContentText());
return data.albums || [];
}
// Helper function to get album names from a specific sheet
function getAlbumNames(sheet) {
var albumNames = [];
var data = sheet.getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
var albumName = data[i][0];
albumNames.push(albumName);
}
return albumNames;
}
The list of albums look like this
Tried chat gpt, but no solution. I have more than 500 albums.
答案1
得分: 1
问题:
我进一步调查了您现有的代码,并发现有限数量的相册的原因来自您的“API请求”。
方法:albums.list
此方法列出了在Google相册应用的“相册”选项卡中向用户显示的所有相册之一的查询参数是“pageSize”,其中提到:
> 要在响应中返回的最大相册数。可能返回的相册少于指定的数量。默认pageSize为20,最大为50。
如果相册数量大于50,响应将包括一个nextPageToken
> 仅输出。令牌以用于获取下一组相册。如果此请求要检索更多相册,则会填充。
然后,您可以使用pageToken查询参数重新运行请求,以捕获您的照片应用程序中的所有相册。
修改后的脚本:
我已更新了您的代码中的API请求,该代码循环获取所有相册,直到没有更多页面为止。
我还在您的mediaItems.search方法中实现了相同的情景,用于包含100个以上媒体项的相册。
function fetchPhotosData() {
var albumSheetName = "sourceAlbum"; // Replace with the name of your sheet
var albumSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var albumSheet = albumSpreadsheet.getSheetByName(albumSheetName);
var metadataSheetName = "metaData"; // Replace with the name of your sheet
var metadataSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var metadataSheet = metadataSpreadsheet.getSheetByName(metadataSheetName);
// Define the target range for the metadata sheet headers
var metadataSheetRange = metadataSheet.getRange(1, 1, 1, 6); // Assuming you want to start from A1
// Set the headers for the metadata sheet
var headers = ['FILENAME', 'CREATION TIME', 'DAY', 'ALBUM NAME', 'DESCRIPTION', 'URL'];
metadataSheetRange.setValues([headers]);
// Get the album names from the specified range
var albumNamesRange = albumSheet.getRange("A2:B"); // Replace with the range containing album names
var albumNamesValues = albumNamesRange.getValues();
var albumNames = albumNamesValues.map(function (row) {
return row[0];
});
// Retrieve albums based on the names from the Google Photos API
var albums = getAlbums();
// Iterate through all albums
for (var i = 0; i < albums.length; i++) {
var album = albums[i];
var albumId = album.id;
var albumName = album.title;
// Check if the album name is present in the specified range
if (albumNames.indexOf(albumName) !== -1) {
// Make an API request to retrieve the photos data for the album
var url = "https://photoslibrary.googleapis.com/v1/mediaItems:search";
var options = {
method: "post",
contentType: "application/json",
headers: {
Authorization: "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true,
payload: JSON.stringify({
albumId: albumId
})
};
var photos = [];
var nextPageToken = "";
do {
var params = {
pageToken: nextPageToken
};
var response = UrlFetchApp.fetch(url + "?" + encodeQueryParams(params), options);
var data = JSON.parse(response.getContentText());
if (data.mediaItems && data.mediaItems.length > 0) {
photos = photos.concat(data.mediaItems);
}
nextPageToken = data.nextPageToken;
} while (nextPageToken);
// Extract and write the relevant photo data to the metadata sheet
if (photos.length > 0) {
for (var j = 0; j < photos.length; j++) {
var photo = photos[j];
var filename = photo.filename;
var creationTime = new Date(photo.mediaMetadata.creationTime);
var creationTimeIST = Utilities.formatDate(creationTime, "IST", "yyyy-MM-dd HH:mm");
var day = '=TEXT(B2,"dddd")';
var url = photo.productUrl;
var description = photo.description;
// Check if the photo already exists in the metadata sheet
var existingData = metadataSheet.getDataRange().getValues();
var existingRowIndex = -1;
for (var k = 1; k < existingData.length; k++) {
if (existingData[k][0] === filename && existingData[k][3] === albumName) {
existingRowIndex = k;
break;
}
}
// If photo exists, update the description
if (existingRowIndex !== -1) {
metadataSheet.getRange(existingRowIndex + 1, 5).setValue(description);
} else {
// Photo doesn't exist, append a new row
var rowData = [filename, creationTimeIST, day, albumName, description, url];
metadataSheet.appendRow(rowData);
}
}
}
}
}
}
// Helper function to retrieve all albums
function getAlbums() {
var url = "https://photoslibrary.googleapis.com/v1/albums";
var options = {
headers: {
Authorization: "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true,
};
var albums = [];
var nextPageToken = "";
do {
var params = {
pageToken: nextPageToken
};
var response = UrlFetchApp.fetch(url + "?" + encodeQueryParams(params), options);
var data = JSON.parse(response.getContentText());
if (data.albums && data.albums.length > 0) {
albums = albums.concat(data.albums);
}
nextPageToken = data.nextPageToken;
} while (nextPageToken);
return albums;
}
function encodeQueryParams(params) {
var encodedParams = [];
for (var key in params) {
encodedParams.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key]));
}
return encodedParams.join("&");
}
// Helper function to get album names from a specific sheet
function getAlbumNames(sheet) {
var albumNames = [];
var data = sheet.getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
var albumName = data[i][0];
albumNames.push(albumName);
}
return albumNames;
}
参考:
https://developers.google.com/photos/library/reference/rest/v1/mediaItems/search
https://developers.google.com/photos/library/reference/rest/v1/albums/list
英文:
Issue:
I further investigated your existing code and found out that the reason for the limited number of albums is from your API requests
.
Method: albums.list
This method lists all albums shown to a user in the Albums tab of the Google Photos app. One of the query parameters of this method is pageSize
that states:
> Maximum number of albums to return in the response. Fewer albums might
> be returned than the specified number. The default pageSize is 20, the
> maximum is 50.
If the number of albums is greater than 50, the response will include a nextPageToken
> Output only. Token to use to get the next set of albums. Populated if
> there are more albums to retrieve for this request.
You can then rerun the request with pageToken query parameter to capture all albums in your photo app.
> A continuation token to get the next page of the results. Adding this
> to the request returns the rows after the pageToken. The pageToken
> should be the value returned in the nextPageToken parameter in the
> response to the listAlbums request.
Modified Script:
I have updated the API requests in your code that loops to fetch all the albums by making subsequent requests until there are no more pages left.
I also implemented this same scenario in your mediaItems.search method for media items greater than 100 in an album.
function fetchPhotosData() {
var albumSheetName = "sourceAlbum"; // Replace with the name of your sheet
var albumSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var albumSheet = albumSpreadsheet.getSheetByName(albumSheetName);
var metadataSheetName = "metaData"; // Replace with the name of your sheet
var metadataSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var metadataSheet = metadataSpreadsheet.getSheetByName(metadataSheetName);
// Define the target range for the metadata sheet headers
var metadataSheetRange = metadataSheet.getRange(1, 1, 1, 6); // Assuming you want to start from A1
// Set the headers for the metadata sheet
var headers = ['FILENAME', 'CREATION TIME', 'DAY', 'ALBUM NAME', 'DESCRIPTION', 'URL'];
metadataSheetRange.setValues([headers]);
// Get the album names from the specified range
var albumNamesRange = albumSheet.getRange("A2:B"); // Replace with the range containing album names
var albumNamesValues = albumNamesRange.getValues();
var albumNames = albumNamesValues.map(function (row) {
return row[0];
});
// Retrieve albums based on the names from the Google Photos API
var albums = getAlbums();
// Iterate through all albums
for (var i = 0; i < albums.length; i++) {
var album = albums[i];
var albumId = album.id;
var albumName = album.title;
// Check if the album name is present in the specified range
if (albumNames.indexOf(albumName) !== -1) {
// Make an API request to retrieve the photos data for the album
var url = "https://photoslibrary.googleapis.com/v1/mediaItems:search";
var options = {
method: "post",
contentType: "application/json",
headers: {
Authorization: "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true,
payload: JSON.stringify({
albumId: albumId
})
};
var photos = [];
var nextPageToken = "";
do {
var params = {
pageToken: nextPageToken
};
var response = UrlFetchApp.fetch(url + "?" + encodeQueryParams(params), options);
var data = JSON.parse(response.getContentText());
if (data.mediaItems && data.mediaItems.length > 0) {
photos = photos.concat(data.mediaItems);
}
nextPageToken = data.nextPageToken;
} while (nextPageToken);
// Extract and write the relevant photo data to the metadata sheet
if (photos.length > 0) {
for (var j = 0; j < photos.length; j++) {
var photo = photos[j];
var filename = photo.filename;
var creationTime = new Date(photo.mediaMetadata.creationTime);
var creationTimeIST = Utilities.formatDate(creationTime, "IST", "yyyy-MM-dd HH:mm");
var day = '=TEXT(B2,"dddd")';
var url = photo.productUrl;
var description = photo.description;
// Check if the photo already exists in the metadata sheet
var existingData = metadataSheet.getDataRange().getValues();
var existingRowIndex = -1;
for (var k = 1; k < existingData.length; k++) {
if (existingData[k][0] === filename && existingData[k][3] === albumName) {
existingRowIndex = k;
break;
}
}
// If photo exists, update the description
if (existingRowIndex !== -1) {
metadataSheet.getRange(existingRowIndex + 1, 5).setValue(description);
} else {
// Photo doesn't exist, append a new row
var rowData = [filename, creationTimeIST, day, albumName, description, url];
metadataSheet.appendRow(rowData);
}
}
}
}
}
}
// Helper function to retrieve all albums
function getAlbums() {
var url = "https://photoslibrary.googleapis.com/v1/albums";
var options = {
headers: {
Authorization: "Bearer " + ScriptApp.getOAuthToken()
},
muteHttpExceptions: true,
};
var albums = [];
var nextPageToken = "";
do {
var params = {
pageToken: nextPageToken
};
var response = UrlFetchApp.fetch(url + "?" + encodeQueryParams(params), options);
var data = JSON.parse(response.getContentText());
if (data.albums && data.albums.length > 0) {
albums = albums.concat(data.albums);
}
nextPageToken = data.nextPageToken;
} while (nextPageToken);
return albums;
}
function encodeQueryParams(params) {
var encodedParams = [];
for (var key in params) {
encodedParams.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key]));
}
return encodedParams.join("&");
}
// Helper function to get album names from a specific sheet
function getAlbumNames(sheet) {
var albumNames = [];
var data = sheet.getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
var albumName = data[i][0];
albumNames.push(albumName);
}
return albumNames;
}
Reference:
https://developers.google.com/photos/library/reference/rest/v1/mediaItems/search
https://developers.google.com/photos/library/reference/rest/v1/albums/list
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论