スプレッドシートでスクレイピング

Googleスプレッドシート

はじめに

 GASには、WebページのHTMLを取り込む便利な関数が用意されています。
 UrlFetchApp.fetch(“URL”).getContentText(‘UTF-8’)
 この関数を使うと、HTMLの構造で取り込んでくれるため、目的のページの必要な部分だけを取り出す事が可能です。
 
 ただし、場合によっては上手く取り込めない場合がありますのでご了承ください。
 
 Webページから必要な部分を取り出す事を「スクレイピング」と言いますが、スクレイピングは文字列を上手く加工するテクニックが必要なるばかりでなく、Webページの構造が更新により変更されてしまった場合には、上手く機能しなくなります。
 更に、頻繁にプログラムでアクセスする行為はサイト側に迷惑がかかるばかりでなく、スクレイピング自体を禁止しているサイトもありますので十分に注意してください。
 
 ・スクレイピングにはHTML構造と文字列加工のテクニックが必要
 ・Webページの構造が変わると機能しなくなる
 ・サイト側に迷惑となるような行為はしない

プログラムの概要

 今回は、電車の遅延情報を取得する事を想定したプログラムです。
 新しいスプレッドシートを作って、適当な名前を付けたら、
メニューの「拡張機能」>「Apps Script」からGASのプログラミング画面を開いて、以下のコードを記述してください。

 具体的なプログラム作成・実行方法については、以下を参照してください。
 ・初めてのGAS

 本プログラムでは、url 変数に目的のWebページのURLを入れます。
どのページにするかは、「電車 遅延情報」などで検索して、良さそうなサイトを見つけます。
 
 その後、目的のページのHTMLソースコードを見て、切り出すための開始部分と終了部分を見つけます。
 
 切り出された文章から、HTML記号を削除してプレーンな文章にします。

 スプレッドシートのセルには、A列に日付時間、B列に取り出した文章を入れるようにします。
 入力は、最終行を取得するので、実行するたびに下に追加されていきます。

ソースコード

function getMySite() {
  // サイトURL
  const url = "***目的のサイトのURL***";
  let html = UrlFetchApp.fetch(url).getContentText('UTF-8');

  //文章の抜き出し
  const str = '</header>';
  let s1 = html.indexOf(str);
  html = html.substring(s1 + str.length);
  let s2 = html.indexOf('</div>');

  //HTML記号を削除
  let content = html.substring(0,s2).replace(/<("[^"]*"|'[^']*'|[^'">])*>/g,'');

  //日付を取得
  let myDate = new Date();
  myDate = Utilities.formatDate(myDate,'Asia/Tokyo','yyy/MM/dd HH:mm_ss');

  //最終行の取得
  let ssh = SpreadsheetApp.getActiveSpreadsheet();
  let sht = ssh.getSheetByName('HTML');
  let myRow = sht.getDataRange().getLastRow() + 1;

  //日付と文章をセルに入力
  sht.getRange(myRow,1).setValue(myDate);
  sht.getRange(myRow,2).setValue(content);
  sht.getRange(myRow,2).trimWhitespace();
  
}

プログラム解説

URLの設定

  const url = “***目的のサイトのURL***”;
 ここには、目的のサイトのURLを入れます。ここで指定したサイトにアクセスしますのでスクレイピングが禁止されているサイトは設定しないようにしましょう。

文章の抜き出し

  let html = UrlFetchApp.fetch(url).getContentText(‘UTF-8’);
 で htmlにページのソースが入ります。そこから必要な部分を抜き出します。

 抜き出すには、HTMLソースを見て、抜き出したい前後のタグを指定するようにします。

  const str = '</header>';
  let s1 = html.indexOf(str);
  html = html.substring(s1 + str.length);
  let s2 = html.indexOf('</div>');

 今回は上の下線部分に抜き出したいタグを指定しています。

HTML記号を削除

 HTMLのタグとなる<>の部分を削除するコードは以下のようになります。

 replace(/<(“[^”]“|'[^’]‘|[^'”>])*>/g,”)

 この書き方はHTML記号を取り除くときによく使われるので覚えておくと良いでしょう。

最終行の取得

 最終行は、現在のスプレッドシートの‘HTML’という名前のシートを取得して、
 sht.getDataRange().getLastRow()
 とすれば取得できます。

セルへの入力

 セルに値を入力するには以下のようにします。
 sht.getRange(myRow,1).setValue(myDate);
 
 getRange( , ) としてセルを指定。
 setValue( )  として、引数に値を入れます。
 
 最後の、trimWhitespace()は、セルの中の不要な空白やTabなどを削除してくれる命令になります。

 尚、セルへの文字列は5万行を超えるとエラーとなるようです。

まとめ

 今回は、スクレイピングの基本部分を書いてみました。
 やり方自体は難しくないのですが、Webページの構造によって、どこをどのように取り出すかで難易度が高くなります。
 実際に行うときは、スクレイピングしやすいページを選んで、HTMLソースを見ながら、抜き出すタグを見つけていく作業が大変です。
 スクレイピングの難しさはむしろこの部分で、思うようにいかない事もあるかと思います。
 また苦労して取り出せても、サイト側で変更をかけた場合、これまでのコードは通用しなくなります。
 「スクレイピングは水物」と考えた方が良いでしょう。

Googleスプレッドシートの可能性

 今回は、スクレイピング部分のみを取り上げましたが、Googleスプレッドシートでは、PCの電源がOFFでも定期的にプログラムを実行したり、その結果をメールで送信したりできます。

 このような一連の動作が実現できるのもGoogleスプレッドシートの強みと言えるでしょう。


コメント

タイトルとURLをコピーしました