Google Documentをよく作成しているのですが、いつも文書のタイトルを入力して、本文にもタイトルを入力するようにしています。
地味に同じ文字列を二度入力するのは手間です。
そこからGoogle Document APIを使って、作業効率化できないかなと思って調べてみることにしました。
まず結論
ここに至る結論が長いので、結論から書きます。私は以下のようなコードにすることにしました。
from __future__ import print_function import pickle import os.path import webbrowser from googleapiclient.discovery import build from google_auth_oauthlib.flow import InstalledAppFlow from google.auth.transport.requests import Request SCOPES = ['https://www.googleapis.com/auth/documents'] def get_credential(): 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( 'credentials.json', SCOPES) creds = flow.run_local_server(port=0) # Save the credentials for the next run with open('token.pickle', 'wb') as token: pickle.dump(creds, token) return creds def main(title, text): """Shows basic usage of the Docs API. Prints the title of a sample document. """ creds = get_credential() service = build('docs', 'v1', credentials=creds) body = { "title":title } doc = service.documents().create(body=body).execute() requests = [ { 'insertText': { 'location': { 'index': 1, }, 'text': text } } ] document_id = doc.get('documentId') url = 'https://docs.google.com/document/d/' + document_id service.documents().batchUpdate(documentId=document_id, body={'requests': requests}).execute() webbrowser.open(url) if __name__ == '__main__': # 文書のタイトルと本文の内容を指定 main('ドキュメントタイトル','本文')
- credentials.jsonから認証情報を生成
- 文書を作成
- 文書に文字列を挿入
- WebBrowserで生成したドキュメントを開く
という流れです。
補足説明
文書を作成して、さらに文書に文字列を挿入しています。
これは二度手間だと思うのですが、GoogleDocumentの厄介な点として文書構造の複雑さにあります。
末尾で文書情報のjsonサンプルを紹介しますが、文書情報はフォント、フォントサイズ、文字の揃えなど、こちらが考える以上の情報量です。
それを補うだけの情報をAPIで用意されているようです。
が、それっぽい文書情報をjsonで入力してみたのですが本文が空で上手く行きませんでした。
私としては、とりあえず、手軽に作れれば良いやということで、insertTextのAPIを用いて文字列を挿入しています。
SCOPE
SCOPE(文書の参照・編集について)は以下を。
参考までに文書構造を
body = { "title": "ドキュメントタイトル", "body": { "content": [ { "endIndex": 1, "sectionBreak": { "sectionStyle": { "columnSeparatorStyle": "NONE", "contentDirection": "LEFT_TO_RIGHT" } } }, { "startIndex": 1, "endIndex": 6, "paragraph": { "elements": [ { "startIndex": 1, "endIndex": 6, "textRun": { "content": "タイトル\n", "textStyle": {} } } ], "paragraphStyle": { "headingId": "h.er2w7sbutfor", "namedStyleType": "TITLE", "direction": "LEFT_TO_RIGHT" } } }, { "startIndex": 6, "endIndex": 13, "paragraph": { "elements": [ { "startIndex": 6, "endIndex": 13, "textRun": { "content": "サブタイトル\n", "textStyle": {} } } ], "paragraphStyle": { "headingId": "h.6imx0s8syx4j", "namedStyleType": "SUBTITLE", "direction": "LEFT_TO_RIGHT" } } }, { "startIndex": 13, "endIndex": 18, "paragraph": { "elements": [ { "startIndex": 13, "endIndex": 18, "textRun": { "content": "見出し1\n", "textStyle": {} } } ], "paragraphStyle": { "headingId": "h.95f0tp522tw7", "namedStyleType": "HEADING_1", "direction": "LEFT_TO_RIGHT" } } }, { "startIndex": 18, "endIndex": 23, "paragraph": { "elements": [ { "startIndex": 18, "endIndex": 23, "textRun": { "content": "見出し2\n", "textStyle": {} } } ], "paragraphStyle": { "headingId": "h.ygndpctymssk", "namedStyleType": "HEADING_2", "direction": "LEFT_TO_RIGHT" } } }, { "startIndex": 23, "endIndex": 28, "paragraph": { "elements": [ { "startIndex": 23, "endIndex": 28, "textRun": { "content": "見出し3\n", "textStyle": {} } } ], "paragraphStyle": { "headingId": "h.bkjlj5ejudzk", "namedStyleType": "HEADING_3", "direction": "LEFT_TO_RIGHT" } } } ] }, "documentStyle": { "background": { "color": {} }, "pageNumberStart": 1, "marginTop": { "magnitude": 72, "unit": "PT" }, "marginBottom": { "magnitude": 72, "unit": "PT" }, "marginRight": { "magnitude": 72, "unit": "PT" }, "marginLeft": { "magnitude": 72, "unit": "PT" }, "pageSize": { "height": { "magnitude": 841.8897637795277, "unit": "PT" }, "width": { "magnitude": 595.2755905511812, "unit": "PT" } } }, "namedStyles": { "styles": [ { "namedStyleType": "NORMAL_TEXT", "textStyle": { "bold": False, "italic": False, "underline": False, "strikethrough": False, "smallCaps": False, "backgroundColor": {}, "foregroundColor": { "color": { "rgbColor": {} } }, "fontSize": { "magnitude": 11, "unit": "PT" }, "weightedFontFamily": { "fontFamily": "Arial", "weight": 400 }, "baselineOffset": "NONE" }, "paragraphStyle": { "namedStyleType": "NORMAL_TEXT", "alignment": "START", "lineSpacing": 115, "direction": "LEFT_TO_RIGHT", "spacingMode": "COLLAPSE_LISTS", "spaceAbove": { "unit": "PT" }, "spaceBelow": { "unit": "PT" }, "borderBetween": { "color": {}, "width": { "unit": "PT" }, "padding": { "unit": "PT" }, "dashStyle": "SOLID" }, "borderTop": { "color": {}, "width": { "unit": "PT" }, "padding": { "unit": "PT" }, "dashStyle": "SOLID" }, "borderBottom": { "color": {}, "width": { "unit": "PT" }, "padding": { "unit": "PT" }, "dashStyle": "SOLID" }, "borderLeft": { "color": {}, "width": { "unit": "PT" }, "padding": { "unit": "PT" }, "dashStyle": "SOLID" }, "borderRight": { "color": {}, "width": { "unit": "PT" }, "padding": { "unit": "PT" }, "dashStyle": "SOLID" }, "indentFirstLine": { "unit": "PT" }, "indentStart": { "unit": "PT" }, "indentEnd": { "unit": "PT" }, "keepLinesTogether": False, "keepWithNext": False, "avoidWidowAndOrphan": True, "shading": { "backgroundColor": {} } } }, { "namedStyleType": "HEADING_1", "textStyle": { "fontSize": { "magnitude": 20, "unit": "PT" } }, "paragraphStyle": { "namedStyleType": "NORMAL_TEXT", "direction": "LEFT_TO_RIGHT", "spaceAbove": { "magnitude": 20, "unit": "PT" }, "spaceBelow": { "magnitude": 6, "unit": "PT" }, "keepLinesTogether": True, "keepWithNext": True } }, { "namedStyleType": "HEADING_2", "textStyle": { "bold": False, "fontSize": { "magnitude": 16, "unit": "PT" } }, "paragraphStyle": { "namedStyleType": "NORMAL_TEXT", "direction": "LEFT_TO_RIGHT", "spaceAbove": { "magnitude": 18, "unit": "PT" }, "spaceBelow": { "magnitude": 6, "unit": "PT" }, "keepLinesTogether": True, "keepWithNext": True } }, { "namedStyleType": "HEADING_3", "textStyle": { "bold": False, "foregroundColor": { "color": { "rgbColor": { "red": 0.2627451, "green": 0.2627451, "blue": 0.2627451 } } }, "fontSize": { "magnitude": 14, "unit": "PT" } }, "paragraphStyle": { "namedStyleType": "NORMAL_TEXT", "direction": "LEFT_TO_RIGHT", "spaceAbove": { "magnitude": 16, "unit": "PT" }, "spaceBelow": { "magnitude": 4, "unit": "PT" }, "keepLinesTogether": True, "keepWithNext": True } }, { "namedStyleType": "HEADING_4", "textStyle": { "foregroundColor": { "color": { "rgbColor": { "red": 0.4, "green": 0.4, "blue": 0.4 } } }, "fontSize": { "magnitude": 12, "unit": "PT" } }, "paragraphStyle": { "namedStyleType": "NORMAL_TEXT", "direction": "LEFT_TO_RIGHT", "spaceAbove": { "magnitude": 14, "unit": "PT" }, "spaceBelow": { "magnitude": 4, "unit": "PT" }, "keepLinesTogether": True, "keepWithNext": True } }, { "namedStyleType": "HEADING_5", "textStyle": { "foregroundColor": { "color": { "rgbColor": { "red": 0.4, "green": 0.4, "blue": 0.4 } } }, "fontSize": { "magnitude": 11, "unit": "PT" } }, "paragraphStyle": { "namedStyleType": "NORMAL_TEXT", "direction": "LEFT_TO_RIGHT", "spaceAbove": { "magnitude": 12, "unit": "PT" }, "spaceBelow": { "magnitude": 4, "unit": "PT" }, "keepLinesTogether": True, "keepWithNext": True } }, { "namedStyleType": "HEADING_6", "textStyle": { "italic": True, "foregroundColor": { "color": { "rgbColor": { "red": 0.4, "green": 0.4, "blue": 0.4 } } }, "fontSize": { "magnitude": 11, "unit": "PT" } }, "paragraphStyle": { "namedStyleType": "NORMAL_TEXT", "direction": "LEFT_TO_RIGHT", "spaceAbove": { "magnitude": 12, "unit": "PT" }, "spaceBelow": { "magnitude": 4, "unit": "PT" }, "keepLinesTogether": True, "keepWithNext": True } }, { "namedStyleType": "TITLE", "textStyle": { "fontSize": { "magnitude": 26, "unit": "PT" } }, "paragraphStyle": { "namedStyleType": "NORMAL_TEXT", "direction": "LEFT_TO_RIGHT", "spaceAbove": { "unit": "PT" }, "spaceBelow": { "magnitude": 3, "unit": "PT" }, "keepLinesTogether": True, "keepWithNext": True } }, { "namedStyleType": "SUBTITLE", "textStyle": { "italic": False, "foregroundColor": { "color": { "rgbColor": { "red": 0.4, "green": 0.4, "blue": 0.4 } } }, "fontSize": { "magnitude": 15, "unit": "PT" }, "weightedFontFamily": { "fontFamily": "Arial", "weight": 400 } }, "paragraphStyle": { "namedStyleType": "NORMAL_TEXT", "direction": "LEFT_TO_RIGHT", "spaceAbove": { "unit": "PT" }, "spaceBelow": { "magnitude": 16, "unit": "PT" }, "keepLinesTogether": True, "keepWithNext": True } } ] }, "revisionId": "AOV_f4-TiMb57reetZjj3ZBaNwuyf0eVOuiRuDL83726nz5RagiKs47V08duz0X5Bn-qVSCg_qYk1KG3vtnfj3Q", "suggestionsViewMode": "SUGGESTIONS_INLINE", "documentId": "15zjqYL9PAJ40tFYqb3PwzMyl-QmvtR58M_W6NXtZn7E" }
長いです。