GASとGoogleスプレッドシートではじめるWebスクレイピングとデータ生成

悩める人
悩める人

サクッとWeb上のデータをぶっこ抜いて、データ作っちゃいたいな~

楽な方法ないかな~~

悩める人
悩める人

スプレッドシートの単純な入力作業がしんどい。。自動で入力できないかな~

こんな人のための記事です。

私自身、

zukkey
zukkey

スプレッドシートの単純作業を自動化したかったり、Web上から必要な情報を研究や趣味で使いたいな~

なるべく楽したいしめんどーなことはやりたくないな~~

という場面がいくつかありました。

今日はそういったお悩みを解決する手段として、GASとGoogleスプレッドシートでWebスクレイピングおよび自動入力によるデータ生成の方法について、まったくプログラムを書いたことがないけど、楽したい!自動化したい!という方に向けて紹介をさせていただきます!

  • 準備するもの
  • 最低限必要なプログラミング概念について学ぶ
  • コードを書いてGoogleスプレッドシートに入力してみよう
  • コードを書いてGoogleスプレッドシートから値を取得してみよう
  • Webスクレイピングをしてシートにデータを集める

準備するもの

1. Googleアカウントを用意する

GASとGoogleスプレッドシートを用意するので、まずはじめにGoogleアカウントが必要です。

Googleアカウントを既に持っている方は、このステップを飛ばしていただいて構いません。

持っていない方は、次のリンクより必要な項目を埋めて作成しましょう。

2. 新しくGoogleスプレッドシートを用意する

次のリンクより、あたらしくスプレッドシートを作成しましょう

パーソナルとビジネスで若干制限周りが異なりますが、どちらでも利用できます。

個人利用の方はパーソナルを利用しましょう。Google スプレッドシートを使ってみるからいけます。

クリックすると、次の画面が見えてくると思います。

今回は特にテンプレートを利用しないので、空白を選択してください。

この画面にきたら、準備完了です。デフォルトで、無題のスプレッドシート、という名前がついてます。

添付画像が異なるのは、私の場合はtestと名前をつけたので変わっています。

3. 新しくGASを用意する

GASとは、Google Apps Scriptの略です。

Google Apps Scriptとは、Googleによって開発されたスクリプトプラットフォームである軽量のアプリケーション開発のためのGoogleのワークスペースプラットフォーム。 主にGoogleのサービスを自動化するスクリプト言語である。JavaScriptがもとになっているため汎用性が高く、開発環境はGoogle Chromeだけでいいのでプログラミング初心者が始めやすい言語の1つである。

WikiPediaより引用: https://ja.wikipedia.org/wiki/Google_Apps_Script
Google Apps Script

簡潔にまとめると、JavaScriptを元としたスクリプト言語&ワークスペースプラットフォームということですね。

Google Apps Scriptは、Google スプレッドシートから利用が可能です。

先ほど作成した、Googleスプレッドシートの方に移動して、ツール > スクリプトエディタより利用ができます。

他の場合として、拡張機能 > Apps Scriptより利用することができます。

Google Apps Scriptを開くと、次のような画面が出てきます。

この画面が出てきたら準備完了です。

厳密には違うのですが、JavaScriptを元としているので、JavaScriptを学んでおくとある程度やりたいことができると思います。

今回、Webスクレイピングや自動入力を行うのに必要と思われる部分だけに絞って軽くプログラミング概念について触れていきます。

最低限必要なプログラミング概念について学ぶ

やりたいことを実現するのに必要な概念は、変数と関数条件分岐繰り返し処理について学んでおくとよいと思います。

1. 変数と関数

変数とは、一時的に保存するような場所のことを表します。

箱自体を指していい、中身を入れ替えて使うことができます。GASでの変数の宣言は、var をつけます。変数には数値や文字列を代入することができます。

例えば、次のように宣言します。

sample.gs
var box = 12

これは、boxという名前の変数に12という数字が代入されている状態です。

GAS上で実際にコードを動かしてみることができるので、やってみましょう。

デフォルトでは、次のように、コード.gsというファイルにmyFunctionという関数(function)が定義されています。

関数とは、命令(実行したい処理)をまとめたものです。

