岡村靖幸のWikipedia記事から人名を抽出する
最近スクレイピングしてないので素振りをすることにした。
今回は岡村靖幸のWikipedia記事内の経歴の項目における人名を抽出して眺めてみたい。
以下の流れで進める。
1. ページを眺めて、スクレイピングの対象とする文章が埋め込まれている場所を特定する。
2. rvestパッケージを使ってスクレイピングを実行する。
3. gooラボの固有表現抽出APIを使って人名を抽出する。
ページを眺めて、スクレイピングの対象とする文章が埋め込まれている場所を特定する。
まず岡村靖幸のページを眺めてみよう。
https://ja.wikipedia.org/wiki/%E5%B2%A1%E6%9D%91%E9%9D%96%E5%B9%B8
衝撃的なデビュー、瞬く間にスターダムにのし上がった後の没落、3度の逮捕からの不死鳥のごとき復活、様々な想いが私の胸を去来する。
さて、記事一覧において、各記事のURLが埋め込まれている構造(XPath/CSSセレクタ)についてはChromeの「検証ツール」を用いて取得する。
この情報は後ほどrvestパッケージを用いて各記事のURLを抽出する際に用いる。
たとえば「経歴」と書かれた部分のXPathを取得したい場合は、「経歴」の上で右クリックして「検証」を選ぶ。
そして、「経歴」という文字の上でさらに右クリックをしてCopy→Copy XPathを選ぶ。
すると以下のような文字列が取得できるだろう。これはこのページにおける「経歴」の位置をXpathで取得した結果である。
//*[@id=".E7.B5.8C.E6.AD.B4"]
該当部分における実際のHTMLドキュメントは以下のようになっている。
<span class="mw-headline" id=".E7.B5.8C.E6.AD.B4">経歴</span>
idはドキュメントの中で一意である。
ここではidが".E7.B5.8C.E6.AD.B4"という形で指定されている。
したがって、このidを指定するだけで位置が一意に決まる。これをXpathで指定すると先の例になる。
Xpathの指定方法については以下のチートシート等を参考にすると良い。
http://aoproj.web.fc2.com/xpath/XPath_cheatsheets_v2.pdf
さて、今回欲しいのは「経歴」のドキュメントのみである。
ソースを見る限り、「経歴」があらためてdivタグで囲われてidが振られているなんて便利なことはないなので地道にpタグ以下の文章の順番を確認して抽出していく必要がありそうである。
「経歴」の最初と最後、それぞれの文の上で検証ツールを通してXPathを取得すると以下の結果が得られる。
//*[@id="mw-content-text"]/p[4] //*[@id="mw-content-text"]/p[42]
rvestパッケージを使ってスクレイピングを実行する。
rvestパッケージによるスクレイピングは以下の手順で進める。
1. HTMLドキュメントの読み込み
2. 目標とする情報が埋め込まれている構造を指定して情報を抽出する(今回はXPathを利用する)
3. データを整形する
library("rvest") u <- "https://ja.wikipedia.org/wiki/%E5%B2%A1%E6%9D%91%E9%9D%96%E5%B9%B8" h <- read_html(u) txt <- h %>% html_nodes(xpath='//*[@id="mw-content-text"]/p') %>% html_text() txt <- txt[4:42] txt <- iconv(txt, from="UTF-8",to="CP932") txt <- paste(txt, collapse="")
HTMLドキュメントの読み込みにはread_html関数を用いる。
さらにhtml_nodes関数に先ほど取得したXPathを指定して情報を抽出する。
Xpathでは、Rの要素指定のように//*[@id="mw-content-text"]/p[4:42]のような指定はできないので、いったん要素の番号を指定せずに抽出し、Rのベクトルに変換した後あらためて要素の番号を指定している。
最後に文字コードを変換した後(使用OSがWindowsなので)、全ての文章をpaste関数で結合している。
これで目標とする部分が抽出できた。
gooラボの固有表現抽出APIを使って人名を抽出する
最後に収集したテキストから固有表現を抽出する。
今回はgooラボの固有表現抽出APIを利用する。
https://labs.goo.ne.jp/api/jp/named-entity-extraction/
利用にあたって登録が必要であり、この際Githubアカウントが求められる。
Githubアカウントさえ持っているなら登録は一瞬であり、即時にアプリケーションIDが発行される。
このアプリケーションIDをメモっておく。
なお、本APIを利用する際はクレジット画像の表示が必要とのことなので以下に表示する。
さて、固有表現抽出APIのようなwebAPIを使う際は、httrパッケージを用いる。
固有表現抽出APIの説明を確認すると、リクエスト先URLにhttps://labs.goo.ne.jp/api/entity
が、そしてリクエスト方法としてはapplication/x-www-form-urlencodedもしくはapplication/json形式でのPOSTを受け付けるとある。
また、リクエストパラメータとしてはapp_idとして先ほど取得したアプリケーションIDと、sentenceとして固有表現を抽出したい文章が必須であるとも書かれている。
以上の情報をhttrパッケージを用いて書くと以下のようなコードになる。
POSTメソッドなのでPOST関数を用いて、そのurl引数にリクエスト先URLを指定し、application/json形式でPOSTするためにencodeに"json"を指定している。
リクエストパラメータについてはbody引数に指定する。リクエストパラメータが複数ある場合はlistでまとめる。
library("httr") app_id <- "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" res <- POST(url="https://labs.goo.ne.jp/api/entity", encode="json", body=list(app_id=app_id,sentence=txt))
取得した結果にはステータス等様々な情報が含まれている。
固有表現抽出APIの適用結果のみ抽出したい場合はhttrパッケージのcontent関数を用いる。
content関数のtype引数に何も指定しないと、データのcontent-typeを見てよしなに変換してくれる。
今回はcontent-typeがapplication/jsonなのでjsonliteパッケージのfromJSON関数が適用されリストに変換される。
リストにはrequest_idと固有表現の抽出結果であるne_listが含まれているので、ne_listを抽出し、データフレームに変換し、列名を付与している。
固有表現にはART(人工物名)、ORG(組織名)、PSN(人名)、LOC(地名)、DAT(日付表現)、TIM(時刻表現)があり、今回は人名が欲しいのでPSNのみを抽出した。
library("dplyr") ne_list <- do.call("rbind",content(res)$ne_list) colnames(ne_list) <- c("word", "type") ne_list %>% filter(type=="PSN") %>% unique()
結果は以下の通りである。
> ne_list %>% filter(type=="PSN") %>% unique() word type 1 渡辺美里 PSN 2 吉川晃司 PSN 3 鈴木雅之 PSN 5 白井貴子 PSN 6 TM PSN 8 尾崎豊 PSN 9 岡村 PSN 13 金山一彦 PSN 14 チェッカーズ PSN 18 川本真琴 PSN 19 西田彩 PSN 20 黒田倫弘 PSN 21 朝日美穂 PSN 22 直枝政太郎 PSN 23 直枝政広 PSN 25 直枝 PSN 26 石野 PSN 29 小林武史 PSN 30 岡村靖幸 PSN 39 MEG PSN 42 大沢伸一 PSN 46 木村カエラ PSN 48 坂本龍一 PSN 49 小出祐介 PSN 50 久保 PSN 51 久保みね PSN
久保とか久保みねというのはテレビ番組「久保みねヒャダ」を抽出しそこなかった結果ですね。
それにしても川本真琴のデビュー曲「愛の才能」は後奏が突然岡村靖幸ソロになるんだよなあ、とか
尾崎豊と岡村靖幸がぐだぐだになりながら二人で歌っている広島のライブ映像は「若さ!!!!!!!!!!!!!」という感じで実に良いんだよなあ、とか
岡村靖幸がなぜか変名で作曲した川本真琴の「FRAGILE」は初めて聴いた時は「なげえ」としか思わなかったけど今聴くとなんだか胸に迫るんだよなあ、とか
様々に思い起こされる結果でした。