【スクレイピング】`rvest`を使ってe-Statからファイルを取得する
はじめに
本記事ではRでスクレイピングを行っていきます。Rのrvest
パッケージを使ったスクレイピング自体は他のウェブサイトでも多数紹介されているのですが、ここではJavaScriptが使われているページ(特にe-Stat)にも対応した方法をまとめます。
e-Statにも様々な形式のファイルがあるのですが、今回はシェープファイル(.shp
)をダウンロードすることにします。
もう少し詳しい説明は自分のページでも説明していますので、興味がある方はご覧ください。
環境
- Windows 11
- R 4.5.1
- RStudio 2025.5.0.496
パッケージ
使用するパッケージはrvest
とhere
です。主に使用するのはrvest
で、here
はファイルの保存先を指定するのに使います。使わなくても問題ありません。
# パッケージのインストール
pak::pak(c("rvest", "here"))
# or
install.packages(c("rvest", "here"))
library(rvest)
# 保存するディレクトリを指定
save_dir <- here::here("data/shpfiles")
# ディレクトリがまだない場合は作成する
if (!dir.exists(save_dir)) {
dir.create(save_dir)
}
今回はあらかじめ保存するディレクトリを指定しています。ディレクトリがない場合でもif
の方を実行すれば自動で"data/shpfiles"
が作成されるので、そちらを実行してください[1]。
ファイルをダウンロードするページ
今回ファイルを取得していくのは、e-Statの「地図」→「境界データダウンロード」→「3次メッシュ」→「世界測地系平面直角座標系・Shapefile」のページです。もちろん他のページでも可能です。
メッシュいうのは国土を例えば1km×1kmの正方形で区切ったものをいい、その中の人口等のデータを扱うことができるようになります。
主に使用する関数
JavaScriptが使用されている動的ページにも使える関数として、read_html_live()
があります。これを主に使用します。
読み込むページが1ページだけであれば、引数にURLを入れるだけで実行できます。
html <- read_html_live("https://www.e-stat.go.jp/gis/statmap-search?page=1&type=2&aggregateUnitForBoundary=S&coordsys=2&format=shape")
ループする
e-Statのページに飛んでいただければわかりますが、シェープファイルは全9ページにわたって存在しています。
これらのファイルを1ページずつローリング作戦していくのは骨が折れるので、for
ループで一気にダウンロードしていきましょう。
関数の詳細については冒頭に挙げた私のページに記載しています。
base_url <- "https://www.e-stat.go.jp"
for (i in 1:9) {
url <- paste0("https://www.e-stat.go.jp/gis/statmap-search?page=", i, "&type=2&aggregateUnitForBoundary=S&coordsys=1&format=shape")
html <- read_html_live(url)
Sys.sleep(1)
links <- html |>
html_elements("a") |>
html_attr("href")
shp_links <- links[grepl("data\\?dlserveyId=S&", links)]
full_urls <- paste0(base_url, shp_links)
for (j in seq_along(full_urls)) {
code <- sub(".*code=([0-9]+).*", "\\1", shp_links[j])
folder_path <- file.path(save_dir, paste0("mesh", code))
shp_file <- list.files(folder_path, pattern = "\\.shp$", full.names = TRUE)
if (length(shp_file) > 0) next
zip_path <- file.path(save_dir, paste0("mesh", code, ".zip"))
tryCatch({
download.file(full_urls[j], destfile = zip_path, mode = "wb")
Sys.sleep(1)
dir.create(folder_path, showWarnings = FALSE)
unzip(zip_path, exdir = folder_path)
file.remove(zip_path)
}, error = function(e) {
warning(paste("Error in downloading or extracting:", full_urls[j]))
})
Sys.sleep(2)
}
}
ざっくり説明すると、ページを読み込んだ後にaタグの中のhrefを探してリンクを探り、シェープファイルのリンクに絞ったうえでページ内の各ファイルを繰り返しダウンロード、その後zipファイルを解凍してzipの方は削除しています。これをページ単位で9回繰り返し実行しているというイメージです。
おわりに
メッシュ人口が入ったCSVファイルについても同様の方法でダウンロード可能です。ちなみにコードだけほしい方は、そちらもまとめていますので以下をご覧ください。
ご覧いただきありがとうございました。
-
if
文なので、ディレクトリが既にある場合は実行しても何も起こりません。 ↩︎
Discussion