現時点では、ちょっとわかりづらいと思います。百聞は一見に如かず。

先ほど定義した変数boxの値をログとして出力をしてみましょう。

myFunctionの中身を次のように変えます。変更すると、コード.gsの隣に黄色いアイコンが出ていると思います。

この状態はまだ保存されていないので、Macの場合は cmd + s 、Windowsの場合は control + sをキーボード入力して保存しましょう。

上のサンプルコードも載せておきます。コピペで動かせます。

コード.gs
function myFunction() {
  var box = 12
  console.log(box)
}

最後に、実行をクリックすると、次のように実行ログに12と出力されていることが分かります。

console.logは実行ログを出力するためのメソッドです。次のようにしてログとして確認することができます。

console.log(出力させたい内容をいれる)

実行したときの流れとして、「myFunctionに定義した処理として、boxという変数に12を代入して、コンソールログとして出力した。」というのが一連の流れになります。

関数は、このようにして、いくつかの処理をまとめておくものとして定義します。

2. 条件分岐

条件分岐には、ifswitchがありますが、最低限ifだけ覚えておけば大丈夫だと思います。(もちろん、他も覚えておくと場合によっては良いので、習得をおすすめします。)

if文は次のように書きます。

コード.js
function myFunction() {
  var box = 12
  if (12 < box) {
    console.log("12より大きいよ!")
  } else {
    console.log("12以下だよ!")
  }
}

if (条件式) と書いて、条件式にて比較したい内容を書きます。elseの中には、当てはまらなかった場合に当てはまります。

条件式は比較演算子を用いて書きます。

比較演算子使用例意味真偽値
<3 < xxは3より大きいxが4の場合はtrue、xが3の場合はfalse
<=3 <= xxは3もしくは3より大きいxが3の場合はtrue、xが2の場合はfalse
==3 == xxは3と等しいxが3の場合はtrue、xが4の場合はfalse
!=3 != xxは3と等しくはないxが3の場合はfalse、xが4の場合はtrue

他もありますが、大体これらを押さえておけば良いかと思います。

あとは、条件式に含められる、論理演算子&&(AND)と||(OR)も覚えておくといいでしょう

論理演算子使用例意味真偽値
&&0 < x && x <= 3xは0より大きく3以下xが3の場合はtrue、xが4の場合はfalse
||x < 2 || 4 < xxは2より小さいもしくはxは4よりおおきいxが1の場合はtrue、xが3の場合はfalse、xが5の場合はtrue

複数の条件を使いたい時によく使うので、覚えておきましょう。

先に書いた、コード.jsを実行すると次のようになります。

boxは12なので、12 < boxという比較はfalseになります。そのため、elseの分岐に入り、コンソールログに12以下だよ!と表示されます。

他にも色々と知りたい方は、下記ドキュメントがオススメです。

3. 繰り返し処理

繰り返し処理は、特定の回数繰り返したい時に使い、whileforなどがあります。

最低限forだけは覚えておきましょう。状況に応じて使い分けたい時も出てくるかと思うので他も習得しておくとおすすめです。

for文は次のように書きます。

コード.js
function myFunction() {
  console.log("実行開始")
  for(let i = 0; i <= 5; i++) {
    console.log("繰り返し処理実行中: " + i)
  }
  console.log("実行終了")
}

実行すると、下記のログを確認することができます。

for ([初期化式]; [条件式]; [加算式])とかきます。

初期化式では、let カウンターとして利用したい名前 = 0のように書きます。例ではカウンターとして利用したい名前をiとしています。

条件式では、カウンターの終了条件を定義します。条件がfalseになった段階で繰り返し処理が終わります。例では、iが5以下であればtrue、5よりおおきいつまり、6以上であればfalseとなり、繰り返し処理がとまります。

加算式では、カウンターを増やす意味としてカウンター名++と書きます。条件式に当てはまった場合に繰り返し処理が実行されたのち、加算式が実行されます。

例での処理と実行結果を見ると、カウンターが0から5まで加算されて処理が終了するので、計6回の繰り返し処理が実行されてログが出力されていることがわかります。

