2014-04-25 00:36

利用 Google Script 將 Blogger 備份到 Google Drive

在 Google Drive 中建立『指令碼』



然後選擇『空白專案』



貼上以下程式碼
  1. /* 
  2. Ref: 
  3. https://developers.google.com/apps-script/reference/drive/drive-app 
  4. https://developers.google.com/apps-script/reference/drive/file 
  5. https://developers.google.com/apps-script/reference/drive/folder 
  6. https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app 
  7. https://developers.google.com/apps-script/reference/url-fetch/o-auth-config 
  8. https://developers.google.com/apps-script/reference/base/blob 
  9. https://developers.google.com/apps-script/reference/utilities/utilities 
  10.  
  11. */ 
  12.  
  13. var _backupKeepAmount = 10; 
  14. var _backupFolderName = 'blogger_backup'; 
  15. var _backupFolder; 
  16.  
  17.  
  18.  
  19. function main(){ 
  20.  var folders = DriveApp.getFoldersByName(_backupFolderName); 
  21.  
  22.  if(folders.hasNext()){ 
  23.    _backupFolder = folders.next(); 
  24.  }else{ 
  25.    _backupFolder = DriveApp.createFolder(_backupFolderName); 
  26.  } 
  27.  
  28.  
  29.  setAuth(); 
  30.  
  31.  backupBlogger('{my_blog_1}', '{blog_id}', false); 
  32.  backupBlogger('{my_blog_2}', '{blog_id}', false); 
  33.  
  34.  MailApp.sendEmail(Session.getActiveUser().getEmail(), 'Backup Blogger To Google Drive', Logger.getLog()); 
  35. } 
  36.  
  37.  
  38. /** 
  39. * @param {String} prefixName 備份檔名的前綴 
  40. * @param {String} blogId 
  41. * @param {Boolean} isBigSize 如果備份的檔案超過 10M,請設為 true 
  42. */ 
  43. function backupBlogger(prefixName, blogId, isBigSize){ 
  44.  logMsg('Backup Start', prefixName); 
  45.  
  46.  
  47.  /* 取得之前的備份清單 */ 
  48.  var files = _backupFolder.getFilesByType('application/xml'); 
  49.  var beforeFiles = []; 
  50.  while (files.hasNext()) { 
  51.    var file = files.next(); 
  52.    if(file.getName().indexOf(prefixName) == -1){ continue; } 
  53.  
  54.    beforeFiles.push(file); 
  55.  } 
  56.  
  57.  beforeFiles.sort(function (a, b) { 
  58.    return b.getName().localeCompare(a.getName()); 
  59.  }); 
  60.  
  61.  
  62.  /* 下載並儲存檔案 */ 
  63.  var isChange; 
  64.  if(isBigSize){ 
  65.    isChange = downloadAndSaveBigSizeArchiveXml(prefixName, blogId, beforeFiles[0]); 
  66.  }else{ 
  67.    isChange = downloadAndSaveArchiveXml(prefixName, blogId, beforeFiles[0]); 
  68.  } 
  69.  
  70.  /*沒有異動結束處理*/ 
  71.  if(!isChange){ return; } 
  72.  
  73.  
  74.  /* 刪除舊檔案 */ 
  75.  var oleFiles = beforeFiles.slice(_backupKeepAmount); 
  76.  for(var i=0; i < oleFiles.length; i++){ 
  77.    oleFiles[i].setTrashed(true); 
  78.  } 
  79.  
  80.  
  81.  logMsg('Backup Complete', prefixName); 
  82. } 
  83.  
  84.  
  85.  
  86.  
  87. function logMsg(status, msg){ 
  88.  Logger.log('%s | %s', status, msg); 
  89. } 
  90.  
  91.  
  92.  
  93. function setAuth(){ 
  94.  var scope = "https://www.blogger.com/feeds/"; 
  95.  var oAuthConfig = UrlFetchApp.addOAuthService("blogger"); 
  96.  oAuthConfig.setRequestTokenUrl("https://www.google.com/accounts/OAuthGetRequestToken?scope="+scope); 
  97.  oAuthConfig.setAuthorizationUrl("https://www.google.com/accounts/OAuthAuthorizeToken"); 
  98.  oAuthConfig.setAccessTokenUrl("https://www.google.com/accounts/OAuthGetAccessToken"); 
  99.  
  100. //  oAuthConfig.setConsumerKey("anonymous"); 
  101. //  oAuthConfig.setConsumerSecret("anonymous"); 
  102. } 
  103.  
  104.  
  105.  
  106. function getArchiveXmlResponse(blogId){ 
  107.  var options = { 
  108.      "oAuthServiceName" : "blogger", 
  109.      "oAuthUseToken" : "always" 
  110.  }; 
  111.  
  112.  var url = 'https://www.blogger.com/feeds/' + blogId + '/archive'; 
  113.  var response = UrlFetchApp.fetch(url, options); 
  114.  
  115.  /*下載失敗,錯誤記錄*/ 
  116.  if(response.getResponseCode() != 200){ 
  117.    logMsg('Download Failed', response.getAllHeaders().toSource()); 
  118.    return null; 
  119.  } 
  120.  
  121.  return response; 
  122. } 
  123.  
  124.  
  125. function downloadAndSaveArchiveXml(prefixName, blogId, beforeFile){ 
  126.  var response = getArchiveXmlResponse(blogId); 
  127.  if(!response){ return false; } 
  128.  
  129.  var downloadContent = response.getContentText(); 
  130.  
  131.  /* 檢查檔案異動 */ 
  132.  if(beforeFile){ 
  133.    var content = beforeFile.getBlob().getDataAsString(); 
  134.  
  135.    if(beforeFile && Math.abs(content.length -downloadContent.length) < 100){ 
  136.      logMsg('Not Change', prefixName); 
  137.      return false; 
  138.    } 
  139.  } 
  140.  
  141.  /* 儲存下載 */ 
  142.  var fileName = Utilities.formatDate(new Date(), "+8", "yyyyMMdd_HHmmss'.xml'"); 
  143.  _backupFolder.createFile(prefixName + '_' + fileName, downloadContent, 'application/xml'); 
  144.  
  145.  return true; 
  146. } 
  147.  
  148.  
  149.  
  150. function downloadAndSaveBigSizeArchiveXml(prefixName, blogId, beforeFile){ 
  151.  var response = getArchiveXmlResponse(blogId); 
  152.  if(!response){ return false; } 
  153.  
  154.  
  155.  /* 儲存下載 */ 
  156.  var fileName = Utilities.formatDate(new Date(), "+8", "yyyyMMdd_HHmmss'.xml'"); 
  157.  var downloadBlob = response.getBlob(); 
  158.  downloadBlob.setName(prefixName + '_' + fileName); 
  159.  downloadBlob.setContentType('application/xml'); 
  160.  var downloadFile = _backupFolder.createFile(downloadBlob); 
  161.  
  162.  
  163.  /* 檢查檔案異動 */ 
  164.  if(beforeFile && Math.abs(beforeFile.getSize() - downloadFile.getSize() ) < 1000){ 
  165.    downloadFile.setTrashed(true); 
  166.    logMsg('Not Change', prefixName); 
  167.    return false; 
  168.  } 
  169.  
  170.  return true; 
  171. } 


修改 {my_blog_1} 及 {blog_id},{my_blog_1} 是備份檔名的前綴,{blog_id} 則可以在文章管理的網址上找到



儲存檔案,並取名為『Backup Blogger To Google Drive』




先來測試一下備份是否能正常執行,請選擇執行的函數為『main』,並按下『執行』,然後先為此程式授權





如果都沒問題,接著來設定排程,選擇『啟動程序』



新增一個觸發程序



選擇執行的函數『main』,然後時間定在晚上 11 點,接著選擇『通知』



這個設定主要是發生錯誤的時候可以寄送通知