CodeZine(コードジン)

特集ページ一覧

Pythonで使って覚えるEvernote API

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

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

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

 それでは実装していきましょう。

必要モジュール、クラスのインポート

 ソースコードの文字コードはUTF-8とし、必要モジュールとクラスをインポートします。

 標準ライブラリのjsonはノートコンテンツから生成したタグをJSON形式でファイルへ出力する際に利用します。

 ローカルライブラリのqiitaは、Qiita APIを呼び出してQiitaのタグを取得するモジュールです(サンプルファイルのqitta.py)。

モジュールヘッダ
# coding:utf-8
# 標準ライブラリ
import json
import traceback
# サードパーティライブラリ
from evernote.api.client import EvernoteClient
import evernote.edam.notestore.ttypes as NSTypes
import evernote.edam.type.ttypes as Types
from lxml import etree
from janome.tokenizer import Tokenizer
# ローカルライブラリ
import qiita

ノートからタグを生成し、結果をファイルへ出力する

 まずはノートブック一覧を取得し、ノートブック内のノートからタグを生成します。タグの生成結果はファイルへ出力します。

ノートコンテンツからタグを生成する関数
def generate_note_tag(note_store, tag_fp):
    '''ノートコンテンツからタグを生成する。

    ノートコンテンツの内容から抽出した技術用語をタグとして指定ファイルへ出力する。

    Args:
        note_store: Evernoteノートストア
        tag_fp: 生成したタグの出力先ファイル
    '''

    # ノートブック一覧の取得
    notebooks = note_store.listNotebooks()
    print('Number of notebooks: %d' % len(notebooks))

    # Qiitaタグを取得する(key: 小文字タグ文字列, value: タグ文字列)(1)
    qiita_tag_dict = qiita.get_tags()

    for notebook in notebooks:
        print('Notebook name: ' + notebook.name)

        # 検索条件設定:指定ノートブックにひも付くノート
        filter = NSTypes.NoteFilter()
        filter.notebookGuid = notebook.guid

        # 検索結果設定:ノートタイトルのみ取得
        resultSpec = NSTypes.NotesMetadataResultSpec()
        resultSpec.includeTitle = True

        # ノートメタデータの検索
        startIdx = 0
        maxNotes = 250
        while True:
            metalist = note_store.findNotesMetadata(filter, startIdx, maxNotes, resultSpec)
            for n in metalist.notes:
                # ノートGUIDを検索条件にノートデータの取得
                content = note_store.getNoteContent(n.guid)
                print('\tNote title: ' + n.title)
                # ノートコンテンツからタグを生成する(2)
                tags = _generate_tag(content, qiita_tag_dict)

                if 0 < len(tags):
                    # タグ一覧をJSON形式で出力する(3)
                    j = json.dumps(
                        {
                            'note_guid': n.guid,
                            'note_title': n.title,
                            'tag_list': [tag.encode('utf-8') for tag in tags],
                        },
                        ensure_ascii=False
                    )
                    tag_fp.write(j)
                    tag_fp.write('\n')

            # 次のノートの存在チェックをする(4)
            if has_next_note(metalist):
                startIdx += maxNotes
            else:
                break

 「ノート一覧を取得する」とほぼ同じコードに下記の処理を追加しています。

 (1)Qiitaタグを取得します。標準ライブラリのurllib2を使用してAPIを呼び出し、取得したJSONからタグ名の辞書(キー:小文字タグ名、値:タグ名)を返却しています。Evernoteのノートコンテンツの比較用に辞書のキーは小文字化しています。処理内容はEvernote APIとは直接関係がないため、ここでは詳細な解説は割愛します。ソースコードを参考にしてください。

 Qiita APIにも呼び出し制限があります。未認証ではIPアドレスごとに1時間に60回まで、認証していれば1時間に1000回までとなります。本サンプルでは未認証でのAPI呼び出しとしています。

 詳細はQiita API仕様を確認してください。

Qiitaタグを取得するモジュール(qiita.py)
# coding:utf-8
import json
import urllib2

COUNT_PER_PAGE = 100
base_url = 'https://qiita.com/api/v2/tags?page={page}&per_page=' \
            + str(COUNT_PER_PAGE) + '&sort=count'

def get_tags():
    '''Qittaタグを投稿数の多い順に1万件取得する。

    Returns:
        タグ辞書(キー:タグ小文字文字列、値:タグ文字列)
    '''
    tags = {}
    for i in xrange(1, 11):
        url = base_url.format(page=i)
        res = urllib2.urlopen(url)
        if res.getcode() == 200:
            body = res.read()
            taglist = json.loads(body)
            tags.update({tag['id'].lower(): tag['id'] for tag in taglist})
        else:
            raise Exception('Qiita API呼び出しでエラーが発生しました。ステータスコード={}'.format(res.getcode()))
    return tags

 (2)_generate_tag()関数を呼び出し、ノートコンテンツからタグを生成します(生成方法は後述)。

 (3)生成したタグをJSON形式でファイルへ出力します。前述の通り、ノートへ付与するタグの確認のため、生成したタグをいったんファイル出力しています。内容が問題ないことを確認した上で実際にノートにタグを付与する処理を実行できるようにします。

 生成タグの保存形式は、1行1JSONのテキストファイルで、ノートのGUID、タイトル、タグのリストを保持しています。ファイル名は「note_tag.jsons」でPythonソースファイルと同じディレクトリへ出力されます。

JSON定義 ※見やすくするため整形しています。実際はJSON内で改行されていません。
{
    "note_guid": "d1df9a3c-91f2-491c-9ab4-a96b93a0827d",
    "tag_list": ["Azure", "Web"],
    "note_title": "Azure CLI Reference"
}

 (4)NoteStoreのfindNotesMetadata()は1回の呼び出しで取得できる件数が最大250件までのため、取得したメタデータリストから全体のノート件数と取得結果の開始インデックス、取得件数をもとに未取得のノートが存在するかを判定しています。次のノートが存在する場合はインデックスをインクリメントし、存在しない場合はループを抜けます。判定処理はhas_next_note()関数で実装しています。

後続ノート存在チェック関数
def has_next_note(note_meta_list):
    '''指定ノートメタデータリストの後続ノートが存在するかどうかを返す。

    Args:
        note_meta_list (str): ノートメタデータリスト

    Returns:
        後続ノートが存在する場合True、それ以外はFalse
    '''
    return note_meta_list.totalNotes - \
        (note_meta_list.startIndex + len(note_meta_list.notes)) > 0

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

著者プロフィール

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

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

あなたにオススメ

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