Rで解析:WebページやHTMLファイルの表をまとめてExcel化「html2excel」パッケージ
Webページに載っている表を、そのままExcelファイルとして手元に残したい——データを扱う仕事では意外とよくある場面です。rvestで表を取り出し、openxlsxでxlsxに書き出す、という定番の流れは自分でも書けますが、複数のページやファイルをまとめて処理し、そこから必要な表だけを選んでシートに振り分けるとなると、コードはそれなりの分量になります。「html2excel」パッケージは、rvest::read_html・rvest::html_table・openxlsx::write.xlsxの3処理をhtml2excelコマンド1つに束ね、表をtibble化し、xlsxへ書き出せるようにしたパッケージです。
パッケージバージョンは1.0.1。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。
パッケージのインストール
下記コマンドを実行してください。
# パッケージのインストール
install.packages("html2excel")
# パッケージの読み込み
library("html2excel")コマンド例
詳細はコメント、パッケージのヘルプを確認してください。この記事では、当サイトのレビュー記事(Edifier M90)のページに載っている表を題材に、読み込みからxlsxへの書き出しまでを試します。
HTMLの表を読み込んでExcelに書き出す:html2excelコマンド
| オプション | 意味 | 初期値 |
|---|---|---|
| html | HTMLファイルのパス、HTMLファイルを含むディレクトリのパス、またはwww.・http:・https:で始まるURLを文字列ベクトルで指定 | なし |
| ext | 文字列。htmlにディレクトリを指定したとき、読み込むファイルの拡張子をワイルドカードで指定。utils::glob2rxで正規表現に変換されlist.filesに渡される | “*.html” |
| write | 論理値。取り出した表をopenxlsx::write.xlsxでxlsxファイルに書き出すかどうか | TRUE |
| dir | write = TRUEのときの出力先ディレクトリ。htmlがURLなら絶対パスで必須、HTMLファイルやディレクトリなら入力ファイルのある場所からの相対パス。存在しない場合は作成される | なし |
| sheets | 数値ベクトルまたは数値ベクトルのリスト。i番目の出力Excelファイルにシートとして含める表の番号を指定。出力ファイル数に合わせてリサイクルされ、省略すると全ての表が含まれる | なし |
| read_args | rvest::read_htmlに渡す引数のリストを指定 | list() |
| html_args | rvest::html_tableに渡す引数のリストを指定 | list() |
| write_args | openxlsx::write.xlsxに渡す引数のリストを指定。fileはhtmlとdirから決まるため指定できない | list() |
読み込んだ表の大きさを確認する:summaryコマンド
html2excelコマンドの戻り値はhtml2excelクラスを持つリストです。そのまま表示すると各tibbleの中身まで出力されますが、summaryコマンドを使うと行数と列数だけが表示されます。どの表をシートに含めるか、html2excelコマンドのsheetsオプションの内容を決めるときに便利です。
| オプション | 意味 | 初期値 |
|---|---|---|
| object | html2excelコマンドが返したhtml2excelクラスのオブジェクトを指定 | なし |
| … | print.defaultに渡す引数を指定 | なし |
URLから表をまとめて読み込む
html引数にページのURLを渡すだけで、そのページ内の全ての表がtibbleとして読み込まれます。write = FALSEを指定すると、xlsxファイルは書き出さずに読み込みだけを行います。まずはsummaryコマンドで、いくつの表がどんな大きさで取れたかを確認します。
# 対象ページのURLを指定する
url <- "https://www.karada-good.net/bodygood-mono/m90/"
# ページ内の全ての表をtibbleとして読み込む(xlsxファイルは書き出さない)
tabs <- html2excel(url, write = FALSE)
# 読み込んだ表の行数と列数を一覧で確認する
summary(tabs)実行結果:
$`https://www.karada-good.net/bodygood-mono/m90/`
$`https://www.karada-good.net/bodygood-mono/m90/`$sheet1
[1] 7 2
$`https://www.karada-good.net/bodygood-mono/m90/`$sheet2
[1] 12 2
attr(,"class")
[1] "summary.html2excel"このページには表が2つあり、1番目が7行2列(付属品の一覧)、2番目が12行2列(スペックの一覧)と分かります。戻り値は「ページごとのリスト」の中に「表ごとのtibble」が入った入れ子構造です。個別の表を見るときは、ページを[[1]]で、シートを$sheet1のように指定します。
# 1番目の表(付属品の一覧)を表示する
tabs[[1]]$sheet1実行結果:
# A tibble: 7 × 2
付属品 備考
<chr> <chr>
1 ワイヤレスリモコン 単4電池2本付属。音量・入力切替・再生操作対応
2 スピーカー接続ケーブル 左右をつなぐ専用ケーブル。長めで設置の自由度が高い
3 電源ケーブル 100–240V対応
4 USB-Cケーブル PC接続用(フェライトコア付き)
5 3.5mm–RCA/AUXケーブル アナログ接続用
6 光デジタルケーブル テレビ・PCの光出力用
7 クイックスタートガイド 日本語表記ありページの表がそのままtibbleになりました。列名の見出しもHTMLのthタグから取り込まれています。なお、表示の幅はコンソールの設定に依存します。列が途中で省略される場合は、print(tabs[[1]]$sheet1, width = Inf)のように幅を指定すると全体を確認できます。
必要な表だけを選んでxlsxファイルに書き出す
今回はスペックの一覧(2番目の表)をExcelに残したいので、まず中身を確認します。
# 2番目の表(スペックの一覧)を表示する
tabs[[1]]$sheet2実行結果:
# A tibble: 12 × 2
項目 内容
<chr> <chr>
1 型式 EDF100120
2 構成 2ウェイ・アクティブ(バイアンプ)
3 総合出力 100W RMS(ミッドバス35W×2+ツイーター15W×2)
4 ドライバー 4インチ アルミミッドバス+1インチ シルクドームツイーター
5 信号処理 エンドツーエンド24bit/96kHz DSP
6 認証 ハイレゾオーディオ/ハイレゾオーディオワイヤレス
7 Bluetooth 6.0(LDAC最大990kbps・マルチポイント対応)
8 入力 HDMI eARC/光デジタル/USB-C/AUX/Bluetooth
9 出力 SUB OUT
10 サイズ 幅133×高さ212×奥行225mm
11 カラー ブラック/ホワイト
12 通常価格 46,980円この表をxlsxファイルにします。sheets引数に表の番号を渡すと、その表だけがシートとして書き出されます。URLを渡すときは、dir引数に出力先の絶対パスを指定する必要があります(存在しないフォルダは自動的に作成されます)。書き出したファイルのパスは、戻り値のfiles属性から取得できます。
# 出力先の絶対パスを用意する(作業用の一時フォルダ)
out_dir <- normalizePath(tempdir(), winslash = "/")
# 2番目の表(スペックの一覧)だけをシートにしてxlsxファイルに書き出す
picked <- html2excel(url, sheets = 2, dir = out_dir)
# 書き出されたファイルのパスを確認する
attr(picked, "files")
# シート名は元の表番号ではなく、出力順に振り直される
names(picked[[1]])実行結果:
[1] "C:/Users/user/AppData/Local/Temp/Rtmp0aBc12/m90.xlsx"
[1] "sheet1"2番目の表を選んでも、出力側のシート名はsheet1から振り直される点に注意してください。元の表番号ではなく、書き出す表の並び順で番号が付きます。
読み込みと書き出しの挙動を細かく指定する
read_args、html_args、write_argsには、それぞれrvest::read_html、rvest::html_table、openxlsx::write.xlsxに渡したい引数をリストで指定します。文字コードを宣言していないページで文字化けが起きるときはread_argsでエンコーディングを明示し、Excelのテーブル書式で書き出したいときはwrite_argsでasTable = TRUEを渡します。また、html引数にURLの文字列ベクトルやフォルダのパスを渡せば、複数ページ・複数ファイルをまとめて処理できます。
# 文字化けするページでは read_args でエンコーディングを明示する
tabs2 <- html2excel(url, write = FALSE,
read_args = list(encoding = "UTF-8"))
# write_args は openxlsx::write.xlsx へ渡される
# 例:Excelのテーブル書式(オートフィルタ付き)で書き出す
# styled <- html2excel(url, sheets = 2, dir = out_dir,
# write_args = list(asTable = TRUE))
# 複数ページのスペック表をまとめて集めることもできる
# ページごとに取り出す表番号をリストで指定する
# pages <- c("https://www.karada-good.net/bodygood-mono/m90/",
# "https://www.karada-good.net/bodygood-mono/ml/")
# specs <- html2excel(pages, sheets = list(2, 1), write = FALSE)rvestで表を取り出してからopenxlsxで書き出す処理を毎回書いていた方であれば、その定型部分をそのまま置き換えられるパッケージです。1ページから複数の表をまとめてtibble化・xlsx化できるので、レビュー記事のスペック表を集めて比較用のワークブックにする、といった使い方にも発展できます。複数ページ、複数ファイルを扱うときほど効果が分かりやすいと思います。
この記事が誰かの役に立ちますように。