概要
自然言語処理の前処理を行う例。形態素解析と簡単なデータのクレンジングを行うもの。新聞記事の文章を前提とし、処理後のデータはWord2Vecに投入することを想定しています。
前段のデータ収集はこちらの記事参照。
Python Webスクレイピング実装例
環境
- Python3
- MeCab
- NEologd
実装
import sqlite3
import MeCab
import unicodedata
tagger = MeCab.Tagger(' -d /usr/lib/mecab/dic/mecab-ipadic-neologd/')
tagger.parse("")#バグ回避
MeCabを準備します。neologdのパスは環境に合わせてください。
最初に空文字をパースするのはおまじないです。
dbtext = sqlite3.connect("file:text.db", uri=True)
dbtext.row_factory = sqlite3.Row
dbword = sqlite3.connect("file:words.db", uri=True)
dbword.row_factory = sqlite3.Row
dbtextには元文章が入っている状態とします。dbwordには形態素解析後のデータを書き込むためのテーブルを事前に定義しておきます。
row_factoryを記載のように設定しておくと、select結果をdictのように参照できて便利です。
lasttime = ""
row = dbword.execute("select time from wordstbl order by time desc limit 1").fetchone()
if row is not None:
lasttime = row["time"]
バッチ処理としてcronでまわすことを想定しているので、処理済レコードを峻別するためのタイムスタンプを取得しておきます。
for row in dbtext.execute("select * from rawtext where time > ? order by time", (lasttime,)):
node = tagger.parseToNode(unicodedata.normalize("NFKC", row["rawtext"]))
separated_text = ""
while node:
features = node.feature.split(",")
if features[0] in ["名詞"] and features[1] not in ["接尾", "数", "接続詞的", "非自立", "代名詞"]:
separated_text = separated_text + " " + node.surface
node = node.next
insert = "INSERT INTO wordstbl(id, source, time, words) VALUES(?, ?, ?, ?)"
args = (row["id"], row["source"], row["time"], separated_text)
try:
dbword.execute(insert, args)
except sqlite3.Error as e:
print ('sqlite3:', e.args[0])
dbword.commit()
dbword.close()
dbtext.close()
生文章を取り出し、まずnormalizeで表記揺れを取り除きます。
形態素解析後、品詞でフィルタします。今回は名詞以外は除外し、かつ名詞の中でも接尾や非自立といった意味の薄いものは除外します。
SQLiteの全文検索
CREATE VIRTUAL TABLE wordstbl USING fts3(
id VARCHAR(36) NOT NULL PRIMARY KEY,
source VARCHAR(20),
time VARCHAR(20),
words VARCHAR(1024));
参考に書き込み先のテーブル定義です。
fts3により分かち書きされたテキストに対して効率的な全文検索が可能になります。
なお、ftsを使用する場合、全ての列が文字列型扱いになります。
SELECT * FROM wordstbl WHERE words MATCH 'hoge'
所見
生文章・分かち書き文章・単語ベクトルそれぞれ使いどころがあるので、中間データも利用しやすい形で保管しておくと後で後悔しません。再度集めるのも大変です。