CodeZine(コードジン)

特集ページ一覧

Pythonで使って覚えるEvernote API

ノート内容からタグを付与するプログラムを作ってみよう

  • LINEで送る
  • このエントリーをはてなブックマークに追加
目次

ノートコンテンツからタグを生成・付与するプログラムの実装(2)

ノートコンテンツからタグを生成する

 ノートコンテンツからタグを生成する処理を見ていきます。

ノートコンテンツ文字列からタグを生成する関数
# 形態素解析器の初期化
_t = Tokenizer()

# ~中略~

def _generate_tag(content, tag_dict):
    '''指定コンテンツからタグを生成する。

    Args:
        content: タグを生成する対象コンテンツ
        tag_dict: タグとして抽出する文字列を格納した辞書。キーは小文字化した文字列

    Returns:
        生成したタグのSet
    '''
    # ENMLタグの除去(1)
    notags = strip_enml(content)
    u_notags = unicode(notags, encoding='utf-8')

    # 形態素解析の結果から固有名詞リストの取得(2)
    tokens = [token for token in _t.tokenize(u_notags) \
        if token.part_of_speech.split(',')[1] == u'固有名詞']
    tags = set()
    for t in tokens:
        word = t.surface
        # 小文字化して比較
        lower = word.lower()
        # タグ辞書に存在する固有名詞のみを抽出(3)
        if tag_dict.has_key(lower):
            tags.add(tag_dict[lower])
    return tags

def strip_enml(enml_str):
    '''EvernoteノートコンテンツのXHTML (ENML) タグを除去する

    Args:
        enml_str : ENML文字列

    Returns:
        ENMLタグを除去した文字列
    '''
    tree = etree.fromstring(enml_str)
    return etree.tostring(tree, encoding='utf8', method='text')

 (1)strip_enml関数を呼び出してENMLのタグを除去します。strip_enml関数では、XML・HTML処理ライブラリlxmlを使って、ENMLをDOMツリー化してタグ以外のテキスト部分を取得することで、ENMLのタグを取り除いています。

 (2)ENMLタグを除去したノートデータを、形態素解析した分割文字列から固有名詞のみを抽出します。_tはグローバル変数で初期化しています。

 Janomeの形態素解析結果はTokenオブジェクトのリストで返されます。Janomeの仕様については公式サイトを参照してください。

Tokenオブジェクトの属性
属性 説明
surface 表層形
part_of_speech 品詞、品詞細分類1~3のカンマ区切り
infl_type 活用型
infl_form 活用形
base_form 原形
reading 読み
phonetic 発音
node_type ノードタイプ。システム辞書(SYS_DICT)、ユーザー辞書(USER_DICT)、不明(UNKNOWN)のいずれか

 (3)Qiitaタグ辞書に存在する固有名詞のみを抽出します。

生成したタグをノートに付与する

 生成したタグファイルを読み込んで、ノートへタグを付与します。

ノートへタグを付与する関数
def assign_tags(note_store, tag_fp):
    '''指定ファイルのタグを使ってノートへタグを付与する。

    Args:
        note_store: Evernoteノートストア
        tag_fp: 付与するタグを記録したファイル
    '''
    for line in tag_fp:
        # ノートGUIDと付与するタグを取得する(1)
        tags = json.loads(line)

        # ノートを取得する(2)
        n = note_store.getNote(tags['note_guid'], False, False, False, False)

        # ノートに既存タグがある場合、重複しないタグのみを抽出する(3)
        assign_tags = tags['tag_list']
        if n.tagNames is not None:
            assign_tags = set(n.tagNames.extend(assign_tags))

        # ノートにタグを付与する(4)
        n.tagNames = assign_tags
        note_store.updateNote(n)

 (1)タグファイルを1行ずつ読込み、JSON文字列をデコードします。

 (2)タグファイルのノートGUIDをキーに、NoteStoreのgetNote()を使ってノートオブジェクトを取得します。ここではノートに付与されているタグリストのみが取得できればよいため、コンテンツや添付ファイル等を取得するかどうかを指定する第2引数以降は全てFalseを指定しています。