より厳密な定義や他の繰り返し処理について学びたい方は下記ドキュメントを参考にすると良いでしょう。

ここまでで、最低限必要なプログラミングの概念を学んだと思うので、次はコードを書いてGoogleスプレッドシートに入力するところをやっていきましょう。

コードを書いてGoogleスプレッドシートに入力してみよう

まずは、Googleスプレッドシートにコードを実行して入力する、ということをやってみましょう。

GASを用いてGoogleスプレッドシートの操作を行いたい場合は、SpreadsheetAppクラスを用います。

GASを用いてスプレッドシートに入力を行いたい場合は、次のように書きます。

コード.gs
function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(1,1).setValue(1);
}

SpreadsheetApp.getActiveSheetで、今開いているシート(表示しているシート)を取得しています。

getRangeでは、getRange(行, 列)のようにして指定することができ、今は1行1列を指定しています。他の書き方としてgetRange(‘A1’)と指定することもできます。

先で行ったように、GASで実行したあとの結果はこうなります。

1行1列にきちんと書き込まれていることを確認できると思います。

コラム

一番最初の実行時の注意点として、権限の承認が必要になります。

初めてスプレッドシートへ書き込みを行う時に、次のような表示がされます。このとき、権限を確認を押してください。

そうすると、つぎのような画面が出てきますが、無題のプロジェクト(安全ではないページ)に移動をクリックします。

クリックすると、次の画面に遷移します。

ここではじめて許可をクリックして権限の承認を行います。

これをやらないとコード経由での書き込みができないので、最初は戸惑いますが権限の承認を行ってください。

他にも具体例として、getRangeを変えて、次のように書いてみました。

コード.gs
function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(2,3).setValue("ここだよ~");
}

実行結果は次のようになります。

実行してみると、getRangeで指定した2行3列目に値が入力されていることを確認できます。

また、先ほどプログラミング概念をざっくり学んだので、繰り返し処理を実行してみましょう。

次のようにコードを書き換えてみます。

コード.gs
function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  for(let i = 1; i <= 10; i++) {
    sheet.getRange(i,1).setValue(i+"行目にいるよ");
  }
}

シートの入力値をすべて消した状態で、実行した結果は次のようになります。

繰り返し処理で、1行目から10行目まで入力されていることを確認できます。

getRangeで注意が必要なのは、1からはじまることです。0からはじめようとするとエラーになるので注意してください。

さらに、条件分岐を追加して今度は2列目に入力してみましょう。

次のようにコードを書きます。

コード.gs
function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  for(let i = 1; i <= 10; i++) {
    if(i % 2 == 0) {
      sheet.getRange(i,2).setValue(i+"行目は偶数だよ");
    } else {
      sheet.getRange(i,2).setValue(i+"行目は奇数だよ");
    }
  }
}

ifの条件式である i % 2 == 0というのは、iを2で割ったあまりは0という意味を表します。

%は剰余(割り算で割ったあまり)を求める演算子です。つまり、ここでは偶数ならifの分岐に入り、奇数ならelseの分岐に入ることになります。

これを先ほどのシートのままで実行すると次のようになります。

2列目に想定しているように偶数と奇数でそれぞれ入力されていることを確認できます。

コードを書いてGoogleスプレッドシートから値を取得してみよう

次は、すでにシートに入力されている文字を単純に取得してログに表示を行ってみましょう。

スプレッドシートに次のように入力した状態を作ります。

シートに入力されている文字(C4にある「すずきんち」)を取得してログに表示するコードは次のように書きます。

コード.gs
function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var value = sheet.getRange('C4').getValue();
  console.log(value)
}

実行結果は次のようになります。

入力されている文字をきちんと取得できていることが分かります。

シートの値を取得するためには、getRangeで指定した後に、getValueで取得できます。

これと繰り返し処理を組み合わせることで、シートに入力されている文字を変換して新たに作り変えることもできるようになります。

例えば、次のようなシートがあったとします。

今まで学んだことを活かして、コードを実行してA列にある漢字のよみがなをB列に入力するということをやってみます。

よみがなを取得するためには、よみたんAPIを利用してみます。

APIに関しての説明をみると、次のようにあります。

