Isa*_*ero 4 google-sheets google-apps-script google-apis-explorer google-photos-api
我真的试图自己解决这个问题......
我正在尝试使用 Google Photos API 和 google apps 脚本将 google photos 中的照片元数据加载到工作表中。
在对上一个问题提供大量帮助后,我取得了一些进展
我现在有两个功能。
函数 photoAPI_ListPhotos() - 使用方法:mediaItems.list 并为我提供所有未存档的照片 函数 photoAPI_ListAlbums() - 使用方法:albums.list 并为我提供所有相册
我想要做的是检索特定相册中的所有照片。方法:mediaItems.search应该执行此操作,但它使用 POST 协议,而我发现之前的工作示例仅使用 GET。查看该页面上提供的示例,有一个 javascript 部分,但它在应用程序脚本中不起作用。
UrlFetchApp的文档告诉我如何格式化 POST 请求,但没有告诉我如何添加身份验证参数。
外部API也没有给我我正在寻找的示例。
我觉得我错过了一些重要的小信息,我希望我没有浪费大家的时间在这里询问。只是一个关于如何在应用程序脚本中使用 POST 和 oauth 的可靠示例应该可以帮助我到达我需要去的地方。
这是我的工作功能,用于列出所有未存档的照片。
function photoAPI_ListPhotos() {
/*
This function retrieves all photos from your personal google photos account and lists each one with the Filename, Caption, Create time (formatted for Sheet), Width, Height, and URL in a new sheet.
it will not include archived photos which can be confusing if you happen to have a large chunk of archived photos some pages may return only a next page token with no media items.
Requires Oauth scopes. Add the below line to appsscript.json
"oauthScopes": ["https://www.googleapis.com/auth/spreadsheets.currentonly", "https://www.googleapis.com/auth/photoslibrary", "https://www.googleapis.com/auth/photoslibrary.readonly", "https://www.googleapis.com/auth/script.external_request"]
Also requires a standard GCP project with the appropriate Photo APIs enabled.
https://developers.google.com/apps-script/guides/cloud-platform-projects
*/
//Get the spreadsheet object
var ss = SpreadsheetApp.getActiveSpreadsheet();
//Check for presence of target sheet, if it does not exist, create one.
var photos_sh = ss.getSheetByName("photos") || ss.insertSheet("photos", ss.getSheets().length);
//Make sure the target sheet is empty
photos_sh.clear();
var narray = [];
//Build the request string. Max page size is 100. set to max for speed.
var api = "https://photoslibrary.googleapis.com/v1/mediaItems?pageSize=100";
var headers = { "Authorization": "Bearer " + ScriptApp.getOAuthToken() };
var options = { "headers": headers, "method" : "GET", "muteHttpExceptions": true };
//This variable is used if you want to resume the scrape at some page other than the start. This is needed if you have more than 40,000 photos.
//Uncomment the line below and add the next page token for where you want to start in the quotes.
//var nexttoken="";
var param= "", nexttoken;
//Start counting how many pages have been processed.
var pagecount=0;
//Make the first row a title row
var data = [
"Filename",
"description",
"Create Time",
"Width",
"Height",
"ID",
"URL",
"NextPage"
];
narray.push(data);
//Loop through JSON results until a nextPageToken is not returned indicating end of data
do {
//If there is a nextpagetoken, add it to the end of the request string
if (nexttoken)
param = "&pageToken=" + nexttoken;
//Get data and load it into a JSON object
var response = UrlFetchApp.fetch(api + param, options);
var json = JSON.parse(response.getContentText());
//Check if there are mediaItems to process.
if (typeof json.mediaItems === 'undefined') {
//If there are no mediaItems, Add a blank line in the sheet with the returned nextpagetoken
//var data = ["","","","","","","",json.nextPageToken];
//narray.push(data);
} else {
//Loop through the JSON object adding desired data to the spreadsheet.
json.mediaItems.forEach(function (MediaItem) {
//Check if the mediaitem has a description (caption) and make that cell blank if it is not present.
if(typeof MediaItem.description === 'undefined') {
var description = "";
} else {
var description = MediaItem.description;
}
//Format the create date as appropriate for spreadsheets.
var d = new Date(MediaItem.mediaMetadata.creationTime);
var data = [
MediaItem.filename,
"'"+description, //The prepended apostrophe makes captions that are dates or numbers save in the sheet as a string.
d,
MediaItem.mediaMetadata.width,
MediaItem.mediaMetadata.height,
MediaItem.id,
MediaItem.productUrl,
json.nextPageToken
];
narray.push(data);
});
}
//Get the nextPageToken
nexttoken = json.nextPageToken;
pagecount++;
//Continue if the nextPageToaken is not null
//Also stop if you reach 400 pages processed, this prevents the script from timing out. You will need to resume manually using the nexttoken variable above.
} while (pagecount<4 && nexttoken);
//Continue if the nextPageToaken is not null (This is commented out as an alternative and can be used if you have a small enough collection it will not time out.)
//} while (nexttoken);
//Save all the data to the spreadsheet.
photos_sh.getRange(1, 1, narray.length, narray[0].length).setValues(narray);
}
Run Code Online (Sandbox Code Playgroud)
如果我的理解是正确的,那么这个示例脚本怎么样?请将此视为多个答案之一。
var albumId = "###"; // Please set the album ID.
var headers = {"Authorization": "Bearer " + ScriptApp.getOAuthToken()};
var url = "https://photoslibrary.googleapis.com/v1/mediaItems:search";
var mediaItems = [];
var pageToken = "";
do {
var params = {
method: "post",
headers: headers,
contentType: "application/json",
payload: JSON.stringify({albumId: albumId, pageSize: 100, pageToken: pageToken}),
}
var res = UrlFetchApp.fetch(url, params);
var obj = JSON.parse(res.getContentText());
Array.prototype.push.apply(mediaItems, obj.mediaItems);
pageToken = obj.nextPageToken || "";
} while (pageToken);
Logger.log(mediaItems)
Run Code Online (Sandbox Code Playgroud)
albumId、pageSize和pageToken包含在有效负载中,并且值作为 的内容类型发送application/json。当你的脚本修改后,下面修改后的脚本怎么样?
function photoAPI_ListPhotos() {
var albumId = "###"; // Please set the album ID.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var photos_sh = ss.getSheetByName("photos") || ss.insertSheet("photos", ss.getSheets().length);
photos_sh.clear();
var narray = [];
var api = "https://photoslibrary.googleapis.com/v1/mediaItems:search";
var headers = { "Authorization": "Bearer " + ScriptApp.getOAuthToken() };
var nexttoken = "";
var pagecount = 0;
var data = ["Filename","description","Create Time","Width","Height","ID","URL","NextPage"];
narray.push(data);
do {
var options = {
method: "post",
headers: headers,
contentType: "application/json",
payload: JSON.stringify({albumId: albumId, pageSize: 100, pageToken: nexttoken}),
}
var response = UrlFetchApp.fetch(api, options);
var json = JSON.parse(response.getContentText());
if (typeof json.mediaItems === 'undefined') {
//If there are no mediaItems, Add a blank line in the sheet with the returned nextpagetoken
//var data = ["","","","","","","",json.nextPageToken];
//narray.push(data);
} else {
json.mediaItems.forEach(function (MediaItem) {
if(typeof MediaItem.description === 'undefined') {
var description = "";
} else {
var description = MediaItem.description;
}
var d = new Date(MediaItem.mediaMetadata.creationTime);
var data = [
MediaItem.filename,
"'"+description,
d,
MediaItem.mediaMetadata.width,
MediaItem.mediaMetadata.height,
MediaItem.id,
MediaItem.productUrl,
json.nextPageToken
];
narray.push(data);
});
}
nexttoken = json.nextPageToken || "";
pagecount++;
} while (pagecount<4 && nexttoken);
photos_sh.getRange(1, 1, narray.length, narray[0].length).setValues(narray);
}
Run Code Online (Sandbox Code Playgroud)
https://www.googleapis.com/auth/photoslibrary.readonly或https://www.googleapis.com/auth/photoslibrary包含在范围内。如果我误解了你的问题并且这不是你想要的结果,我深表歉意。
| 归档时间: |
|
| 查看次数: |
3100 次 |
| 最近记录: |