NoteStore.getNote()のシグニチャ
Types.Note getNote(Types.Guid guid,
                   bool withContent,
                   bool withResourcesData,
                   bool withResourcesRecognition,
                   bool withResourcesAlternateData)
    throws Errors.EDAMUserException, Errors.EDAMSystemException, Errors.EDAMNotFoundException

 (3)一度setオブジェクトに変換することで、既にノートに付与されているタグと重複しないタグのみを抽出しています。

 (4)ノートにタグを設定し、NoteStoreのノート更新処理updateNote()を呼び出しています。ノートへのタグ付与はNote.tagNamesにリストをセットすることで可能です。Evernoteアカウント内で存在しないタグを指定した場合はタグが新規作成され、既に存在するタグは重複して作成されることはありません。

サンプルプログラムを実行してみよう

 これで必要な関数が実装できました。実装した関数を呼び出すメイン関数を作って実行してみましょう。

メイン関数
    # ノートへ付与するタグの一時保存先ファイル
    TAG_FILE_PATH = 'note_tag.jsons'

    # ~中略~

def main():
    '''メイン関数。

    Evernoteノートコンテンツからタグ情報を生成し、ファイルへ出力する。
    ファイルを読み込んでノートへタグを付与する。
    '''

    try:
        # Evernoteクライアントの初期化
        client = EvernoteClient(token='Set your developers token')
        note_store = client.get_note_store()

        # ノートコンテンツからタグを生成し、ファイルへ出力する(1)
        with open(TAG_FILE_PATH, 'w') as tag_fp:
            generate_note_tag(note_store, tag_fp)

        # !!注意!!
        # 生成されたタグファイルが妥当であることを確認した上で
        # 下記コードのコメントアウトを外してノートへのタグ付与を行ってください

        # タグファイルを使ってノートへタグを付与する(2)
        # with open(TAG_FILE_PATH, 'r') as tag_fp:
        #     assign_tags(note_store, tag_fp)

    except Exception as e:
        print('予期せぬエラーが発生しました。')
        traceback.print_exc()
    else:
        print('finished!!')

if __name__ == '__main__':
    main()

 (1)Evernoteのノートコンテンツからタグを生成し、結果をファイル出力するgenerate_note_tag()関数を呼び出します。

 (2)(1)で生成したタグファイルを使ってノートへタグを付与します。コメントにも記載している通り、最初はコメントアウトした状態で実行し、生成されたタグファイルの内容を確認してください。ノート内容に対して生成されているタグが問題なければ、コメントアウトを外して実行してください。

 ノートの件数によっては処理時間がかかります。また、Evernote APIのレート制限にかかってエラーとなることがあります。APIのレート制限の問題については、エラーをハンドリングしてリトライする、プロキシオブジェクトを実装するといった対策が可能です。APIのレート制限エラーのハンドリングについては前述した公式サイトの情報を参照してください。

 筆者のEvernoteアカウントで試した実行結果の一部です。

実行結果その1

 ノート内容:※WikipediaのTensorFlowをWebクリッピングしたもの。

 付与されたタグ:C,google,Python,Twitter,Ubuntu,iOS,Mobile,AI,Linux,TensorFlow,Android

 ※C++がCになっていました。この辺りはJanomeでユーザー定義辞書を使うといった対策が必要そうです。

実行結果その2

 ノート内容:Hadoop運用管理ツールApache Ambariの調査メモ

Apache Ambariの調査メモ
Apache Ambariの調査メモ

 付与されたタグ:Web,Windows,hadoop,rest,Kafka,api,UI,hive,HTTPS,Linux,Spark,SSH

まとめ

 Evernote APIの基本的な使い方を解説し、ノート内容からタグを付与するプログラムを作りました。具体的な活用方法を通して、手軽に利用できることをイメージいただけたのではないでしょうか。

 Evernote APIを使って用途に特化したアプリケーションやサービスを作ってみるのもよいですし、もっとハードルを下げて個人的なツールから作ってみるのも面白いと思います。APIを活用することですぐに動く実用的なものが作れるのは楽しいものです。プログラミング学習にもおすすめします。

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 水倉 良明 (サイオステクノロジー株式会社)(ミズクラ ヨシアキ)

    分子生物学の世界からIT業界に飛び込み、エンタープライズなシステム開発の面白さに魅了される。アプリケーションエンジニアとして経験を積み、AWS、Azureの登場でいつの間にかインフラ構築、運用にも携わるように。現在はサイオステクノロジー(株)で主にクラウド上でのデータ分析基盤構築や関連ツールの開発に...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5