唯物是真 @Scaled_Wurm

プログラミング(主にPython2.7)とか機械学習とか

ニコニコ大百科のデータが公開されたらしい

ニコニコ大百科のデータが公開されてダウンロードできるようになったらしいので見てみました。
前に以下のような記事も書いてます。

元のデータはデータベースから持ってきているためか(?)、辞書の見出し語(記事タイトル)と説明(記事本文)が別のファイルになっていたりしてテキストのまま扱うには少し使いづらいです。

以下のようなCSV形式になっています。

■ファイル書式について
MySQL にて以下の設定で出力した CSVファイルとなっています。


FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '\\' LINES TERMINATED BY '\n'


文字コードUTF-8 です(表計算ソフト等で開くとエラーになる場合があります)。
記事本文と掲示板については改行が含まれています。


[記事ヘッダ]
ファイル名: head*.csv (6ファイル)
カラム: 記事ID, 記事タイトル, 記事ヨミ, 記事種類(a:単語,v:動画,i:商品,l:生放送), 記事作成日時
※ユーザページ、ユーザIDは削除されています。


[記事本文]
ファイル名: rev*.csv (50ファイル)
カラム: 記事ID, 記事本文, 記事更新日時
※記事更新日時が最新のものがデータ作成時点に表示される記事の内容となります


[掲示板]
ファイル名: res*.csv (6ファイル)
カラム: 記事ID, レス番号, レス投稿日時, レス本文

データの詳細な形式は各要素が"で囲まれていて、改行や"を\でエスケープしたCSVになっています。
記事本文やレス本文には途中に改行が含まれている場合があるため、Pythoncsvモジュールだと解析に失敗しました。
フォーマット自体は単純なので正規表現などで簡単に解析できます。

見出し語と読みを抽出

見出し語(記事タイトル)とその読みを抽出してみます。
head{年}.csv に含まれています。

perl -F, -lane 'print substr($F[1], 1, length($F[1]) - 2) . "\t" . substr($F[2], 1, length($F[2]) - 2)' head2014.csv > result.txt

出力例

カベキック	カベキック
電波°	デンパ
はっせーP	ハッセーピー
ニコニコ超パーティーⅢ	ニコニコチョウパーティースリー
サプレッサー	サプレッサー
コミックマーケット86	コミックマーケットハチジュウロク
100万再生達成動画の一覧(2013年分その4)	ヒャクマンサイセイタッセイドウガノイチランニセンジュウサンネンブンソノヨン
ながみー	ナガミー
古代魚	コダイギョ
WBC(艦これ)	イチジカンハンノアクム
200万再生達成動画の一覧(2013年分)	ニヒャクマンサイセイタッセイドウガノイチランニセンジュウサンネンブン
上田麗奈	ウエダレイナ
エリート塩	アセ
魔王龍 ベエルゼ	マオウリュウベエルゼ
宝札	ホウサツ

