自動化厨のプログラミングメモブログ │ CODE:LIFE

Python/VBA/GAS/JavaScript/Raspberry Piなどで色んなことを自動化

Googleスプレッドシート関数でWebスクレイピング超入門①

Webスクレイピング。

Webページから欲しいデータを抽出する仕組みのことです。 調べ物を定期的に行いたい もしくは 大量に行いたい場合には自動でデータを収集させて手作業を削減したいですよね。

これにはいろいろなやり方があります。 RPA(UiPathやPowerAutomateDesktop)、プログラミング(SeleniumやPlaywrightやBeautifulSoupやChrome DevTools Protocol)、その他専用ツールなどなど。

しかし、いずれも初心者には少々ハードルの高いもの。 そこでWebスクレイピングの超入門的なやり方としてGoogleスプレッドシート関数を使った方法を紹介します。

細かいことは良いから実際のスプレッドシートを見たいという方はこちらのシートをコピーしてお試しください。

スプレッドシート関数で始めるWebスクレイピング - Google スプレッドシート

スプレッドシートで使えるWebスクレイピング関数

Level① IMPORTFEED関数 でQiitaのトレンド記事を取得する

まず1つ目はIMPORTFEED関数。 RSSやAtomフィードから最新の更新情報を取得するための関数で、ニュースやブログの最新情報を自動的に取得したい場合に便利。 今回の例ではQiitaのトレンド記事を取得します。

A1セルに =IMPORTFEED("https://qiita.com/popular-items/feed.atom","items",1) と入力するだけでOK。

RSSフィードなどはそもそも機械的にデータを受け渡すための仕組みなのでほぼ確実に↓のようにキレイなデータが出来上がる。

フィードが配信されているサイトで、なおかつ欲しい情報がそこに含まれているならこれが一番無難な方法。

Qiitaのトレンド記事をスプレッドシートに出力

IMPORTFEED関数の引数

=IMPORTFEED(URL, [クエリ], [見出し], [アイテムの番号])

引数 概要
URL フィードのURL。
クエリ "items"(デフォルト)や"feed"を指定して取得内容を選択。
"items Title" のようにするとTitleだけが出力される。
見出し ヘッダー行を表示するかどうか(TRUE/FALSE)。
デフォルトでは表示されないためTRUE(または1)を設定推奨。
アイテムの番号 取得するアイテム数。指定しなければ全て出力される。

IMPORTFEED - Google ドキュメント エディタ ヘルプ

Level② IMPORTHTML関数 でYahoo天気の週間予報を取得する

次にIMPORTHTML関数。 RSSやAtomフィードが配信されていなくても、Webページ上にあるtableタグ(表になっている部分)を取得してスプレッドシート上に展開してくれる。

A1セルに =IMPORTHTML("https://weather.yahoo.co.jp/weather/jp/13/4410.html","table",4) と入力してみましょう。

東京都の週間天気予報がスプレッドシートに

何番目のテーブルなのかを確認するには?

これ実はページ上の見た目で判断してはいけないやつです。あくまでもHTMLタグとしてのtableが何番目なのかを指定します。

数が少なければテキトーに入力しながら試して欲しいデータになったら それ! というやり方でもOK。

一発で何番目かを知りたい場合は[F12]または[Ctrl + Shift + I]でブラウザの開発者ツールを開いて、[Ctrl + F] で table を検索→何番目の要素が取得対象なのかを確認します。

ブラウザの開発者ツールで何番目のテーブルか確認

IMPORTHTML関数の引数

=IMPORTHTML(URL, クエリ, [指数], [locale])

引数 概要
URL 取得したいページのURL。
クエリ 目的のデータを含むアイテムの種類を "list"(リスト)か "table"(表)で指定。
指数 対象の表またはリストが何番目にあるのかを指定する。
4番目なら4と入力。何も入力しない場合は自動的にそれっぽいのを取るみたい?
locale 基本的には指定不要。en_USなどと指定すると日付や通貨などの表示がUS向けのものになる。

IMPORTHTML - Google ドキュメント エディタ ヘルプ

Level③ IMPORTXML関数 でいい感じにYahoo天気の週間予報を取得する

さて、IMPORTHTML関数も良かったですが、気づいた方もいるはず。 最高気温と最低気温が同じセルに入っている...!? これではグラフ化することも計算式で扱うこともできませんね...。

回避するにはさらに細かく ”テーブルの中のどの部分を抽出するのか” も指定する必要があります。

それを実現できるのが IMPORTXML関数 です。

まずはA1セルに =IMPORTXML("https://weather.yahoo.co.jp/weather/jp/13/4410.html","//*[@id=""yjw_week""]/table/tbody/tr[1]") と入力してみましょう。

すると↓のように日付の行だけを抽出できます。

週間天気予報から日付の行だけを抽出

ポイントはIMPORTXML関数の第2引数で指定している //*[@id=""yjw_week""]/table/tbody/tr[1] の部分。

