mixiの過去日記をevernoteに取り込む
投稿者:しんさん 2016/03/24

楽しかった思い出をありがとうmixi
「過去にmixiで書いた日記をevernoteに取り込みたいなぁ」と思ってネットで色々と調べてみたのだが、簡単にできるようなやり方がなかなか見つからない。
「無いなら自分でなんとかしよう」と自力で色々とがんばってみたところをせっかくなので記録として残しておこうと思う。
流れとしてはこんな感じになります。
- mixiの過去日記をhtmlとしてローカルに一旦すべて保存
- 保存した日記のhtmlをテキストファイル化
- evernoteのインポートフォルダの機能で取り込み
注意点として、一旦テキストファイルに落としているので、日記中に張られた画像やら動画やらの情報は失われてしまいます。
あまり時間をかけずにサクっと終わらせたかったので、この辺はトレードオフですかね。いつか誰かツールを作ってくれないかなと思う今日この頃です。
1の「過去日記の保存」ですが、こちらは「撤退!mixi」というソフトを使いました。
使い方は簡単なので割愛します。
2の「htmlテキスト化」がメインのトピックになります。
よさげなツールやらTIPSが見つからなかったので、pythonで簡単なスクリプトを書きました。
「BeautifulSoup」というHTMLパーサーを使ってhtmlを解析→テキスト化の流れです。
BeautifulSoupは事前にインストールしておく必要があります。
easy_install BeautifulSoup
BeautifulSoupの機能をふんだんに使ってテキストファイルを成型するのも良かったのですが、楽をしたかったので、
- 一旦タグを除去してテキスト化
- 必要な部分のみ切り出し
みたいな流れで処理しました。
タグを除去してテキスト化する方法は以下のサイトを参考にさせていただきました。
http://python.g.hatena.ne.jp/y_yanbe/20081025/1224910392
テキスト部のみとりだせたら、「あとはテキトーに正規表現でゴリゴリ」とか考えていたのですが、私のPythonの腕が未熟すぎて日本語混じりの正規表現をうまく使う事ができなかったので、最終的にはシンプルにテキストを一行ずつ頭からなめていって処理することにしました。
出来上がったコードはこんな感じです。過去に書いたコードをコピペで使いまわしたりして作ったので、きれいなものとは呼べませんがとりあえずは機能してくれたようです。
#!/usr/bin/env python
# coding: UTF-8
__version__ = "1.0.1"import sys, re, htmlentitydefs, string
def get_soup( html ) :
# HTMLソースをBeautifulSoupに渡す
from BeautifulSoup import BeautifulSoup
soup = BeautifulSoup( html )
return soup
def getNavigableStrings(soup):
from BeautifulSoup import BeautifulSoup, NavigableString, Declaration, Comment
if isinstance(soup, NavigableString):
if type(soup) not in (Comment, Declaration) and soup.strip():
yield soup
elif soup.name not in ('script', 'style'):
for c in soup.contents:
for g in getNavigableStrings(c):
yield g
def get_title(soup):
u"""
タイトルを取得するメソッド
"""
# BeutifulSoupが自動でUnicode型に変換して返してくれる。
websitetitle = soup.find( "title" ).string
# 文字参照をUnicodeに変換
websitetitle = getUnicodeByHtmlEntity( websitetitle )
return websitetitle
def getUnicodeByHtmlEntity( txt):
u"""
文字参照(文字実体参照・数値文字参照)をunicode型に変換するメソッド
"""
# ループで繰り返し使用するので正規表現をあらかじめコンパイルしておく
reference_regex = re.compile(u'&(#x?[0-9a-f]+|[a-z]+);', re.I)
num16_regex = re.compile(u'#x\d+', re.I)
num10_regex = re.compile(u'#\d+', re.I)
# 返却文字列を初期化
replaced_txt = u""
# 文字位置を初期化
character_position = 0
# txtの長さを取得
txt_length = len( txt )
# 検索開始位置をずらしながら、文字列を検索する
while character_position < txt_length :
match_obj = reference_regex.search( txt, character_position )
# 検索開始位置以降の文字列に、文字参照が見つかった場合
if match_obj :
replaced_txt += txt[character_position:match_obj.start()]
# 検索開始位置を後ろにずらす
character_position = match_obj.end()
# 正規表現にマッチする部分のみを取り出す
matched_string = match_obj.group(1)
# 文字実体参照(実体参照)をunicodeに置き換える
if matched_string in htmlentitydefs.name2codepoint.keys():
replaced_txt += unichr( htmlentitydefs.name2codepoint[ matched_string ])
# 数値文字参照(文字参照)処理部
elif num16_regex.match( matched_string ):
# 16進数により指定されている数値文字参照(文字参照)をunicodeに置き換える
replaced_txt += unichr( int( u"0"+matched_string[1:], 16 ))
elif num10_regex.match( matched_string ) :
# 10進数により指定されている数値文字参照(文字参照)をunicodeに置き換える
replaced_txt += unichr( int( matched_string[1:] ))
# 検索開始位置以降の文字列に、文字参照が見つからなかった場合
else :
# 検索開始位置以降の文字列を返却文字列の後ろに連結
replaced_txt += txt[character_position:]
# while文から抜けるよう、検索開始位置を指定
character_position = txt_length
# 文字参照をUnicodeに変換した結果を返却
return replaced_txt
def get_trimed_text(text,title):
trimed_text = u""
preflag=False
dateflag=False
commentflag=False
iineflag=False
for line in text.split("\n"):
line = line.strip()
if line == u"編集する":
preflag=True
elif line == u"コメントを書く":
break
elif preflag == True and dateflag == False:
trimed_text = line + " " + title
trimed_text += u"\n■■本文■■"
dateflag=True
elif line == u"コメント" and commentflag==False:
commentflag=True
elif line == u"イイネ!":
iineflag=True
elif iineflag:
if line ==u"(":
pass
elif line ==u")":
iineflag=False
else:
line = u"■■イイネ!("+ line + u")■■"
trimed_text = trimed_text + "\n" + line
elif line == u"コメント" and commentflag==True:
line = u"■■コメント■■"
trimed_text = trimed_text + "\n" + line
elif preflag == True and dateflag == True:
trimed_text = trimed_text + "\n" + line
return trimed_text
def main():
u"""
メインメソッド
"""
f = open(sys.argv[1])
html = f.read()
f.close()
html = html.decode( "euc-jp" , "ignore").encode( "utf-8")
soup = get_soup( html)
title = get_title( soup )
text = '\n'.join(getNavigableStrings(soup))
text = getUnicodeByHtmlEntity( text )
text = get_trimed_text(text,title)
fw = open(sys.argv[2],"w")
fw.write(text.encode( "shift-jis" , "ignore"))
fw.close()
if __name__=="__main__":
main()
sys.exit(0)
第一引数に元ファイル名、第二引数に出力先ファイル名を指定します。
1ファイルずつ処理する作りにしたので、てきとーにfor文でまわして処理しました。
最後にできあがったテキストファイルをevernoteに取り込むわけですが、「インポートフォルダ」という機能があるので、そちらを使うと便利でしょう。