https://yomi-tan.jp/api/yomi.php?ic=UTF-8&oc=UTF-8&k=h&n=3&t=%E6%BC%A2%E5%AD%97

たとえば上記のURLにアクセスすると、UTF-8で「かんじ」と読みがなを返します。

「ic」クエリーは入力文字コード、「oc」クエリーは出力文字コードが入ります。文字コードは「UTF-8」「EUC-JP」「SJIS」「JIS」が使えます。デフォルトはUTF-8です。

「k」クエリー「h」を入れるとひらがな「k」を入れるとカタカナを返します(無指定だとひらがなが出ます)。

「t」クエリーには、変換したい漢字等が入ります。変換したい漢字等は、URLエンコード(%AD%E3のような形式)にしてください。

「n」クエリーには読み方の候補として出力する数を指定します。出力は「,」(カンマ)を区切りとして複数出力されます。ただし、読み方のパターンが存在しない場合、指定種類出力されないこともあります。

よみたんAPI v1: よみたん

この仕様にそって、APIリクエストを行いよみがなを取得して書き込む部分をGASで書くと次のようになります。

コード.gs
function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var value = sheet.getRange('A1:A4').getValues();
  for(let i = 0; i < value.length; i++) {
    var word = value[i];
    var url = "https://yomi-tan.jp/api/yomi.php?ic=UTF-8&oc=UTF-8&k=h&n=1&t=" + word;
    var context = UrlFetchApp.fetch(url).getContentText();
    sheet.getRange(i+1, 2).setValue(context);
  }
}

実行した結果は次のようになります。

サンプルでは、A1からA4の範囲の文字列を読み取るので、A1:A4と指定します。

getValuesで指定すると、二次元配列として文字列が返ってきます。

配列とは、複数の要素(値)の集合を格納・管理するのに用いられるデータ構造のことです。


1つの変数の中に複数の値の集まりを保持することができます。二次元配列は、二次元的に宣言された配列変数のまとまりです。

例のコードでいうと、valueの中身は、次のようになっています。

[ [ ‘情報’ ], [ ‘処理’ ], [ ‘勉強’ ], [ ‘始める’ ] ]

つまり、A1からA4まで読み取った値を、valueという変数の中に二次元的な箱の中にそれぞれ格納しているという状態になっています。

次のfor文では、0から A1からA4まで読み取った値の配列の長さ、つまり4までカウントアップするということを示しています。

for文の中に入ると、 var word = value[i]; と書くことで、wordという変数の中にvalueという配列のi番目の値を入れるということを示しています。例えば、i=0の場合だとvalue[0]は、’情報’という値がwordに格納されます。このようにしてAPIリクエストに必要なurlの文字列の作成を行っています。

UrlFetchApp.fetch(url)を利用してGETリクエストを行うことができます。


リクエスト後にgetContentTextをすることで、文字列としてレスポンスを取得できます。

最後は、先の章で行った書き込みをB列に行うことで値を取得して変換してから新たな値を書き込むということを自動で行うことができるようになりました。

Webスクレイピングをしてシートにデータを集める

WEBスクレイピングとは、ウェブサイト上から情報を抽出する技術のことです。

GASを利用して、今度はウェブサイト上から情報を抜き出すということを行ってみます。

注意

WEBスクレイピングは、明示的に禁止しているサイトもありますので、事前に利用可能かどうかを調べたうえで行ってください。

また、短期間でのアクセスなどはサイトに負荷がかかりますので、なるべく負荷をかけないように気を付けてコードを書きましょう。

管理人は繰り返し処理の最後に下記の関数を呼び出すようにして、遅延実行させるようにしています。

runDelay.gs
function runDelay(milliseconds){
 var start = new Date().getTime();
 var end=0;
 while( (end-start) < milliseconds){
     end = new Date().getTime();
 }
}

runDelay(5000)ぐらいがちょうどよいと思います

今回は、例として自分のサイト(このサイト)からタイトルを抜き出すということをやってみようと思います。

まずは、次の記事の詳細ページに行きます。

記事詳細ページに遷移したら、右クリックを押して検証をクリックします。

このような表示になると思うので一番下の検証を選択してください。

