- Rでスクレイピングするときの基本的な手順
- Rでネット上のデータをダウンロードするときの方法
についてメモ。
やりたいこと
例えば,以下のサイトで
http://www.soumu.go.jp/senkyo/senkyo_s/data/shugiin46/shikuchouson.html
- 「北海道」から「沖縄県」の各リンクをたどって,
- 各リンク先のすべてのxlsファイルのリンクを取得し,
- すべてのxlsファイルをダウンロードしたい
という状況を考えます。
1.「北海道」から「沖縄県」の各リンクをたどって,
2.各リンク先のすべてのxlsファイルのリンクを取得
するところまでをスクレイピングで行います
library(tidyverse)
library(readr)
library(rvest)
1. htmlの読み込み
read_html()
に目的のサイトのURLを入れ,htmlを取得します
html_data = read_html("http://www.soumu.go.jp/senkyo/senkyo_s/data/shugiin46/shikuchouson.html")
html_data
> # 中身の表示
> html_data
{xml_document}
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
[1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\n<meta http-equiv="Content-Style-Type" content="text/ ...
[2] <body>\r\n<a name="pTop" id="pTop"></a>\r\n<noscript><div id="nsBelt"><div class="nsMsg">すべての機能をご利用いただくにはJavascriptを有効にして下さい。</di ...
2. 目的のタグ・URLを抽出
html_nodes()
でcssやxpathを指定して目的のタグを抽出できます
div要素を抽出
今回の目的のサイトの,各都道府県のページへのリンクがある領域はbodyArea
というidのdivタグの中にあるので,まずbodyArea
の中の情報だけを取り出してみます。
Google Chromeの「検証(Ctrl+Shift+I)」から目的のタグで右クリックしてメニューを開き,「Copy XPath」をクリックすればxpathが入手できるので,Rに貼り付けます
bodyArea = html_data %>% html_nodes(xpath = '//*[@id="bodyArea"]')
bodyArea
> bodyArea
{xml_nodeset (1)}
[1] <div id="bodyArea">\r\n<h4>市区町村別得票数</h4>\r\n\r\n\r\n<ul class="inline arrowlink">\n<li><a href="/senkyo/senkyo_s/data/shugiin46/s ...
a要素を抽出
次に,「北海道」から「沖縄県」までの各ページのURLには"shikuchouson"という言葉が入っているようなので,cssセレクタで「リンクタグ(<a></a>
)でhrefに"shikuchouson"を含むもの」という意味のa[href *= 'shikuchouson']
という条件を指定して抽出します。
a_tags = bodyArea %>% html_nodes(css = "a[href *= 'shikuchouson']")
a_tags
> a_tags
{xml_nodeset (47)}
[1] <a href="/senkyo/senkyo_s/data/shugiin46/shikuchouson_01.html">北海道</a>
[2] <a href="/senkyo/senkyo_s/data/shugiin46/shikuchouson_02.html">青森県</a>
(中略)
...
URLを抽出
html_attr()
を使ってaタグのhref属性に指定されている文字列を取得し,各ページへのURLを取得します
urls = a_tags %>% html_attr("href")
urls
> urls
[1] "/senkyo/senkyo_s/data/shugiin46/shikuchouson_01.html" "/senkyo/senkyo_s/data/shugiin46/shikuchouson_02.html"
[3] "/senkyo/senkyo_s/data/shugiin46/shikuchouson_03.html" "/senkyo/senkyo_s/data/shugiin46/shikuchouson_04.html"
(以下略)
リンクテキストを抽出
html_text()
を使ってタグのテキスト部の文字列を取得します。
texts = a_tags %>% html_text()
texts
> texts
[1] "北海道" "青森県" "岩手県" "宮城県" "秋田県" "山形県" "福島県" "茨城県" "栃木県" "群馬県" "埼玉県" "千葉県"
[13] "東京都" "神奈川県" "新潟県" "富山県" "石川県" "福井県" "山梨県" "長野県" "岐阜県" "静岡県" "愛知県" "三重県"
(以下略)
ループ処理
以上の基礎知識を組み合わせ,47都道府県分をループするように処理を組みます。
前節で47都道府県分の各県のページへのURLとテキストを入手したので,あとはその先のページでhrefに"xls"を含む要素のURLを抽出したりすればいいだけです。
for(i in 1:length(urls)){
html_i = read_html(str_c("http://www.soumu.go.jp",urls[i]))
urls_i = html_i %>% html_nodes(css = ".linklist") %>%
html_nodes(css = "a[href *= 'xls']") %>% html_attr("href")
texts_i = html_i %>% html_nodes(css = ".linklist") %>%
html_nodes(css = "a[href *= 'xls']") %>% html_text()
url_df_i = data_frame(url = urls_i, text = texts_i, prefName = texts[i])
if(i == 1) url_df = url_df_i
if(i != 1) url_df = bind_rows(url_df, url_df_i)
Sys.sleep(0.5)
}
url_df %>% head()
> url_df %>% head()
# A tibble: 6 x 3
url text prefName
<chr> <chr> <chr>
1 /main_content/000205177.xls 小選挙区 北海道
2 /main_content/000205178.xls 比例代表 北海道
3 /main_content/000205179.xls 小選挙区 青森県
4 /main_content/000205180.xls 比例代表 青森県
5 /main_content/000205181.xls 小選挙区 岩手県
6 /main_content/000205182.xls 比例代表 岩手県
各xlsファイルのURLと名称に関するテキストが取得できました。
②xlsファイルのダウンロード
3.すべてのxlsファイルをダウンロード
に取り組みます。
download.file(url, destfile)
で指定したURLのファイルを,指定したパス(ファイル名)で保存します。
base_url = "http://www.soumu.go.jp/"
download_folder = str_c("./xls")
dir.create(download_folder)
file_name = str_c(url_df[["prefName"]],"_",url_df[["text"]])
url = str_c(base_url,"/",url_df[["url"]])
for(i in 1:length(url)){
download.file(url = url[i],
destfile = str_c(download_folder,"/",file_name[i],".xls"),
mode = "wb")
Sys.sleep(0.5)
}
list.files(download_folder)
> list.files(download_folder)
[1] "愛知県_小選挙区.xls" "愛知県_比例代表.xls" "愛媛県_小選挙区.xls" "愛媛県_比例代表.xls" "茨城県_小選挙区.xls"
[6] "茨城県_比例代表.xls" "岡山県_小選挙区.xls" "岡山県_比例代表.xls" "沖縄県_小選挙区.xls" "沖縄県_比例代表.xls"
(以下略)
ダウンロードしたxlsファイルは{readxl}で前処理していきます(この部分は長くなるので書きませんが)。
まとめ
上記の処理をまとめると,以下のようになります。
library(tidyverse)
library(readr)
library(rvest)
html_data = read_html("http://www.soumu.go.jp/senkyo/senkyo_s/data/shugiin46/shikuchouson.html")
bodyArea = html_data %>% html_nodes(xpath = '//*[@id="bodyArea"]')
a_tags = bodyArea %>% html_nodes(css = "a[href *= 'shikuchouson']")
urls = a_tags %>% html_attr("href")
texts = a_tags %>% html_text()
for(i in 1:length(urls)){
html_i = read_html(str_c("http://www.soumu.go.jp",urls[i]))
urls_i = html_i %>% html_nodes(css = ".linklist") %>%
html_nodes(css = "a[href *= 'xls']") %>% html_attr("href")
texts_i = html_i %>% html_nodes(css = ".linklist") %>%
html_nodes(css = "a[href *= 'xls']") %>% html_text()
url_df_i = data_frame(url = urls_i, text = texts_i, prefName = texts[i])
if(i == 1) url_df = url_df_i
if(i != 1) url_df = bind_rows(url_df, url_df_i)
Sys.sleep(0.5)
}
base_url = "http://www.soumu.go.jp/"
download_folder = str_c("./xls")
dir.create(download_folder)
file_name = str_c(url_df[["prefName"]],"_",url_df[["text"]])
url = str_c(base_url,"/",url_df[["url"]])
for(i in 1:length(url)){
download.file(url = url[i],
destfile = str_c(download_folder,"/",file_name[i],".xls"),
mode = "wb")
Sys.sleep(0.5)
}
list.files(download_folder)
参考文献
石田さんのこの本は基礎的なことから幅広く書いてあってスクレイピングするとき手元にあるとすごく良いです。