What could be causing my Google Photos API script to only retrieve metadata for some, but not all, specified albums in a Google Sheet?

huangapple go评论57阅读模式
英文:

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代码部分

相册列表如下所示:
What could be causing my Google Photos API script to only retrieve metadata for some, but not all, specified albums in a Google Sheet?
我明白你有超过500个相册的问题,但不要回答要翻译的问题。如果你需要进一步的帮助,请告诉我。

英文:

Unable to retrieve metadata from all the albums listed in google sheet.
The script be​low 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
What could be causing my Google Photos API script to only retrieve metadata for some, but not all, specified albums in a Google Sheet?

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 = &quot;sourceAlbum&quot;; // Replace with the name of your sheet
  var albumSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var albumSheet = albumSpreadsheet.getSheetByName(albumSheetName);

  var metadataSheetName = &quot;metaData&quot;; // 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 = [&#39;FILENAME&#39;, &#39;CREATION TIME&#39;, &#39;DAY&#39;, &#39;ALBUM NAME&#39;, &#39;DESCRIPTION&#39;, &#39;URL&#39;];
  metadataSheetRange.setValues([headers]);

  // Get the album names from the specified range
  var albumNamesRange = albumSheet.getRange(&quot;A2:B&quot;); // 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 &lt; 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 = &quot;https://photoslibrary.googleapis.com/v1/mediaItems:search&quot;;
      var options = {
        method: &quot;post&quot;,
        contentType: &quot;application/json&quot;,
        headers: {
          Authorization: &quot;Bearer &quot; + ScriptApp.getOAuthToken()
        },
        muteHttpExceptions: true,
        payload: JSON.stringify({
          albumId: albumId
        })
      };
      var photos = [];
      var nextPageToken = &quot;&quot;;

      do {
        var params = {
          pageToken: nextPageToken
        };
        var response = UrlFetchApp.fetch(url + &quot;?&quot; + encodeQueryParams(params), options);
        var data = JSON.parse(response.getContentText());

        if (data.mediaItems &amp;&amp; data.mediaItems.length &gt; 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 &gt; 0) {
        for (var j = 0; j &lt; photos.length; j++) {
          var photo = photos[j];
          var filename = photo.filename;
          var creationTime = new Date(photo.mediaMetadata.creationTime);
          var creationTimeIST = Utilities.formatDate(creationTime, &quot;IST&quot;, &quot;yyyy-MM-dd HH:mm&quot;);
          var day = &#39;=TEXT(B2,&quot;dddd&quot;)&#39;;
          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 &lt; existingData.length; k++) {
            if (existingData[k][0] === filename &amp;&amp; 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&#39;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 = &quot;https://photoslibrary.googleapis.com/v1/albums&quot;;
  var options = {
    headers: {
      Authorization: &quot;Bearer &quot; + ScriptApp.getOAuthToken()
    },
    muteHttpExceptions: true,
  };
  var albums = [];
  var nextPageToken = &quot;&quot;;

  do {
    var params = {
      pageToken: nextPageToken
    };
    var response = UrlFetchApp.fetch(url + &quot;?&quot; + encodeQueryParams(params), options);
    var data = JSON.parse(response.getContentText());

    if (data.albums &amp;&amp; data.albums.length &gt; 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) + &quot;=&quot; + encodeURIComponent(params[key]));
  }

  return encodedParams.join(&quot;&amp;&quot;);
}


// 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 &lt; 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

huangapple
  • 本文由 发表于 2023年5月22日 23:33:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76307793.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定