- Rでスクレイピングするときの基本的な手順
- Rでネット上のデータをダウンロードするときの方法
についてメモ。
やりたいこと
例えば,以下のサイトで
http://www.soumu.go.jp/senkyo/senkyo_s/data/shugiin46/shikuchouson.html
- 「北海道」から「沖縄県」の各リンクをたどって,
- 各リンク先のすべてのxlsファイルのリンクを取得し,
- すべてのxlsファイルをダウンロードしたい
という状況を考えます。
①{rvest}によるスクレイピング
1.「北海道」から「沖縄県」の各リンクをたどって,
2.各リンク先のすべてのxlsファイルのリンクを取得
するところまでをスクレイピングで行います
# ライブラリ読み込み library(tidyverse) library(readr) library(rvest)
1. htmlの読み込み
read_html()
に目的のサイトのURLを入れ,htmlを取得します
# read_html():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に貼り付けます
# html_nodes():cssやxpathを指定して目的のタグを抽出 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を取得します
# html_attr():タグの属性に指定されている文字列を取得 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を抽出したりすればいいだけです。
# 47都道府県分ループして各ページのURLを取得する for(i in 1:length(urls)){ html_i = read_html(str_c("http://www.soumu.go.jp",urls[i])) ## i県のxls(小選挙区,比例代表の2つのデータ)のリンク urls_i = html_i %>% html_nodes(css = ".linklist") %>% html_nodes(css = "a[href *= 'xls']") %>% html_attr("href") ## i県のxlsのリンクの文字列(説明文) texts_i = html_i %>% html_nodes(css = ".linklist") %>% html_nodes(css = "a[href *= 'xls']") %>% html_text() ## data frameにする 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) # 1ループごとに0.5秒待ってサーバーへの負荷をへらす 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のファイルを,指定したパス(ファイル名)で保存します。
# 取得したURL一覧から順次xlsをダウンロードする base_url = "http://www.soumu.go.jp/" # URLの前半部分(取得したURLが相対URLなので) # ダウンロード先フォルダの作成 download_folder = str_c("./xls") # ダウンロード先フォルダ dir.create(download_folder) # 「xls」というフォルダを作成 # download.file():「指定したURL」から「指定したパス」へのダウンロード ## ファイル名ベクトルの作成:「北海道_小選挙区」型のファイル名 file_name = str_c(url_df[["prefName"]],"_",url_df[["text"]]) ## URLベクトルの作成 url = str_c(base_url,"/",url_df[["url"]]) ## 各URLをダウンロード for(i in 1:length(url)){ download.file(url = url[i], destfile = str_c(download_folder,"/",file_name[i],".xls"), mode = "wb") # 今回は"wb"がうまくいった # 1ループごとに0.5秒待ってサーバーへの負荷をへらす 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) # 1. スクレイピングしてURLを取得 =========================== # read_html():htmlの読み込み html_data = read_html("http://www.soumu.go.jp/senkyo/senkyo_s/data/shugiin46/shikuchouson.html") # html_nodes():cssやxpathを指定して目的のタグを抽出 bodyArea = html_data %>% html_nodes(xpath = '//*[@id="bodyArea"]') a_tags = bodyArea %>% html_nodes(css = "a[href *= 'shikuchouson']") # html_attr():タグの属性に指定されている文字列を取得 urls = a_tags %>% html_attr("href") # html_text():タグのテキスト部の文字列を取得 texts = a_tags %>% html_text() # 47都道府県分ループして各ページのURLを取得する ------------ for(i in 1:length(urls)){ html_i = read_html(str_c("http://www.soumu.go.jp",urls[i])) ## i県のxls(小選挙区,比例代表の2つのデータ)のリンク urls_i = html_i %>% html_nodes(css = ".linklist") %>% html_nodes(css = "a[href *= 'xls']") %>% html_attr("href") ## i県のxlsのリンクの文字列(説明文) texts_i = html_i %>% html_nodes(css = ".linklist") %>% html_nodes(css = "a[href *= 'xls']") %>% html_text() ## data frameにする 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) # 1ループごとに0.5秒待ってサーバーへの負荷をへらす Sys.sleep(0.5) } # 2. ダウンロード ========================================== # 取得したURL一覧から順次xlsをダウンロードする base_url = "http://www.soumu.go.jp/" # URLの前半部分(取得したURLが相対URLなので) # ダウンロード先フォルダの作成 download_folder = str_c("./xls") # ダウンロード先フォルダ dir.create(download_folder) # 「xls」というフォルダを作成 # download.file():「指定したURL」から「指定したパス」へのダウンロード ## ファイル名ベクトルの作成:「北海道_小選挙区」型のファイル名 file_name = str_c(url_df[["prefName"]],"_",url_df[["text"]]) ## URLベクトルの作成 url = str_c(base_url,"/",url_df[["url"]]) ## 各URLをダウンロード for(i in 1:length(url)){ download.file(url = url[i], destfile = str_c(download_folder,"/",file_name[i],".xls"), mode = "wb") # 今回は"wb"がうまくいった # 1ループごとに0.5秒待ってサーバーへの負荷をへらす Sys.sleep(0.5) } # ダウンロードしたファイルたち list.files(download_folder)
参考文献
- 作者: 石田基広,市川太祐,瓜生真也,湯谷啓明
- 出版社/メーカー: シーアンドアール研究所
- 発売日: 2017/03/27
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
石田さんのこの本は基礎的なことから幅広く書いてあってスクレイピングするとき手元にあるとすごく良いです。