そうすると、右側にてElementsというタブでサイトのHtmlの構造を見ることができます。

ここから、抽出したい情報を探します。

今回は記事のタイトルを抜きたいので、次のような個所を探し出しました。

取得したい情報は、<h1 class=”entry-title single-title”>個人的にEpoxyを利用していく中で学んだ基本的な知識と使い方、差分更新とハマったことのまとめ</h1> であることを確認できました。

確認ができたら、Htmlデータから簡単に情報を抽出できるようになるParserライブラリを導入します。

導入は簡単で、まずはじめにGASのライブラリの隣のプラスボタンをクリックします。

クリックすると、ライブラリの追加ダイアログが出てくると思うので、先のライブラリのリンクにあるprojectsとeditの間にあるidを入れます。2021/11現在は、「1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw」です。次のようになります。

この状態で追加を押すと、ライブラリが追加されていることを確認できます。

Parserライブラリを追加できたので、サイト上からHtmlデータを抽出してシートへ入力するまでを行います。

次のようにコードを書きます。

コード.gs
function myFunction() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var url = "https://suzukinchi.page/2021/09/22/%e5%80%8b%e4%ba%ba%e7%9a%84%e3%81%abepoxy%e3%82%92%e5%88%a9%e7%94%a8%e3%81%97%e3%81%a6%e3%81%84%e3%81%8f%e4%b8%ad%e3%81%a7%e5%ad%a6%e3%82%93%e3%81%a0%e5%9f%ba%e6%9c%ac%e7%9a%84%e3%81%aa%e7%9f%a5/";
  var html = UrlFetchApp.fetch(url).getContentText();
  var title = Parser.data(html).from('<h1 class="entry-title single-title">').to('</h1>').build();
  sheet.getRange('A1').setValue(title);
}

このコードを実行した結果が次のようになります。

きちんと取得したかったデータが入力されていることを確認できますね。

コードの説明をしていきます。

まず、urlという変数で取得したいWebサイトのリンクをそのまま入れて格納しています。

この状態で、getContentTextをすると、htmlを含んだサイトの情報がhtmlという変数に文字列として格納されます。

このままでは、取得したい記事タイトルが抜けないので、先ほど導入したParserライブラリを使います。

取得したいデータは、 <h1 class=”entry-title single-title”>個人的にEpoxyを利用していく中で学んだ基本的な知識と使い方、差分更新とハマったことのまとめ</h1> だったので、 <h1 class=”entry-title single-title”></h1> に囲まれていることが分かります。

Parserライブラリでは、from(‘抜き出したい情報の前のHtmlタグ’).to( ‘抜き出したい情報の後のHtmlタグ’ )を指定することでfrom-toに一致する情報を抜き出してくれます。

これで、膨大なhtmlの文字列の中からtitleという変数に取得したい情報を格納し、シートに書き込むということを行っています。

Webスクレイピングの基本的な流れはこんな感じです。

あとは、サイトの規則性を見つけて繰り返し処理を行うことで抜き出したい情報を自動取得できるようになります。

いくつか注意点があり、muteHttpExceptionsのOptionをつけて例外処理を行ったり、正規表現で文字列を取り除いて整形したりする必要があったりします。

Webサイトから情報を抜き出してきても、自分が欲しいデータにはならないので、いくつかの手段を用いてデータを整えてやる必要がありますが、それについてはほかの記事にて解説をしようと思います。

まとめ

GASを用いてWebスクレイピングとデータ生成を行うのに必要なことは次の3つです。

  • SpreadSheetAppを利用して取得・入力を行う
  • Parserライブラリを用いてHtmlデータの抽出を行う
  • Webサイトから情報を取得するときは、データを整えてdelayさせて行う

今回は、初めての方向けに書いているのでプログラミング部分ではいくつか省略されていたり、最低限必要と定義したところしか使っていないのでコードとして適切ではない部分もあります。(きれいさや、意味合いとして)

ただ、同じように進めていただければ、たとえ初めてやったとしてもある程度やりたいことができるようになるのではないかとおもっています。

少しでも何かの参考になれば幸いです。

最後まで見ていただきありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA