毎日テキストマイニング

180日間、毎日テキストマイニングをするブログです

2018/09/20【89日目】自然言語処理100本ノック、その7

25問目からです。 よくよく調べて見たら、?P< a >というのはグループ名の指定だったんですね。

(?P...) 正規表現の丸括弧に似ていますが、グループによってマッチした部分文字列はシンボリックグループ名 name によってアクセス可能になります。グループ名は有効な Python 識別子でなければならず、グループ名は 1 個の正規表現内で一意でなければなりません。シンボリックグループは番号付けもされており、番号によるアクセスも可能です。 名前付きグループは 3 つのコンテキストで参照できます。パターンが (?P['\"]).*?(?P=quote) (シングルまたはダブルクオートのどちらかにマッチ) の場合`:

となると、別に<>の中は< a >でも< hoge >でもよかったんですね。

しかし、25問目は答えが全くわからないのでググって解答を調べました。

import codecs
import json
import re
from pprint import pprint

def extract_base_info(text):
    m = re.search("{{基礎情報[^|]+\|(?P<info_body>.+?)\n}}", text, re.DOTALL)
    if not m:
        return {}

    info_body = m.group("info_body")

    info_dict = {}

    for item in info_body.split("\n|"):
        key, word = re.split(r"\s*=\s*", item, maxsplit=1)
        info_dict[key] = word

    return info_dict

text = extract("イギリス")
base_info = extract_base_info(text)

pprint(base_info, indent=4)

いまいちよくわかっていないので、上から見ていきます。 上からimport pprint pprintは辞書型やリスト型を綺麗に表示するための関数だそうです。

base_infoのみの場合

{'GDP/人': '36,727<ref name="imf-statistics-gdp" />',
 'GDP値': '2兆3162億<ref name="imf-statistics-gdp" />',
 'GDP値MER': '2兆4337億<ref name="imf-statistics-gdp" />',
 'GDP値元': '1兆5478億<ref name="imf-statistics-gdp">[http://www.imf.org/external/pubs/ft/weo/2012/02/weodata/weorept.aspx?pr.x=70&pr.y=13&sy=2010&ey=2012&scsm=1&ssd=1&sort=country&ds=.&br=1&c=112&s=NGDP%2CNGDPD%2CPPPGDP%2CPPPPC&grp=0&a= IMF>Data and Statistics>World Economic Out

print(base_info)の場合

{'略名': 'イギリス', '日本語国名': 'グレートブリテン及び北アイルランド連合王国', '公式国名': '{{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>英語以外での正式国名:<br/>\n*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}([[スコットランド・ゲール語]])<br/>\n*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}([[ウェールズ語]])<br/>\n*{{

pprint(base_info, indent=4)の場合

{   'GDP/人': '36,727<ref name="imf-statistics-gdp" />',
    'GDP値': '2兆3162億<ref name="imf-statistics-gdp" />',
    'GDP値MER': '2兆4337億<ref name="imf-statistics-gdp" />',
    'GDP値元': '1兆5478億<ref '
             'name="imf-statistics-gdp">[http://www.imf.org/external/pubs/ft/weo/2012/02/weod

確かに綺麗になっていますね。

次に行きます。

m = re.search("{{基礎情報[^|]+|(?P<info_body>.+?)\n}}", text, re.DOTALL)

ここのsearch関数。 serch関数は以下のような動きをするらしいです。

string を走査し、正規表現 pattern がマッチする最初の場所を探して、対応する match オブジェクト を返します。文字列内にパターンにマッチする場所が無い場合は None を返します; これは文字列内のある場所で長さが 0 のマッチが見つかった場合とは異なることに注意してください。

m = re.search("{{基礎情報[^|]+|(?P<info_body>.+?)\n}}", text, re.DOTALL)

ここの処置のre.DOTALLというもの。

re.DOTALL(原文) 特殊文字 '.' を、改行を含むどんな文字にもマッチさせます; このフラグがなければ、'.' は、改行 以外の 任意の文字とマッチします。 インラインフラグの (?s) に相当します。

要は.を指定すると、全部拾うということですかね? ちょっと返してみます。 re.DOTALLがある場合

<_sre.SRE_Match object; span=(16, 2535), match='{{基礎情報 国\n|略名 = イギリス\n|日本語国名 = グレートブリテン及び北アイルランド連>

ない場合。

{}

何も返ってこないですね。

それで、その正規表現を変数に入れて、for文に入れて回すのが正解らしいですね。

    info_body = m.group("info_body")

    info_dict = {}

    for item in info_body.split("\n|"):
        key, word = re.split(r"\s*=\s*", item, maxsplit=1)
        info_dict[key] = word

あー、なるほどなー、と思いつつも難しいですね。

今日の結果

今日のAKBの呟きは44件でした。 要約するとこんな感じです。

다시만나(SeeYouAgain)Produce48cover→#miyutube""明日17時〜ゆいりーさんとAKBcafeにお邪魔します?❤️お時間ある方はぜひ、待ってます^^#マジムリ学園""アンナさん公演終わりました?✨見に来てくださった方ありがとうございました^^4か月ぶりのアンナさん公演!凄く緊張しました?
"早起きです✌️おはよー!今日ほんとに雨??↑しつこいw""アンナさん公演オンデマンドでみてるよ?✨こみさんの華がすごい!""AKBINGO見てねー☺️☺️☺️""ついに明日が最終回のマジムリ学園『百合を咲かせるか?』舞台前にぜひチェックです\(^o^)/""おはようございます✨福岡聖菜のSHIBUYADESHINING10月2日第4回は、、アシスタントに山邊歩夢ちゃんゲストに交換留学中のお2人TPEのMobileさん、JKTのStefiさんどんな放送になるか楽しみす…""握手会ありがとうございました✨公演や舞台の話などみなさんと楽しい時間を作れて嬉しかったなぁ。54thシングル選抜発表。気持ちを伝えたくて配信してみてくれるそんなみんながいるからこそ頑張ることができます。まだまだな私だ…""9月のプロフィール画像は#じゃんけん大会の衣装にしました☺️いつも21日にアイコンを変わるけど今回はどうしてもこの衣装の写真にしたくて、2日遅く変わりました待ってくれてすみません?
の『210人の美女』に選んでいただきました?‍♀️ぜひチェックよろしくお願いします?‍♀️""54th『NOWAYMAN』の選抜メンバーに選んでいただきました?
'楽しい': 5, 'やばい': 3, '可愛い': 3, '嬉しい': 3, 'いい': 2, '遅い': 2, '痛い': 1, '明るい': 1, 'ない': 1, '凄い': 1, 'しつこい': 1, 'すごい': 1, 'よい': 1, '気持ちよい': 1
'公演': 13, 'さん': 10, '私': 10, 'アンナ': 8, '今日': 6, '選抜': 6, '日': 6, '楽しい': 5, 'メンバー': 5, 'ん': 5, 'チェック': 4, '方': 4, 'お願い': 4, 'アクシュカイ': 4, '月': 4, '人': 4, '千葉': 4, '髪型': 4, 
'する': 20, '公演': 13, 'さん': 10, '私': 10, 'アンナ': 8, '見る': 8, '今日': 6, '選抜': 6, '日': 6, '楽しい': 5, 'メンバー': 5, 'ん': 5, 'みる': 5, 'くださる': 5, 'てる': 5,

f:id:rimt:20180928234636p:plain