Re: [心得] 上傳照片或影片到 Google Photo

看板Python作者 (funky)時間4年前 (2020/08/29 14:05), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串2/3 (看更多)
# -*- coding: utf-8 -*- import pickle import os import re import logging from datetime import datetime, timedelta from googleapiclient.discovery import build from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request import requests import fnmatch from xml.dom.minidom import Document import xml.etree.ElementTree as ET # os.environ["PYTHONIOENCODING"] = "utf-8" # If modifying these scopes, delete the file token.pickle. SCOPES = ['https://www.googleapis.com/auth/photoslibrary'] mytime = datetime.now() + timedelta(hours=8) # 上傳的時間設定 basepath = os.path.dirname(__file__) # 本檔的路徑 filelog = os.path.join(basepath, 'Upload.log') # 上傳的紀錄檔 mypath = r'\\xxxxxx' # 要上傳的路徑, 會以第一層的目錄當相簿 mycreds = None # 開啟紀錄 LogTemp.log def EnableLogging(): logging.basicConfig(level=logging.INFO, format='%(asctime)s %(name)-1s %(levelname)-1s %(message)s', datefmt='%m-%d %H:%M', handlers=[logging.FileHandler(filelog), ]) def Get_Token(): creds = None # The file token.pickle stores the user's access and refresh tokens, and is # created automatically when the authorization flow completes for the first # time. if os.path.exists('token.pickle'): with open('token.pickle', 'rb') as token: creds = pickle.load(token) # If there are no (valid) credentials available, let the user log in. if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( 'client_secrets.json', SCOPES) creds = flow.run_console() # Save the credentials for the next run with open('token.pickle', 'wb') as token: pickle.dump(creds, token) return creds def Create_Album(album): creds = mycreds service = build('photoslibrary', 'v1', credentials=creds) response_create_album = service.albums().create(body={'album': {'title': album}}).execute() print(response_create_album) return response_create_album['id'] def UploadMedia(fullname, albumid, creds): # 'latin-1' file = fullname.encode('utf-8').decode('latin-1').split('/')[-1] desc = file # step 1 upload raw bytes to google server headers = { 'Content-Type': "application/octet-stream", 'X-Goog-Upload-File-Name': file, 'X-Goog-Upload-Content-Type': "mime-type", 'X-Goog-Upload-Protocol': "raw", 'Authorization': "Bearer " + creds.token, } data = open(fullname, 'rb').read() response = requests.post('https://photoslibrary.googleapis.com/v1/uploads', headers=headers, data=data) image_token = response.text # step 2 create media items service = build('photoslibrary', 'v1', credentials=creds) # response_create_album = service.albums().create(body={'album': {'title': '我的相簿'}}).execute() myalbumid = albumid # results = service.albums().list().execute() ''' items = results.get('albums', []) if not items: print('No albums found.') else: for item in items: print(item['title']) if item['title'] == album: myalbumid = item['id'] print(myalbumid) ''' body = { 'albumId': myalbumid, 'newMediaItems': {'description': desc, 'simpleMediaItem': { 'uploadToken': image_token, 'fileName': file } } } response = service.mediaItems().batchCreate(body=body).execute() print(response) mess = response['newMediaItemResults'][0]['status'] # Success or Failed print(mess) return mess['message'] def ReadXML(file, strfile='File'): tree = ET.parse(file) root = tree.getroot() nodelist = root.findall(strfile) if strfile=='File': albumid = root.findall('AlbumID')[0].text for node in nodelist: if node.find('Upload').text == 'false': path = node.find('Fullname').text if UploadMedia(path, albumid, mycreds)=='Success': node.find('Upload').text = 'true' tree.write(file, encoding="utf-8", xml_declaration=True) else: return False else: for node in nodelist: if node.find('Upload').text == 'false': path = node.find('Fullname').text xmlpath = path.split('\\')[-1] + '.xml' xmlpath = os.path.join(basepath, xmlpath) if not os.path.isfile(xmlpath): Albumname = path.split('\\')[-1] albumid = Create_Album(Albumname) list = GetFiles(path) xmlpath = WriteXML(path, list, 'File', albumid) if ReadXML(xmlpath): node.find('Upload').text = 'true' tree.write(file, encoding="utf-8", xml_declaration=True) return True def WriteXML(path, files, strfile='File', albumid=''): xml = path.split('\\')[-1] doc = Document() base = doc.createElement('UploadFileList') doc.appendChild(base) filepath = doc.createElement('FilePath') base.appendChild(filepath) textpath = doc.createTextNode(path) filepath.appendChild(textpath) if albumid != '': albumidpath = doc.createElement('AlbumID') base.appendChild(albumidpath) alidpath = doc.createTextNode(albumid) albumidpath.appendChild(alidpath) for fi in files: file = doc.createElement(strfile) fullname = doc.createElement('Fullname') upload = doc.createElement('Upload') textfullname = doc.createTextNode(fi) isupload = doc.createTextNode('false') fullname.appendChild(textfullname) upload.appendChild(isupload) base.appendChild(file) file.appendChild(fullname) file.appendChild(upload) fname = xml + '.xml' fname = os.path.join(basepath, fname) with open(fname, 'w', encoding='utf-8') as f: doc.writexml(f, indent='\t', newl='\n', addindent='\t', encoding='utf-8') f.close return fname def GetFiles(path): includes = ['*.jpg','*.mp4'] # jpg, mp4 includes = r'|'.join([fnmatch.translate(x) for x in includes]) list = [] for dirPath, dirNames, fileNames in os.walk(path): list = [os.path.join(dirPath, f) for f in fileNames if re.match(includes, f, re.I)] return list def main(): """Shows basic usage of the People API. Prints the name of the first 10 connections. """ EnableLogging() logging.info('----------------------------------Getting Started--------------------------------------------------') path = mypath xmlpath = path.split('\\')[-1] + '.xml' xmlpath = os.path.join(basepath, xmlpath) if not os.path.isfile(xmlpath): dirs = os.listdir(path) list = [os.path.join(path, dir) for dir in dirs] fdname = WriteXML(path, list, 'Folder') print(list) if ReadXML(xmlpath, 'Folder'): LineNotifyMessage('上傳到 Google photo成功') logging.info('----------------------------------All Uploaded--------------------------------------------------') def LineNotifyMessage(msg): token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' headers = { "Authorization": "Bearer " + token # "Content-Type": "application/x-www-form-urlencoded" } # file = {'imageFile': open(picURI, 'rb')} payload = {'message': msg} r = requests.post("https://notify-api.line.me/api/notify", headers=headers, params = payload) return r.status_code if __name__ == '__main__': mycreds = Get_Token() # Get Google Token main() : → kenduest: Google photo api 文件有說上傳的圖片都是原始格式不會 05/18 01:57 : → kenduest: 壓縮處理,所以若是你要不占用空間得自己 resize 成為 05/18 01:57 : → kenduest: 1600萬畫素,一般用 Pillow 處理一下就可以。 05/18 01:57 只要是利用Google API 上傳的都會佔用空間, 不論你是多少解析度的 我已經試用好幾次 : 推 TakiDog: 有實作給個推,可以試著改用API吧 05/18 09:28 給你試試吧,試了好幾次 : → kenduest: 影片部分,只要你影片沒有超過 1080p 記得不壓縮的 05/19 00:11 : → kenduest: 所以你用 api or web 處理最後影片結果都是一樣 05/19 00:11 : → kenduest: 若你是拍 4k 可能就是不一樣情況 05/19 00:11 : 推 TWhtml: 推 05/19 00:31 : 推 unmolk: 推 其實可以推上github 不用這麼辛苦打程式碼在這XD 05/19 11:08 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.230.44.145 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Python/M.1598681103.A.C91.html
文章代碼(AID): #1VIV0FoH (Python)
文章代碼(AID): #1VIV0FoH (Python)