GASでスクレイピングしてデータをスプレッドシートに書き込む

今回はGASを使ってスクレイピングしたいなーと思う。そういえば以前Pythonでスクレイピングするっていうことを書いたね。

とはいっても自分のパソコンにいちいちコードを実行するための環境を用意するのは面倒だ・・・という場合もあるでしょう。そんな時に使えるのがGASです。GASは自分で環境を構築する必要もなく、コードを書けば実行できますからね。

そのGASでスクレイピングをやってやろうではありませんか。せっかくだからスクレイピングしたデータをスプレッドシートに書き込むところまでやろうかなと思う。ではやっていこう。

Parserライブラリをインストールする

Parserという便利なライブラリがあるのでこれを使いたい。ParserのIDをライブラリから追加するのだけど、そのIDがこれ。

1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw
これを左側のライブラリっていうところから入力して追加する。
追加するとこんな感じでParserっていうのがライブラリの下に出てくる。
これでとりあえず準備は完了だから実際にコードを書いていこう。

GASでスクレイピング処理を記述する

Parserの使い方

スクレイピングにParserを使うといっても、Parserってどう使うんだよ?ん??って話ですよね。Parserはデータを抜き出したい始めと終わりのタグを指定してあげることで、その中身を取り出すことができる。

Easy data scraping with Google Apps Script in 5 minutes

これをコードに落とすとこんな感じになる。

// データを取得したいWebサイトのURLを指定
var content = UrlFetchApp.fetch(url).getContentText();

// Parserで取得したい部分を絞り込む
var scraped = Parser
                .data(content)
                .from(fromText)
                .to(toText)
                .build();
  • data・・・Parserに解析させたいデータ
  • from・・・データのどの部分から絞り込むか
  • to・・・データのどの部分を終わりで絞り込むか
  • build・・・条件に最初に合致するデータだけを取得。条件に合致する全てのデータが欲しい場合は、iterate()とすればOK
なんとなく見えてきただろうか。まあ実際にコード書いてみないと分からないよね。実際にデータを取得してみよう。

サイトのデータを取得する

取得するデータはとりあえずこのサイトの新着記事にある記事のタイトルにしようかな。

このタイトルのHTML構造がどうなっているの確認してみるとこんな感じか。

post-titleっていうclassの中にaタグがあってその中にタイトルの文字列が書かれていると、なるほど。このタイトルの文字列を抜き出したいけど、aタグの中はそれぞれのタイトルで変わってくるから面倒ですね。Parserって挟んだものを抜き出してくれるから、一発ではできなそうだな。

試しにpost-titleの部分だけでやってみるとこうなる。無駄なaタグが入ってしまっているんだよなあ。

欲しいのはこのaタグの中にあるテキストなんだよ。だからこのaタグはいらない。とはいってもParserに入れ子になっているものをうまいこと取得するような機能はない?ようなので、正規表現でいきましょう。

タグを置換する正規表現で消してみた。

.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,'')

build()の結果は文字列だからこんなことができたようだ。

複数のタイトルを取得する

一つのタイトルならさっきの感じでやればいけることはわかった。だけど今回はやりたいのはベージにあるタイトルを全部取得したいっていうこと。build()だとそれが実現できないから、iterate()を使おう。そうすると合致するものが配列で返ってくる。

先頭にアクセスしてみると、さっきと同じような感じだね。

aタグが入るからこれを削除したいけど、今回は配列だからそのまま正規表現んは使えないね。eachで回して処理してやろう。

なんか面倒だねこれ。やっていることは以下。

  1. iterate()で条件に合致するものを配列で取得
  2. aタグを取り除いてタイトルだけの新たな配列を作成
  3. 2で作った配列をそれぞれ出力

まあとりあえず目的のものはゲットできたからよしとしよう。次はこれをスプレッドシートに書き込みにくぞ。

スクレイピングしたデータをスプレッドシートに書き込みする

さあ、さっきまでで一応欲しいデータの取得はできた。次はこれはスプレッドシートに書き込みにいこう。まずはGASから入力しにいくスプレッドシートを用意。ここにGASから取得したデータが入力される想定。

コードはこんな感じだ。

配列指定して一回だけで書き込みにいくみたいなことできないのかな。なんかappendChildでちょっとやってみたけどうまくいかなかった・・・GAS関連詳しくないので関数なんかいろいろ調べてみるといいと思います。

ちなみに[入力したいスプレッドシートのID]っていうのはこれです。

function myFunction() {
  const url = "";
  const html = UrlFetchApp.fetch(url).getContentText();
  let title_list = Parser.data(html)
  .from('')
  .to("")
  .iterate()

  let titles = []
  title_list.forEach(function(title){
    titles.push(title.replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,''))
  })

  const ss = SpreadsheetApp.openById("");
  const sheet = ss.getSheetByName("");

  titles.forEach(function(title){
    let lastRow = sheet.getLastRow()
    sheet.getRange(lastRow + 1, 1).setValue(title)
  })  
}

そして実行した結果・・・タイトル入りましたね。

ただなんか先頭空白空いていたりしてちょっと気持ち悪い、まあいいか。今回は許してやろう。

まとめ

GASで情報を取得してスプレッドシートに情報を書き込みにいくっていうことをやったけど、どうだろう。今回Parserっていうやつ使ったけど、個人的になんか使いにくい・・・タグが入れ子になっている場合って結構あると思うんだけど、そういう時今回みたいに正規表現使った力技でやるしかないのかな。。。

GASからスプレッドシートに書き込みに行くのは書き込みたいシート指定してやればいいから楽だったね。今回やったようなことは仕事なんかでデータ集めたいときなんかに便利そうだけど、スクレイピング禁止のサイトって多いからそこら辺は気をつけよう。まずはAPIがないかどうか確認するのが良いと思うよ。

おすすめの記事