ノートコンテンツからタグを生成・付与するプログラムの実装(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仕様を確認してください。
# 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ソースファイルと同じディレクトリへ出力されます。
{
"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
