Evernote API を使ってみよう(2)
ノートを作成する
続いて先ほど作成したノートブック内にノートを作成してみましょう。「ノートブックの作成」のソースの後に下記のコードを追記します。
# ノートインスタンスを生成する(4)
note = Types.Note()
note.title = 'Hello, Evernote'
note.content = '<?xml version="1.0" encoding="UTF-8"?>'
note.content += '<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">'
note.content += '<en-note>New note!!!</en-note>'
# ノート作成先のノートブックのGUIDを指定する(5)
note.notebookGuid = created_notebook.guid
# ノートを作成する(6)
note_store.createNote(note)
print('A note was created!')
(4)ノートインスタンスを生成し、タイトル、ノートコンテンツを設定します。
ENML形式とは
EvernoteはノートコンテンツをEvernote独自のマークアップ言語であるENML(Evernote Markup Languageの略。XHTMLのサブセットとして定義。2017/3/8時点でバージョン2)で保持しています。そのため、XML・DOCTYPE宣言が必要になり、ノートデータは<en-note>タグで囲む必要があります。ENMLとして不正なフォーマットの場合、evernote.edam.error.ttypes.EDAMUserException(エラーコード11:ENML_VALIDATION)が発生する仕様となっています。
(5)ノートオブジェクトのnotebookGuidにノート作成先のノートブックのGUID(ノートブックに振られるユニークID)を指定します。ここでは「ノートブック作成サンプル」で作成したノートブックのGUIDを指定しています。
(6)NoteStoreのノート作成メソッドcreateNote()を呼び出して、Evernoteにノートを保存します。
先ほど作成したノートブックを削除またはリネームしてから、同じように実行してみましょう。
> python samplecreate.py
ノートブック一覧を取得する
ノートブック一覧を取得してみましょう。
# ノートブック一覧の取得(1)
notebooks = note_store.listNotebooks()
print('Number of notebooks: %d' % len(notebooks))
for notebook in notebooks:
print('Notebook name: ' + notebook.name)
(1)NoteStoreのlistNotebooks()関数を呼び出して全ノートブックの一覧を取得します。戻り値のevernote.edam.type.ttypes.Notebookのリストをfor文で取り出してノートブック名を出力しています。
| 属性 | 型 |
|---|---|
| guid | Guid |
| name | string |
| updateSequenceNum | i32 |
| defaultNotebook | bool |
| serviceCreated | Timestamp |
| serviceUpdated | Timestamp |
| publishing | Publishing |
| published | bool |
| stack | string |
| sharedNotebookIds |
list |
| sharedNotebooks |
list |
| businessNotebook | BusinessNotebook |
| contact | User |
| restrictions | NotebookRestrictions |
| recipientSettings | NotebookRecipientSettings |
> python sampleread.py # 実行結果 Number of notebooks: 1 Notebook name: My First Notebook
ノート一覧を取得する
今度はノートの一覧を取得してみましょう。ノートはNoteFilterクラスで検索条件を指定することで取得します。
# ノートブック一覧の取得(1)
notebooks = note_store.listNotebooks()
print('Number of notebooks: %d' % len(notebooks))
for notebook in notebooks:
print('Notebook name: ' + notebook.name)
# 検索条件設定:指定ノートブックにひも付くノート(2)
filter = NSTypes.NoteFilter()
filter.notebookGuid = notebook.guid
# 検索結果設定:ノートタイトルのみ取得(3)
resultSpec = NSTypes.NotesMetadataResultSpec()
resultSpec.includeTitle = True
# ノートメタデータの検索(4)
metalist = note_store.findNotesMetadata(filter, 0, 10, resultSpec)
# ノートGUIDを検索条件にノートデータの取得(5)
for n in metalist.notes:
content = note_store.getNoteContent(n.guid)
print('\tNote title: ' + n.title)
print('\tNote content: ' + content)
(1)「サンプルプログラム:ノートブック一覧の取得」と同様にノートブックを取得します。
(2)検索条件クラスNoteFilterのインスタンスを生成し、ノートブックのGUIDを検索条件に指定します。
(3)ノートメタデータの検索で取得する結果を指定します(ここではタイトルのみを結果に含めています)。
(4)NoteStoreのfindNotesMetadata(検索条件, 取得開始インデックス, 取得最大件数, 検索結果定義)を呼び出して、検索条件にヒットしたノートメタデータのリストを取得します。ここでは10件のノートを取得しています。
(5)ノートメタデータのGUIDを使って、ノート文書データを取得します。
Evernote APIでは複数のノートデータを取得するAPIとして、APIノートのメタデータ(GUID、タイトル、作成日、更新日など)のみを返却する仕様になっています(※注1)。そのため、個別のノートデータはGUIDを指定して取得し直す必要があります。
なぜ、このような仕様になっているのでしょうか。 Evernote APIを利用するクライアントアプリケーションにとって、ノート一覧を取得したいけれどノート文書データまではいらないケースがあります(例えば、ノートタイトルのみが必要なケースなど)。取得したいノート一覧内に、サイズの大きなノートが存在していると非常に時間がかかってしまいますし、メモリ使用量も上がってしまいます。毎回ノートのデータ全体を取得せずに最小限の情報に絞り、本当にノートデータを取得する必要のある時にだけノートデータを取得することで、1回のAPI呼び出しの処理時間、ネットワーク帯域を抑えられます。結果として、Evernoteサービス側、クライアントアプリケーション側双方にとってバランスの取れた仕様といえます。
findNotes()は現在非推奨
※注1:NoteStoreにはメタデータのリストではなく、ノートオブジェクトのリストを取得するfindNotes()がありますが、Python SDKのバージョン1.24から非推奨となり、API Referenceにも記載されなくなりました。
> python sampleread.py
# 実行結果
Number of notebooks: 1
Notebook name: My First Notebook
Note title: Hello, Evernote
Note content: <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note>New note!!!</en-note>
