2021/10/19 にWikipediaのhtmlダンプの配布がアナウンスされた [0]
というわけで、rakulangを使ってダンプデータから情報抽出をする方法を紹介する。
今回は概要文の抽出とInfoboxの特定要素の抽出を行った。
htmlダンプをダウンロードする
-
レジュームができるようにcオプションを指定してwgetでダウンロードする
- jaはjapanで日本語版の意味
- NSというのはnamespaceの意味。ns=0は通常のWikipedia記事のあるところを指している
$ wget -c https://dumps.wikimedia.org/other/enterprise_html/runs/20211018/jawiki-NS0-20211018-ENTERPRISE-HTML.json.tar.gz
- 解凍する
$ tar xvzf jawiki-NS0-20211018-ENTERPRISE-HTML.json.tar.gz
情報抽出
概要文を取得する
-
JSON::Tiny
とDOM::Tiny
を使う - 手順
-
-
JSON::Tiny
でarticle_body -> html
の位置の要素を取得する
-
from-json($item)<article_body><html>
で$item
番目の記事のarticle_body -> html
のところを取得する
-
-
-
DOM::Tiny
で概要文の位置を抜き出す
- sectionタグ内のpタグの中に概要文があるので
qq{section[data-mw-section-id="0"] p}
で位置を指定する。(qqについてはこちらを参照 [1]) - Infoboxの有無により取得するべきpタグの要素を変更する。Infoboxがある場合はpタグのidにmwBwやmwAwが入ったものを選択する[2]。ない場合は先頭を取得する
-
map
で中の要素をイテレーションしつつ$e.text
で文字列を取り出す。 - 最後は文字列の配列を
.join
で結合する
-
-
コード:
$ head -n 5 jawiki_0.ndjson | raku -e 'use JSON::Tiny; use DOM::Tiny; for $*IN.lines -> $item { my $dom = DOM::Tiny.parse(from-json($item)<article_body><html>); my @nodes = $dom.find(qq{section[data-mw-section-id="0"] p}); gather if ($_=@nodes.grep(-> $n { $n.attr("id") // "" eq any("mwBw", "mwAw") })).elems > 0 { take .head } else { take @nodes.head }.head.map(-> $e { $e.text }).join.say }'
結果:
三原鉱(みはらこう、 Miharaite)は、1980年に発表された新鉱物で、東北大学の鉱床学者苣木浅彦などにより、岡山県の三原鉱山から発見された。 化学組成はCu4FePbBiS6で、斜方晶系。産出地の鉱山名から命名された。
ウォーターワールド (Waterworld)
三宅 春楼(みやけ しゅんろう、正徳2年11月15日(1712年12月13日) - 天明2年10月9日(1782年11月13日))は江戸時代中期の儒学者。懐徳堂第3代学主。名は正誼、字は子和、通称は才次郎。初代学主三宅石庵の子に当たる。
駅前温泉(えきまえおんせん)
岡田 優希(おかだ ゆうき、1996年5月13日 - )は、神奈川県川崎市出身のサッカー選手。Jリーグ・FC町田ゼルビア所属。ポジションはフォワード。
Infoboxから呪術廻戦の作者を抜き出す
- ここでは大人気漫画『呪術廻戦』[3] を例題としてInfoboxからの情報抽出に取り組む。呪術廻戦の作者の名前を取得する。
$ grep --no-filename "同年35号より連載が再開" jawiki*json > jujutu.json
$ wc -l jujutu.json
1 jujutu.json
-
span -> mw-data
の箇所にInfoboxをJSON表現したものが格納されているらしい。今度はXML::XPath
を使ってこれを取得していく -
手順
-
-
qq{//descendant::span[@id="mwBg"]/@data-mw}
でidがmwBgになっている箇所 [4]のspanを取得する。@data-mw
で属性値が取れる
-
-
-
@data-mw
の属性値はJSON形式で格納されているため、from-json($xpath.find...
でJSONを取り込む
-
-
- 取り込んだJSONは
parts -> template -> params
の階層になっている。grepを利用して作者の要素が格納されている位置を割り出して、その後でその部分を取り出してsayする
- 取り込んだJSONは
-
コード:
$ cat jujutu.json | raku -e 'use JSON::Tiny; use XML::XPath; for $*IN.lines -> $item { my $xpath = XML::XPath.new(xml => from-json($item)<article_body><html>); from-json($xpath.find(qq{//descendant::span[@id="mwBg"]/@data-mw}).head)<parts>.grep(*<template><params>{"作者"}).head<template><params>{"作者"}.say }'
結果:
{wt => [[芥見下々]]}
おしまい
- 新規に配布が開始されたWikipediaのHTMLダンプについて、rakulangを用いた情報抽出の方法を紹介した
- 比較的重要な要素について仕様のページを探すことができなかった。本格的に使用するならもう少し調査が必要そう
脚注
[0] https://lists.wikimedia.org/hyperkitty/list/xmldatadumps-l@lists.wikimedia.org/thread/VV6JDNE5T4MBEIGYEPSAOUJKIMVPRSHH/
[1] https://docs.raku.org/language/quoting#index-entry-quote_qq-quote_%22_%22-Interpolation:_qq
[2] このページに少しだけIDの説明があるもののInfoboxとの関係は掲載されていなかった: https://www.mediawiki.org/wiki/Parsoid/MediaWiki_DOM_spec/Element_IDs
[3] https://ja.wikipedia.org/wiki/%E5%91%AA%E8%A1%93%E5%BB%BB%E6%88%A6
[4] もしかすると呪術廻戦以外の記事ではBw以外の文字列が入っているかも: https://www.mediawiki.org/wiki/Parsoid/MediaWiki_DOM_spec/Element_IDs