言語処理100本ノック ー第3章ー

この記事では、言語処理100本ノック第2章の解説に引き続き、言語処理100本ノック第3章の解説を行っていきます。 第3章では、正規表現ライブラリやメタ文字を使用して、wikipediaの記事を処理していきます。 それでは、 第3章の問題を解きましたので、処理の流れとポイントを踏まえて、解説していきます。

問題と解説

Wikipediaの記事を以下のフォーマットで書き出したファイルjawiki-country.json.gzがある.

  • 1行に1記事の情報がJSON形式で格納される
  • 各行には記事名が”title”キーに,記事本文が”text”キーの辞書オブジェクトに格納され,そのオブジェクトがJSON形式で書き出される
  • ファイル全体はgzipで圧縮される

以下の処理を行うプログラムを作成せよ.

Setup
  • 正規表現のメタ文字一覧:以下の正規表現の問題で使用するメタ文字の一覧。この一覧を参照して、問題を解く。

JSONデータの読み込み

問20

Wikipedia記事のJSONファイルを読み込み,「イギリス」に関する記事本文を表示せよ.問題21-29では,ここで抽出した記事本文に対して実行せよ.

解答

【コード】

【出力結果】

一部省略
解説

【処理の流れ】

  • pandasをimportする。
  • jsonファイルを読み込み、DataFrameに変換する。
  • DataFrameの”title”列データが”イギリス”である行だけを取得する。
  • uk_df[“text”]列のデータを配列(numpy.ndarray)に変換し出力する。

【ポイント】

  • pd.read_json()関数:第一引数に、Json形式の文字列を渡すことで、文字列がpd.DataFrameに変換される。JSON Linesで書かれたファイルを読み込みたい場合は、lines=Trueを指定する。
  • DataFrameに比較演算子を使用する:DataFrameに比較演算子を使用すると、データをbool型として出力する。Tureとなる場所をDataFrameに指定することで、その行のデータを取得することができる。
  • DataFrame.values属性(Series.values):pandasのDataFrameとSeriesオブジェクトに対して、values属性を指定すると、NumPy配列(ndarry)に変換できる。

カテゴリ名を含む行を抽出

問21

記事中でカテゴリ名を宣言している行を抽出せよ.

解答

【コード】

【出力結果】

解説

【処理の流れ】

  • reをimportする。
  • 20.で取得したデータの要素数と、データ型を確認する。(コメント)
  • split(“\n”)で、uk_dfの要素を改行文字で区切り、re.search(“Category”, text)で、”Category”が書かれている行を出力する。

【ポイント】

  • 「カテゴリ名を宣言している行」というのは、Categoryから始まる行のこと。
  • re標準モジュール:正規表現操作を行うモジュール。
  • str.split()メソッド:引数で指定した文字列で、strオブジェクトを分割する。戻り値は、list型。デフォルトで改行文字で区切るので、”\n”を指定しなくてもいい。
  • re.search()関数:第1引数は、文字列またはstr型のメタ文字。第2引数は、検索対象となるstrオブジェクトを指定する。戻り値は、match型。マッチする文字列が複数あった場合でも、最初にマッチする文字列しか返さないことに注意する。
  • uk_dfの要素数は1、データ型はstr。

カテゴリ名の抽出

問22

記事のカテゴリ名を(行単位ではなく名前で)抽出せよ.

解答

【コード】

【出力結果】

解説

【処理の流れ】

  • 前半は、問21と同じなので説明を省略する。
  • replace()を使用して、カテゴリ名以外の余計な文字列を削除して、出力する。

【ポイント】

セクション構造

問23

記事中に含まれるセクション名とそのレベル(例えば”== セクション名 ==”なら1)を表示せよ.

解答

【コード】

【出力結果】

以下省略
解説

【処理の流れ】

  • イギリスデータの要素を空白文字で区切り、反復させる 。
  • 正規表現のメタ文字を使用して、セクション名をサーチする
  • “=”の数ごとのレベルを取得し、セクション名とレベルを出力する

【ポイント】

  • シーケンス型共通のcount()メソッド:引数に指定した要素をカウントする

ファイル参照の抽出

問24

記事から参照されているメディアファイルをすべて抜き出せ.

解答

【コード】

【出力結果】

以下省略
解説

【処理の流れ】

  • イギリスデータを見ると、「ファイル:」の形でメディアファイルが記述されているので、findall(“ファイル:(.+?)|”, t_df[0])を使用する。
  • 最後は、m_fileリストの要素を改行文字で、連結させる。

【ポイント】

  • メディアファイル
  • re.findall():マッチするすべての文字列をlist型にして返す。リストの要素は、strオブジェクト(matchオブジェクトではない事に注意)。

