LoginSignup
1
2

More than 1 year has passed since last update.

WikipediaのHTMLダンプからワンライナーで情報抽出する

Last updated at Posted at 2021-10-31

2021/10/19 にWikipediaのhtmlダンプの配布がアナウンスされた [0]
というわけで、rakulangを使ってダンプデータから情報抽出をする方法を紹介する。
今回は概要文の抽出とInfoboxの特定要素の抽出を行った。

htmlダンプをダウンロードする

  • https://dumps.wikimedia.org/other/enterprise_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::TinyDOM::Tinyを使う
  • 手順
    • 1. JSON::Tinyarticle_body -> html の位置の要素を取得する
      • from-json($item)<article_body><html>$item番目の記事のarticle_body -> htmlのところを取得する
    • 2. 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を使ってこれを取得していく

  • 手順

    • 1. qq{//descendant::span[@id="mwBg"]/@data-mw} でidがmwBgになっている箇所 [4]のspanを取得する。@data-mwで属性値が取れる
    • 2. @data-mwの属性値はJSON形式で格納されているため、from-json($xpath.find... でJSONを取り込む
    • 3. 取り込んだJSONはparts -> template -> paramsの階層になっている。grepを利用して作者の要素が格納されている位置を割り出して、その後でその部分を取り出してsayする

コード:

$ 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

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2