製造系SEのメモ

普段気になった内容をメモしていきます

RでWebページ上のテーブルを読み込み(ウェブスクレイピング)

f:id:asakat:20190130204302j:plain

最近RでWebページ上のテーブルを読み込む方法を知ったのでメモします。

テストデータ

テストデータとして、気象庁が提供している過去の気象データを使います。
www.data.jma.go.jp

今回は2019年1月1日の東京都における気象データ(10分ごとの値)を読み込む対象にします。

テーブルの読み込み(失敗)

XMLパッケージreadHTMLTable()関数で簡単に読み込めるということで試してみると…

> library(XML)
> 
> url <- "https://www.data.jma.go.jp/obd/stats/etrn/view/10min_s1.php?prec_no=44&block_no=47662&year=2019&month=1&day=1&view="
> 
> #headerオプションでテーブルにヘッダーがあるかを指定
> #stringsAsFactorsオプションでcharacter列をfactor型で返すかを指定
> read <- readHTMLTable(url, header = TRUE, stringsAsFactors = FALSE)
Warning message:
XML content does not seem to be XML: 'https://www.data.jma.go.jp/obd/stats/etrn/view/10min_s1.php?prec_no=44&block_no=47662&year=2019&month=1&day=1&view=' 

失敗しました。何でだ!と思って調べるとURLの「https」部分を「http」に書き換える必要があるようです。

テーブルの読み込み(再挑戦)

「http」に書き換える書き換えて実行すると…

> library(XML)
> 
> url <- "http://www.data.jma.go.jp/obd/stats/etrn/view/10min_s1.php?prec_no=44&block_no=47662&year=2019&month=1&day=1&view="
> 
> #headerオプションでテーブルにヘッダーがあるかを指定
> #stringsAsFactorsオプションでcharacter列をfactor型で返すかを指定
> read <- readHTMLTable(url, header = TRUE, stringsAsFactors = FALSE)
> read
$`NULL`
NULL

$`NULL`
NULL

$`NULL`
NULL

$`NULL`
NULL

$tablefix1
      V1     V2     V3   V4       V5   V6   V7     V8   V9    V10  V11
1   現地   海面   平均 風向 最大瞬間 風向 <NA>   <NA> <NA>   <NA> <NA>
2  00:10 1023.4 1026.5   --      2.3   57  1.2   北西  2.4 西北西     

~省略~

90 14:50 1017.7 1020.7   --      9.8   42  3.0 南南東  7.2 南南東   10
 [ reached 'max' / getOption("max.print") -- omitted 55 rows ]

$`NULL`
NULL

読み込みはできましたがページ内に6つテーブルがあると認識されたため、欲しいテーブル(tablefix1)以外にも空テーブルが読み込まれています

これはテーブルを指定して別の変数に代入する(例:table <- read$tablefix1)か、readHTMLTable()関数のwhichオプション(which = 整数値)であらかじめテーブルを指定しておくことで解決できます。

また、headerオプションを指定しましたが列名がうまく設定されていません。
これはこのデータの列名が複数行、複数列にまたがっていてうまく読み込めないためですが、今回は数が多くないので後で手動で設定します。

テーブルの読み込み(再再挑戦)

修正・追記して実行しました。

> library(XML)
> library(dplyr)
> 
> url <- "http://www.data.jma.go.jp/obd/stats/etrn/view/10min_s1.php?prec_no=44&block_no=47662&year=2019&month=1&day=1&view="
> 
> #headerオプションでテーブルにヘッダーがあるかを指定
> #stringsAsFactorsオプションでcharacter列をfactor型で返すかを指定
> #whichオプションで読み込むテーブルを指定
> #skip.rowsオプションで無視する行を指定
> read <- readHTMLTable(url, header = FALSE, stringsAsFactors = FALSE, which = 5, skip.rows = 1:2)
> 
> table <- read %>%
+   rename(時分 = V1, 気圧_海面 = V2, 気圧_現地 = V3,
+            降水量 = V4, 気温 = V5, 相対湿度 = V6,
+            風速_平均 = V7, 風向_平均 =V8, 風速_最大 = V9,
+            風向_最大 = V10, 日照時間 = V11)
> table
    時分 気圧_海面 気圧_現地 降水量 気温 相対湿度 風速_平均 風向_平均 風速_最大 風向_最大 日照時間
1  00:10    1023.4    1026.5     --  2.3       57       1.2      北西       2.4    西北西         
2  00:20    1023.5    1026.6     --  1.8       59       1.1    西北西       2.3    西北西         

~省略~

90 15:00    1017.7    1020.7     --  9.2       45       4.2    南南東       7.0      南東       10
 [ reached 'max' / getOption("max.print") -- omitted 54 rows ]

テーブルとして読み込めました。

一番のポイントは

> read <- readHTMLTable(url, header = FALSE, stringsAsFactors = FALSE, skip.rows = 1:2, which = 5)

ですね。
「header = FALSE」、「skip.rows = 1:2」で列名部分(1~2行目)を無視し
「which = 5」でページ内の5番目のテーブルを読み込んでいます。

後はdplyrのrename()関数で列名を設定していますが、数値が入るはずの「降水量」に文字列「--」が入っていたりするのでもう少し加工は必要ですね。

まとめ

readHTMLTable()関数についてまとめると以下の通りです。

  • XMLパッケージのreadHTMLTable()関数でWebページ上のテーブルを読み込み可能
  • URLが「https」から始まっていると読み込めないため、「http」への書き換えが必要
  • headerオプションでテーブルにヘッダーがあるかを指定可能
  • stringsAsFactorsオプションでcharacter列をfactor型で返すかを指定可能
  • whichオプションで読み込むテーブルを指定可能
  • skip.rowsオプションで無視する行を指定可能

詳細は以下のページをご確認ください(英語です)。
readHTMLTable function | R Documentation



以上です。