テンプレートの抽出

問25

記事中に含まれる「基礎情報」テンプレートのフィールド名と値を抽出し,辞書オブジェクトとして格納せよ.

解答

【コード】

【出力結果】

一部省略
解説

【処理の流れ】

  • 空のdictを作成し、イギリスデータの要素を改行文字で区切る。
  • 「基本情報」テンプレートのフィールド名と値の形に注目して、正規表現のメタ文字を記述する。
  • if re.search(“|(.+?)\s=\s*(.+)”, text):でTrueになった値にたいして、キーと値を指定し、dictに追加する。

【ポイント】

  • 基礎情報テンプレートの「|フィールド名 = 値」で記述されている箇所を抽出する。
  • re.search()メソッド:戻り値は、match型。インデックスを指定することで、このmatchオブジェクトから3種類の値を取得できる。インデックス0なら、マッチしたオブジェクトが存在する行、1ならマッチしたオブジェクトだけ、2ならマッチしたオブジェクト以外の値を返す。

強調マークアップの除去

問26

25の処理時に,テンプレートの値からMediaWikiの強調マークアップ(弱い強調,強調,強い強調のすべて)を除去してテキストに変換せよ(参考: マークアップ早見表).

解答

【コード】

【出力結果】

一部省略
解説

【処理の流れ】

  • 前半は、問25と同じなので説明を省略する。
  • re.sub(“‘{2,}(.+?)'{2,}”, “\1”, text)を使用して、マッチした文字列を(.+?)で置換する。

【ポイント】

  • 例)「”’グレートブリテン及び北アイルランド連合王国”’」を「グレートブリテン及び北アイルランド連合王国」に変更する。
  • re.sub():第一引数で、指定した正規表現とマッチした文字列を第二引数で、指定した文字列に置換する。戻り値は、str型。
  • re.sub()メソッドの引数”\\1″:第一引数のメタ文字の一部を()で囲むと、マッチしたオブジェクトを()内の文字列で置換する。

 内部リンクの除去

問27

26の処理に加えて,テンプレートの値からMediaWikiの内部リンクマークアップを除去し,テキストに変換せよ(参考: マークアップ早見表).

解答

【コード】

【出力結果】

以下省略
解説

【処理の流れ】

  • 前半は、問26と同じなので説明を省略する。
  • 26.で協調マークアップの除去を行ったように、内部リンクも除去して出力する。

【ポイント】

  • ([[スコットランド・ゲール語]])を(スコットランド・ゲール語)に変更する。
  • re.sub()を用いて、内部リンクマークを(.+?)に置換する。つまり、内部リンクマークを削除する。

MediaWikiマークアップの除去

問28

27の処理に加えて,テンプレートの値からMediaWikiマークアップを可能な限り除去し,国の基本情報を整形せよ.

解答

【コード】

【出力結果】

以下省略
解説

【処理の流れ】

  • 前半は、問27と同じなので説明を省略する。
  • マークアップ早見表を確認し、該当するマークアップをre.sub()で削除していく。

【ポイント】

国旗画像のURLを取得する

問29

テンプレートの内容を利用し,国旗画像のURLを取得せよ.(ヒント: MediaWiki APIimageinfoを呼び出して,ファイル参照をURLに変換すればよい)

解答

【コード】

【出力結果】

解説

【処理の流れ】

  • S.get(url=URL, params=PARAMS)にURLとparamsを指定して、URLの情報を取得する。
  • R.json()で、取得した情報をJSON形式に変換する。
  • [“query”][“pages”]の要素に国旗画像のURLが含まれているため、[“imageinfo”]のキーを指定して、値(国旗画像のURL)を取得する。

【ポイント】

  • imageinfoのPythonコードを参照する。
  • requestsモジュール:HTTP通信を行うためのライブラリ。
  • requests.get()メソッド:URL先の情報を取得する。戻り値は、Response型。
  • get()のparamsを指定すると、URLにクエリストリングとして指定される。今回は、URLを取得したいので、”iiprop”:”url”を指定。”titles”:”File(国旗画像のファイル名)”を指定することで、指定したファイル名を取得する。
  • Response.json()メソッド:取得した情報をJSON形式で取得する。

おわりに

以上が、言語処理100本ノック第3章の解説になります。正規表現のメタ文字については、最初は理解する事に時間がかかるかもしれませんが、第3章を通して徐々に理解していくと思います。実装方法は、一通りではないので、自分なりのコードで挑戦してみてはいかかでしょうか。次は、言語処理100本ノック第4章の解説を行っていきます。

K.Y

タイトルとURLをコピーしました