Evernote API を使ってみる


Evernote API の使い方などの説明です (2010/11/14 頃新規作成) (2013/6/5 OAuth に対応)。

Evernote API / 導入 / 認証 / 初期化 / 基本 / ノート / 戻る / トップページ


Evernote API

Evernote は、 テキストや画像・PDF ファイルの情報をサーバーに蓄積して、 記憶したデータを検索できるようにするメモサービスです。
 
Evernote API は、その Evernote のノートを操作できるようにする 公式の API サービスです。 Evernote クライアントが使っているものと同じ API が提供されているので、 その気になれば Evernote クライアントの代替品を作ることも 不可能ではありません。 拙作のツール もこの Evernote API を利用させてもらっています。
 
API にはクラウド API (Cloud API) とローカル API (Local API) の 2 種類が あります。 クラウド API はサーバー上に保存されているノートにアクセスし、 ほぼ全ての機能が使えます。 ローカル API は OS 上で動作している Evernote アプリと連携する API ですが、 Android 版ではそこそこですが、Mac 版は AppleScript からのアクセスを、 Windows 版は ENScript.exe からのアクセスを許すのみで、 ごく一部の機能にしかアクセスできません。 ここではクラウド API についてのみ扱います。
 
クラウド API は Facebook の開発した Thrift フレームワークに従っています。 ですが、提供されているライブラリ (Java, Perl, PHP, Python, Ruby, C# など多くが提供されてます) を使えば、 その仕組みを詳しく理解せずとも普通に言語のライブラリを 使っているようにアクセスできます。 ここでは Python を使った説明を書きますが、 処理の流れや呼び出すべき関数は同じです。
 
API の構造はシンプルになっており、 API リファレンス を見て分かるように、 NoteStore モジュール (クラスで表現されます) に ほとんどのサービス (関数で表現されます) は集約されており、 ログイン時やアカウント情報を触る時だけ UserStore モジュールを使います。

API の導入

Evernote API のドキュメント類は本家サイトで提供されています。 Evernote API Overview Evernote Corporation がそのサイトです。
 
Evernote API での開発をするには、申請をしてアクセス用の API キー (consumerKey と consumerSecret) を取得する必要があります。 こちら の 右上の▼マークのメニューで「API KEY の取得」で表示されるフォームに、 何を作りたいかの簡単な説明を書いて申請します。
 
始めの申請でもらえるコードでは、テストサーバーにのみ アクセスできるようになってます。 テストサーバー (Sandbox) は 普段使われているサーバーとはノートもユーザー管理も別管理なので、 普段自分が使っているノートとは切り離して実験できます (ただしデータは バックアップされていないなど、テストサーバーなりの保証になります)。 このテストサーバーにテスト用のアカウントを作りましょう。
 
テストサーバーで十分に検証がされたら、 こちら の 「キーのアクティベーションを申請する」から申請して、 API キーを本番サーバーでも使えるようにしてもらいます。

認証

クラウド API ではユーザーを OAuth 認証して、 それで得られる Token を使ってアクセスします。 先ほど取得した API キー (consumerKey, consumerSecret) は その OAuth 認証のために使います。 なお、以前はユーザー名とパスワードでアクセスできていましたが、 セキュリティ強化のため廃止されています (このページもその頃に そのような説明で書かれてましたが、OAuth 対応版に修正しました)。
 
ですが、API のテストをするために OAuth から手をつけるのは手間なので、 Token を取った状態からテストできる方法が用意されています。 テストサーバーでアカウントを取得した後に、 Developer Tokens のページに表示されている Developer Token をメモしておきましょう。 これが Token として使えますので、当面は直接この値を使います。
 
当然ながら、本番サーバーには Developer Tokens は用意されていませんので、 最終的には OAuth 認証を使って Token を取得するフローを実装する 必要があります。

初期化

クラウド API を使うには、当然ながら、まずサーバーに接続する必要があります。
 
Developer Token を持っている場合はとても簡単です。 evernote.api.client.EvernoteClient の引数 token に Developer Token を、 引数 sandbox に接続先がテストサーバーかを指定して EvernoteClient を生成します。 そこから get_user_store() 関数で UserStore を取得します。 UserStore はユーザーの情報を持ってます。
	import evernote.edam.userstore.UserStore
	import evernote.edam.notestore.NoteStore
	import evernote.edam.userstore.constants
	import evernote.api.client
	
	# あらかじめ、authToken に Developer Token を代入しておく
	
	client=evernote.api.client.EvernoteClient(token=authToken,sandbox=True)
	
	userStore=client.get_user_store()
	
	# ライブラリがクラウド API のバージョンに対応してるかチェック
	success=userStore.checkVersion(
	    "Evernote Test/0.0.0; Windows/XP SP3",
	    # 第一引数はアプリケーション名を UserAgent 的に書くのが本当
	    evernote.edam.userstore.constants.EDAM_VERSION_MAJOR,
	    evernote.edam.userstore.constants.EDAM_VERSION_MINOR
	)
	assert success
また、EvernoteClient から get_note_store() 関数で NoteStore を取得します。 NoteStore はノートの情報を持ってます。
	noteStore=client.get_note_store()
	
	# ノートブック一覧を取得
	notebooks=noteStore.listNotebooks()
	for notebook in notebooks:
		print notebook.name.decode("utf-8")		# 文字コードは UTF-8

基本的な使い方

一度 token の取得と NoteStore の生成が出来ていれば、 NoteStore に対して関数を呼ぶことでほとんどの処理はできます。
 
ノート一覧の取得
 
ノートの一覧を取る機能はなく、一覧を取る場合も検索をかける手順を取ります。 検索は NoteStore に findNotesMetadata() を呼び出して NotesMetadataList データ型 (クラスで表現されます) を取得し、 その notes フィールドからリスト型で格納されている ノート (NoteMetadata データ型) を得ます。
 
findNotes() の引数には、 検索条件 (NoteFilter データ型), 検索結果の何番目から, 何個取るか, 結果として欲しい情報、を指定します。
	import evernote.edam.notestore.ttypes
	
	# 検索条件として、検索語なし、更新日順ソートを指定
	filter=evernote.edam.notestore.ttypes.NoteFilter()
	filter.order=evernote.edam.type.ttypes.NoteSortOrder.UPDATED
	
	# 検索結果として、タイトル名のみを指定
	resultSpec=evernote.edam.notestore.ttypes.NotesMetadataResultSpec()
	resultSpec.includeTitle=True
	
	# noteList にノート 10 件のタイトルを取得
	noteMetaList=noteStore.findNotesMetadata(filter,0,10,resultSpec)
	
	# ノートごとに処理
	for noteMeta in noteMetaList.notes:
		print(noteMeta.title.decode("utf-8"))	# ノートタイトルを取得
なお、文字列は全て UTF-8 で扱われているようです。 Python なら、文字列を返す関数や値は UTF-8 の str 型なので、 note.name.decode("utf-8") のように unicode 型に変換して扱うと良いでしょう。
 
ノートの実体の取得
 
findNotesMetadata() で得た NoteMetadata データ型には、 ノートの実体 (本文) やリソース (添付ファイル) 情報は入っていません。 NoteStore に getNote() を呼び出して、完全なノートの情報を得ましょう。
	for noteMeta in noteMetaList.notes:
		note=noteStore.getNote(noteMeta.guid,True,True,True,True)
		
		# note.content で本文が読み取れる
		print("  "+note.content.decode("utf-8"))
getNote() 関数の第二引数には、ノートを識別する GUID を指定します。 ノートの GUID は検索結果で得られたノート情報などから参照できます。 なお、Evernote ではノート以外にもノートブックやタグも GUID で識別しています。
 
ノートの新規作成
 
ノートを新規に作って登録するには、Note データ型のデータを用意して、 NoteStore に createNote() を呼び出すことで実現します。
	note=evernote.edam.type.ttypes.Note()
	note.title=u"ノートタイトル".encode("utf-8")
	
	# 本文の指定内容は次章を参照
	content=u"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
	content=content+u"<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml.dtd\">"
	content=content+u"<en-note>"
	content=content+u"ノートの本文"
	content=content+u"</en-note>"
	note.content=content.encode("utf-8")
	
	# ノート生成を実行
	noteStore.createNote(note)

ノートの本文

ノートの本文は XHTML をベースに作られています (正確には ENML と 名付けられた XML データで、XHTML のサブセット+独自拡張)。 XHTML のほとんどのタグ・属性をサポートしてるようで、 改行の br タグのようによく使われるものから acronym のように滅多に使われないものまでサポートされてます。 BUTTON, SCRIPT タグや onclick 属性など、表示に関わるものでない ( 操作やスクリプト) ものだけを外しているように見えます。
 
style タグや外部スタイルシートの参照はサポートされていないものの (Web ページをクリップしても見た目情報がなくなるのはこのため)、 style 属性はサポートされており、実際に今も使われています。 どうやらいずれは style タグもサポート するようにしていく予定があるようです。
 
XHTML は HTML を XML で再定義し、HTML の後継を目指していたものですが、 ページ作者にメリットがなく普及しなかったため、HTML を拡張する HTML 5 の 作成に軌道修正をしています。 その意味ではやや時代の流れとずれてしまってますが、XML データで あることや HTML と完全ではないものの互換性があるため、 扱いやすいとも言えます。
 
そのノートの本文は NoteStore の getNote() などで得られる Note 型の値の content フィールドに収められています。 Evernote クライアントでノートをエクスポートした .enex ファイルを テキストエディタで開いても確認できるので、 適当に作ったノートを見てみると良いでしょう。
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
    <en-note>
      <b>ノートの本文</b>
    </en-note>
ルートノードが <en-note> で、その下に本文データが入ります。 独自の拡張部分はさほど多くなく、この EN-NOTE タグの他には、 添付ファイル (画像や PDF) の貼り付けに使う EN-MEDIA タグ、 TODO チェックマークの EN-TODO タグ、 暗号化テキストの EN-CRYPT タグ、で全てです。
 
※ここから下の説明は、実際の挙動を調べて得た情報で、ドキュメントで 提供されていたものではないため、ある日突然変更がされる可能性があります。
 
ノートを Evernote の Web サイトEvernote クライアント から編集する時に、フォーマットの指定ができますが、 それによってタグや属性が自動で付与されています。 ですが、これが結構統一性がなく癖のある設定をしているようです。
 
まず、入力されたスペースは &nbsp; に (ペーストすると空白文字の場合もある)、タブキーでの入力は &nbsp; が 5 つ (Evernote クライアント 3.0 からタブ文字 \t になったようです) に変換されます。 また、1 行ごとに DIV タグでくくられるようです (メールからの登録の場合は改行を <br/> タグに変換することで行が区切られます)。
 
編集時のフォーマット指定と対応する ENML タグ
フォーマット Web サイトから編集した時 Windows クライアント 3.0 から編集した時
太字 <strong> <b>
イタリック <em> <i>
下線 <span style="text-decoration: underline;"> <u>
取り消し線 <span style="text-decoration: line-through;"> <s>
下付き文字 <sub> 指定できず
上付き文字 <sup> 指定できず
左揃え <div style="text-align: left;"> <div style="text-align: left;">
中央揃え <div style="text-align: center;"> <div style="text-align: center;">
右揃え <div style="text-align: right;"> <div style="text-align: right;">
両端揃え 指定できず <div style="text-align: justify;">
箇条書きリスト <ul><li> <ul><li>
番号付きリスト <ol><li> <ol><li>
インテンド <div style="padding-left: 30px;"> <blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;">
水平線 <hr/> <hr/>

戻る