IMEとか形態素解析とか読み上げソフトの辞書の元として使えるかもしれません(上の出力例を見ればわかるようにノイズ(?)がかなりありますけど

ちなみにIME用の辞書はニコニコ大百科をクロールして作っている方がいたりします

MeCabの辞書作りで参考になりそうなURL

記事の本文を抽出

大雑把にHTMLタグも改行も全部取り除いて1行1記事として抽出。

import re
import sys

begin = re.compile(r'^"\d+","')
end = re.compile(r'","\d+"$')

buffer = ''

tag = re.compile(r'<.*?>')

for line in sys.stdin:
    line = line.rstrip('\n').replace('\\\\', '\\')
    match_b = begin.match(line)
    match_e = end.match(line)
    if match_b and match_e:
        print tag.sub('', line.split(',')[1].strip('"').rstrip('\\'))
    elif match_e:
        buffer += line.split(',')[0].rstrip('"').rstrip('\\')
        print tag.sub('', buffer)
        buffer = ''
    elif match_b:
        buffer += line.split(',')[1].lstrip('"').rstrip('\\')
    else:
        buffer += line.rstrip('\\')


抽出した本文をトピックモデルのLDAにかけてみました。
トピックモデルはどんなトピック(同じジャンルの単語のまとまりみたいなもの)がテキスト中に含まれているかを示してくれます。
過去の記事でも使っているようにライブラリのgensimを使って解析してみます。

本来はニコニコ特有の単語を辞書に追加して形態素解析すべきですが、今回は素のIPA辞書を使ってMeCab形態素解析しました。

具体的な手続きは上で抽出したテキストを"mecab -Owakati"で形態素分かち書きして以下のスクリプトを実行しました。
入力として使う分かち書き済みのテキストファイル名はスクリプトのfilename変数にハードコーディングしてあるので注意

import gensim

if __name__ == '__main__':
    filename = '20140102_wakati.txt'

    dictionary = gensim.corpora.dictionary.Dictionary()
    with open(filename) as f:
        for line in f:
            dictionary.add_documents([line.strip().split()])
    
    corpus = []
    dictionary.filter_extremes()
    with open(filename) as f:
        for line in f:
            corpus.append(dictionary.doc2bow(line.strip().split()))
    lda = gensim.models.ldamodel.LdaModel(corpus=corpus, num_topics=50, id2word=dictionary)
    for topic in lda.show_topics(-1):
        print topic

2014年1月と2月のデータ(2万件強)について、出現頻度が5回未満の単語と半分以上の記事に出現する単語は除いて、トピック数50で解析した結果を以下に示します。
まあまあうまくいっていそうですが、ガンダムがガンとダムに分かれていたり単語を区切りすぎてるのが結構あります。

うまくとれていそうなトピックの例

  • 0.015*放送 + 0.010*1 + 0.009*リスナー + 0.009*2 + 0.008*主 + 0.007*0 + 0.007*配信 + 0.007*! + 0.006*枠 + 0.006*ゲーム
  • 0.208*/ + 0.103*リンク + 0.039*ニュース + 0.027*VIP + 0.024*速報 + 0.018*- + 0.018*まとめ + 0.016*ゲーム + 0.015*アニメ + 0.010*ch
  • 0.045*駅 + 0.023*市 + 0.019*県 + 0.014*● + 0.012*線 + 0.010*町 + 0.008*JR + 0.008*鉄道 + 0.007*バス + 0.007*-
  • 0.054*艦 + 0.017*これ + 0.013*駆逐 + 0.011*型 + 0.010*艦隊 + 0.008*第 + 0.007*娘 + 0.007*隊 + 0.007*空母 + 0.006*提督
  • 0.036*- + 0.013*機 + 0.009*ガン + 0.007*ダム + 0.006*戦闘 + 0.005*機体 + 0.005*第 + 0.005*軍 + 0.005*機動 + 0.004*国
  • 0.020*ポケモン + 0.016*技 + 0.016*タイプ + 0.014*系 + 0.008*世代 + 0.008*● + 0.007*車 + 0.007*: + 0.006*特性 + 0.005*ず
  • 0.014*モンスター + 0.013*効果 + 0.013*. + 0.012*カード + 0.010*- + 0.009*攻撃 + 0.008*No + 0.007*ランク + 0.006*登場 + 0.006*ナンバーズ
  • 0.067*→ + 0.036*○ + 0.030*ちゃん + 0.027*さん + 0.027*P + 0.013*アイドル + 0.012*マスター + 0.012*プロデューサー + 0.011*@ + 0.010*:
  • 0.027*曲 + 0.026*P + 0.025*ミク + 0.021*初音 + 0.021*音 + 0.020*VOCALOID + 0.012*オリジナル + 0.011*- + 0.009*投稿 + 0.009*鏡

結果の全体

0.018*: + 0.007*話 + 0.006*登場 + 0.005*魔法 + 0.005*第 + 0.005*『 + 0.005*』 + 0.004*少女 + 0.004*神 + 0.004*;&
0.029*一覧 + 0.017*☆ + 0.011*お + 0.010*加筆 + 0.009*記事 + 0.008*絵 + 0.007*俺 + 0.007*カキコ + 0.007*要 + 0.006*!
0.148*第 + 0.103*回 + 0.059*~ + 0.034*| + 0.013*: + 0.012*0 + 0.011*/ + 0.010*- + 0.008*さん + 0.007*14
0.045*/ + 0.041*東方 + 0.037*: + 0.026*. + 0.022*0 + 0.021*卓 + 0.015*GM + 0.011*ワールド + 0.011*魔 + 0.011*ソード
0.014*主義 + 0.008*… + 0.006*帝国 + 0.005*力 + 0.005*武器 + 0.005*PC + 0.005*> + 0.004*マルクス + 0.004*もの + 0.004*数
0.035*超 + 0.016*ニコニコ + 0.011*! + 0.011*会議 + 0.010*: + 0.010*募集 + 0.009*ます + 0.009*み + 0.009*█ + 0.009*ヽ
0.020*実況 + 0.017*. + 0.016*2013 + 0.016*! + 0.015*/ + 0.013*生放送 + 0.013*ニコニコ + 0.011*ゲーム + 0.010*~ + 0.007*『
0.026*: + 0.025*CV + 0.012*: + 0.009*- + 0.008*話 + 0.008*年生 + 0.006*第 + 0.004*アニメ + 0.004*『 + 0.004*』
0.014*モンスター + 0.013*効果 + 0.013*. + 0.012*カード + 0.010*- + 0.009*攻撃 + 0.008*No + 0.007*ランク + 0.006*登場 + 0.006*ナンバーズ
0.022*- + 0.022*. + 0.017*『 + 0.015*』 + 0.012*アニメ + 0.007*~ + 0.006*ガン + 0.006*戦士 + 0.006*ダム + 0.005*!
0.242*/ + 0.051*. + 0.030*- + 0.014*ver + 0.012*枠 + 0.007*12 + 0.007*~ + 0.006*11 + 0.006*10 + 0.005*No
0.103*# + 0.065*■ + 0.057*全 + 0.021*~ + 0.010*- + 0.010*! + 0.008*一覧 + 0.007*ー + 0.007*!! + 0.006*:
0.029*- + 0.021*曲 + 0.020*. + 0.010*' + 0.007*楽曲 + 0.007*~ + 0.006*収録 + 0.006*あんぱん + 0.005*/ + 0.005*☆
0.054*[ + 0.049*] + 0.018*R + 0.014*アイドル + 0.014*SR + 0.008*歳 + 0.005*ゆ + 0.004*登場 + 0.004*… + 0.004*特訓
0.071*分 + 0.048*時 + 0.024*時間 + 0.023*sm + 0.017*01 + 0.016*】 + 0.016*【 + 0.014*02 + 0.013*03 + 0.013*08
0.035*! + 0.034*さん + 0.019*時 + 0.018*だっ + 0.016*相手 + 0.016*名前 + 0.014*対戦 + 0.014*ん + 0.012*ー + 0.011*?
0.015*放送 + 0.010*1 + 0.009*リスナー + 0.009*2 + 0.008*主 + 0.007*0 + 0.007*配信 + 0.007*! + 0.006*枠 + 0.006*ゲーム
0.052*カード + 0.016*デッキ + 0.016*王 + 0.011*枚 + 0.010*闇 + 0.010*遊戯 + 0.009*使用 + 0.008*ネッキー + 0.008*デュエル + 0.007*龍
0.018*ゲーム + 0.015*シリーズ + 0.009*版 + 0.009*』 + 0.008*『 + 0.007*星 + 0.007*キャラクター + 0.006*マリオ + 0.006*カービィ + 0.006*登場
0.054*艦 + 0.017*これ + 0.013*駆逐 + 0.011*型 + 0.010*艦隊 + 0.008*第 + 0.007*娘 + 0.007*隊 + 0.007*空母 + 0.006*提督
0.013*ドグマ + 0.012*” + 0.012*1 + 0.011*2 + 0.009*放送 + 0.008*“ + 0.008*0 + 0.007*! + 0.007*』 + 0.007*『
0.020*ポケモン + 0.016*技 + 0.016*タイプ + 0.014*系 + 0.008*世代 + 0.008*● + 0.007*車 + 0.007*: + 0.006*特性 + 0.005*ず
0.067*→ + 0.036*○ + 0.030*ちゃん + 0.027*さん + 0.027*P + 0.013*アイドル + 0.012*マスター + 0.012*プロデューサー + 0.011*@ + 0.010*:
0.024*MMD + 0.022*音 + 0.021*モデル + 0.021*. + 0.020*式 + 0.017*sm + 0.012*杯 + 0.012*/ + 0.010*〜 + 0.010*-
0.015*. + 0.010*ます + 0.006*ニコニコ + 0.006*: + 0.006*可能 + 0.006*コメント + 0.005*場合 + 0.005*削除 + 0.005*記事 + 0.005*無料
0.036*- + 0.013*機 + 0.009*ガン + 0.007*ダム + 0.006*戦闘 + 0.005*機体 + 0.005*第 + 0.005*軍 + 0.005*機動 + 0.004*国
0.062*[ + 0.053*] + 0.047*/ + 0.036*- + 0.018*# + 0.017*: + 0.016*. + 0.015*公開 + 0.014*: + 0.011*記事
0.077*gt + 0.070*: + 0.069*;& + 0.045*lt + 0.027*- + 0.022*=\" + 0.018*;/ + 0.018*, + 0.017*style + 0.014*td
0.018*! + 0.009*変身 + 0.008*獣 + 0.008*: + 0.008*仮面ライダー + 0.008*ロック + 0.008*電 + 0.007*戦隊 + 0.007*鎧 + 0.006*武
0.029*: + 0.019*配信 + 0.018*枠 + 0.017*【 + 0.017*】 + 0.015*/ + 0.014*, + 0.010*雑談 + 0.009*! + 0.008*放送
0.054*sm + 0.033*/ + 0.019*im + 0.019*配布 + 0.018*※ + 0.012*え + 0.010*静 + 0.010*画 + 0.010*モデル + 0.010*ま
0.023*. + 0.011*0 + 0.010*- + 0.010*4 + 0.009*試合 + 0.009*戦 + 0.008*5 + 0.007*位 + 0.006*選手 + 0.006*:
0.063*・ + 0.016*オ + 0.015*タ + 0.012*mylist + 0.011*兄 + 0.011*part + 0.010*マ + 0.010*再生 + 0.010*万 + 0.009*より
0.208*/ + 0.103*リンク + 0.039*ニュース + 0.027*VIP + 0.024*速報 + 0.018*- + 0.018*まとめ + 0.016*ゲーム + 0.015*アニメ + 0.010*ch
0.011*マルクス + 0.010*日本 + 0.005*資本 + 0.005*社会 + 0.005*あっ + 0.004*労働 + 0.004*経済 + 0.004*- + 0.004*家 + 0.003*現在
0.086*: + 0.059*, + 0.046*話 + 0.038*~ + 0.028*放送 + 0.027*00 + 0.018*)  + 0.018*2013 + 0.017*分 + 0.015*コメ
0.020*話 + 0.019*登場 + 0.018*プロ + 0.017*選手 + 0.016*初 + 0.015*野球 + 0.014*所属 + 0.008*アイドル + 0.008*投手 + 0.007*手
0.027*曲 + 0.026*P + 0.025*ミク + 0.021*初音 + 0.021*音 + 0.020*VOCALOID + 0.012*オリジナル + 0.011*- + 0.009*投稿 + 0.009*鏡
0.007*これ + 0.006*… + 0.005*』 + 0.005*『 + 0.005*もの + 0.005*ば + 0.005*う + 0.004*たり + 0.004*なく + 0.004*まで
0.016*み + 0.015*歌っ + 0.014*猫 + 0.014*. + 0.011*実況 + 0.010*トーリ + 0.009*96 + 0.009*~ + 0.008*投稿 + 0.007*&
0.007*選手 + 0.006*監督 + 0.006*テーマ + 0.005*年度 + 0.005*大 + 0.004*歳 + 0.004*現役 + 0.004*コーチ + 0.004*チャンス + 0.004*OB
0.011*仲間 + 0.010*ユニット + 0.009*攻撃 + 0.009*100 + 0.008*できる + 0.008*姉 + 0.008*貴 + 0.008*加入 + 0.008*クエスト + 0.007*クッキー
0.016*放送 + 0.015*アニメ + 0.013*- + 0.011*: + 0.010*番組 + 0.008*~ + 0.007*2014 + 0.007*『 + 0.007*』 + 0.007*!
0.104*】 + 0.102*【 + 0.028*作品 + 0.027*達成 + 0.017*ミリオン + 0.016*氏 + 0.016*み + 0.015*投稿 + 0.014*実況 + 0.011*歌っ
0.057*/ + 0.027*2013 + 0.020*アイドル + 0.016*開始 + 0.015*ガチャ + 0.013*限定 + 0.012*! + 0.012*期間 + 0.011*2012 + 0.010*開催
0.045*駅 + 0.023*市 + 0.019*県 + 0.014*● + 0.012*線 + 0.010*町 + 0.008*JR + 0.008*鉄道 + 0.007*バス + 0.007*-
0.015*氏 + 0.012*あっ + 0.011*ぶどう + 0.010*ぱん + 0.008*攻撃 + 0.006*技 + 0.005*. + 0.005*なお + 0.004*! + 0.004*Lv
0.047*4 + 0.046*5 + 0.037*6 + 0.036*7 + 0.030*8 + 0.024*9 + 0.024*10 + 0.016*11 + 0.015*- + 0.014*12
0.015*プリキュア + 0.012*: + 0.010*! + 0.008*シリーズ + 0.007*作品 + 0.006*『 + 0.006*映画 + 0.005*作 + 0.005*― + 0.005*役
0.031*百 + 0.020*週 + 0.019*週刊 + 0.018*Vol + 0.017*動 + 0.015*アイドルマスターランキング + 0.015*][ + 0.014*音源 + 0.010*音 + 0.008*UTAU