これはXPathという記法で、構造化されたテキスト(XMLやHTML)の中でどの部分を取ってくるのか を定義しています。

//*[@id=""yjw_week""]/table/tbody/tr[1] では 「idがyjw_week"という要素の下のtableの下のtbodyの下の1つ目のtr」と指示しています。これもブラウザの開発者ツールで確認可能です。

idがyjw_week"という要素の下のtableの下のtbodyの下の1つ目のtr

さらに対象のタグを右クリックしてCopy XPathを選択することで //*[@id="yjw_week"]/table/tbody/tr[1] が得られるので、シンプルな構造であればこれだけでOKです。

※XPath内に含まれる " はそのままスプレッドシート関数に貼り付けると上手く認識されません。"" のように2つ連続させると正しく認識されるので //*[@id="yjw_week"]/table/tbody/tr[1] の場合は //*[@id=""yjw_week""]/table/tbody/tr[1] とします。

右クリック → Copy XPath

同様に他の行もやっていきましょう。

A2セルに =IMPORTXML("https://weather.yahoo.co.jp/weather/jp/13/4410.html","//*[@id=""yjw_week""]/table/tbody/tr[2]") で天気が取得できます。

A3セルに =IMPORTXML("https://weather.yahoo.co.jp/weather/jp/13/4410.html","//*[@id=""yjw_week""]/table/tbody/tr[3]") で最高気温だけが....取れない。

なぜならテーブル行としては同じ行だから。HTMLを確認すると別れているのはfontタグのみです。

行を分けてくれていれば簡単なのに...

最高気温だけを取るにはこうです。

=IMPORTXML("https://weather.yahoo.co.jp/weather/jp/13/4410.html","//*[@id=""yjw_week""]/table/tbody/tr[3]/td/small/font[1]")

tr[3] のあとに続けて /td/small/font[1] とすることで「3行目のtdの下のsmallの下の1つ目のfont」という指定になります。

で、ここまで来て完成かと思いきやあとひと工夫必要です。

横向きに並んでほしいのに縦向きに...

縦向きのデータを横向きにするには TRANSPOSE関数 を用います。

B3セルに =TRANSPOSE(IMPORTXML("https://weather.yahoo.co.jp/weather/jp/13/4410.html","//*[@id=""yjw_week""]/table/tbody/tr[3]/td/small/font[1]")) を入力。

TRANSPOSE関数で横向きに変換

ようやく形になってきました。

B4セルに =TRANSPOSE(IMPORTXML("https://weather.yahoo.co.jp/weather/jp/13/4410.html","//*[@id=""yjw_week""]/table/tbody/tr[3]/td/small/font[2]")) を入力。( font[2] として最低気温を取得)

A5セルに =IMPORTXML("https://weather.yahoo.co.jp/weather/jp/13/4410.html","//*[@id=""yjw_week""]/table/tbody/tr[4]") を入力。

A3、A4セルには手動で「最高気温(℃)」「最低気温(℃)」を入力して完成です。

XPathで取りたい要素が選択できているか確認するには

開発者ツールでXPathによる検索を行います。 1. F12 または [Ctrl + Shift +I] で開発者ツールを起動 2. Elementsタブに移動 3. [Ctrl + F] で検索バーを表示 4. XPath で検索して取得対象の要素が全てヒットすることを確認

XPathで要素を検索

IMPORTXML関数の引数

=IMPORTXML(URL, XPathクエリ, [locale])

|引数|概要| |--|--| |URL| 取得したいページのURL。| |XPathクエリ| 取得対象要素のXPathを指定。| |locale| 基本的には指定不要。en_USなどと指定すると日付や通貨などの表示がUS向けのものになる。| IMPORTXML - Google ドキュメント エディタ ヘルプ

Level④ IMPORTDATA関数 で祝日一覧CSVを取得したい

さて、最後になったIMPORTDATA関数。

使い方自体はとても簡単で、CSVまたはTSVファイルのURLを指定するだけ。しかし、これは上手くいきません。

A1セルに =IMPORTDATA("https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv") を入力してみましょう。

すると内閣府の提供する祝日一覧CSVデータ(国民の祝日について - 内閣府)が読み込まれます、が、文字化けします...(T_T)

なんの祝日なのか全くわからない

なぜかというとこの関数が対応している文字コードが「UTF-8」であり、日本でよく使われているCSVデータの文字コードは「Shift_JIS」だから。

現状はGASで自作するしかない

いつかUTF-8が主流になればいいなと願いつつも、ExcelでCSVをダブルクリックで開いた時には逆にUTF-8だと文字化けする問題があり、これを回避するためにShift_JISを採用していると思われ...。 つまり、日本語のCSVデータではIMPORTDATA関数の出番は無く、どうにかしてShift_JISのデータを読み込むには Google Apps Script を用いるしか無いのが現状です。

ということでGASを使った自作 importCsv関数 の記事はこちら↓

codelife.cafe