GASでWebスクレイピングを行う方法

GASgetContentText,Parser,UrlFetchApp,UrlFetchApp.fetch,スクレイピング

Google Apps Script(GAS) を使ってWebページの情報をスクレイピングを行う方法をご紹介します。

Webスクレイピングとは

Webスクレイピングとは、指定したWebサイト(URL)にアクセスして情報を取得するためのプログラムです。

特段の事情がなければPythonやRubyを扱うことが多いですが、GASでもWebスクレイピングを実行することができます。特にGoogleアプリと連携したスクレイピング(スプレッドシートからURLを読み込む、取得情報をスプレッドシートに書き出す等)であれば非常に便利なのでぜひマスターしてみてください。

今回は、GASでWebサイトデータの情報を取得し、GAS上で加工してスプレッドシートに書き出すところまでをゴールとしてみます。

GASでWebスクレイピングを行うメリット

GASでWebスクレイピングを行う大きなメリットは以下の点です。

  1. 環境構築が不要
  2. トリガー設定で自動実行が簡単
  3. Googleサービスとの連携が容易
  4. 初心者が学びやすい言語

環境構築が不要

Webスクレイピングに使用されることが多いPythonやRubyはスクレイピング実行や分析用のパッケージが豊富に用意されていたり、実装したいコードのサンプルがネット上で見つかりやすいメリットがある反面、実行環境のセットアップに時間がかかり、初心者が試すにはハードルが高いのも事実です。

一方で、GASはGoogle Workspace(または個人向けGoogle アカウント)さえあれば、Web上で実行できるため、セットアップに時間がかかりません。スクレイピングを試してみたい初心者や、サクッとスクレイピングを実行したい方にとってGASでのWebスクレイピングは非常におすすめです。

実際にこの記事のサンプルコードを見ながら簡単に実行できるはずなので、興味がある方はぜひ試してみてください。

トリガー設定で自動実行が簡単

他の言語で定期的なスクレイピングを行ったり、特定の日時でスクレイピングするプログラムを実行するには、PCを常時起動したりサーバー側での操作が必要になります。

GASはGoogle Workspace上で実行できるプログラムですが、記述したスククリプトを定期的に実行するためにトリガー機能が用意されており、スクレイピングの自動化が非常にやりやすいです。

トリガーに関する機能は下記の記事でも紹介しています。

Googleサービスとの連携が容易

スプレッドシート/カレンダー/Gmail等、GASはほとんどのGoogleサービスと連携が可能です。

プログラミングを分析までGAS上で完結することも可能で協力なメリットですが、これらのサービスと連携して、スクレイピング実行結果を日次でスプレッドシートに書き出したり、それをGmailに添付して送るといったこともできます。

初心者が学びやすい言語

環境構築が必要ないので始めやすいというメリットもありながら、GASはjavascriptをベースにした言語で記述方法や関数の種類など、共通した要素が大きくあります。GASで基礎を学びながら、他言語への足掛かりにもできそうです。

事前準備:Parserライブラリのインストール

Webスクレイピングによって取得した情報を分析・処理するにはParserライブラリを使う必要が出てくるので、あらかじめライブラリをインストールしておきましょう。

Paserライブラリを利用するにはエディタ左部の「ライブラリ」の「+」ボタンをクリックして、ポップアップ出ててきたボックスの「スクリプトID」欄にParserライブラリのIDを入力「追加」ボタンをクリックして完了です。

*2022年8月現在の最新のIDでした。アップデートで変更になるので最新のIDを調べて入力してみてください。

1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw

Parserライブラリに関する詳細は下記の記事で詳細を解説しています。

Webスクレイピングのステップ

GASを使ったスクレイピングはざっくり下記のようなステップで進めます。

1.分析対象とするページを決める
2.スクレイピングを実行してHTTPレスポンスデータを取得する
3.取得したデータをテキストに変換する
3.データを集計/加工する(ここでParserライブラリを使用)
4.書き出す(保存する)

今回は、Yahoo!ニュースのトップページからトップニュースの情報(順位 / URL / タイトル)を取得することを例題として、「Paeser」ライブラリを使ったGASスクレイピングの進め方をページのソースコードを確認しながら具体的にご紹介します。

サンプルコード

今回のコードは長くなるため、先にコード全体をご紹介して一つずつ解説をしていきます。

\知識ゼロから学べる/

GASのWebスクレイピング入門講座 > icon

  let response = UrlFetchApp.fetch("https://news.yahoo.co.jp/");
  let text = response.getContentText("utf-8");
  // console.log(text);

  //トップニュースのブロックを抽出
  let topic_block = Parser.data(text).from('class="sc-ewMkZo jIVpTC"').to('</div>').build();
  // console.log(topic_block);

  //ulタグで囲まれている記述(トップニュース)を抽出
  let content_block = Parser.data(topic_block).from('<ul>').to('</ul>').build();
  // console.log(content_block);

 // ニュースリスト用の配列変数を宣言
  let newsList= new Array();

    // content_blockの要素のうち、aタグに囲まれている記述を抽出
     topics = Parser.data(content_block).from('<a').to('</a>').iterate();

    // aタグに囲まれた記述の回数分、順位/タイトル/URLを抽出する
    for(news of topics){

      //配列内のインデックス番号+1を取得(ニュース掲載順位として利用)
      let newsRank = topics.indexOf(news) + 1;

      //URL取得
      let newsUrl = news.replace(/.*href="/,"").replace(/".*/,"");
      //タイトル取得
      let newsTitle = news.replace(/.*class="sc-iELTvK ejAUqE">/,"").replace(/<.*>/,"");

      // 各ニュースページからカテゴリを取得
        let newsResponse = UrlFetchApp.fetch(newsUrl);
        let newsText = newsResponse.getContentText("utf-8");

        let newsCategory = Parser.data(newsText).from('トピックス(').to(')').build();


      // ニュース順位、URL、タイトルの組を作成
      let newsInfo = [newsRank, newsUrl, newsTitle, newsCategory];

      //ニュースリストに格納
      newsList.push(newsInfo);
   }

  console.log(newsList);

分析対象を決める

今回は例題としてYahoo!ニュースのトップニュースの情報を取得します。

UrlFetchAppでHTTPリクエスト実行

Google Apps Script(GAS)でHTTPリクエストを行うために、UrlFetchAppクラスが用意されています。fetchメソッドを使って引数のURLに対してHTTPリクエストを送ります。

UrlFetchApp.fetch(URL [, パラメータ])

  • URL:スクレイピング対象ページのURL
  • 戻り値:対象URLのHTTPレスポンス

HTTPResponse.getContentText([charset])

  • charset:文字コード(’UTF-8’、’shift-jis’ 等) ※デフォルトは「utf-8」
  • 戻り値:HTTP形式の情報が変換された文字列
  let response = UrlFetchApp.fetch("https://news.yahoo.co.jp/");
  let text = response.getContentText("utf-8");
  // console.log(text);

console.logで文字の羅列が返ってきたら成功です。

「Webページの情報を取得する」という操作だけれであればここで終了です。ここから、Parserライブラリを使ってWebページのテキストデータを取得したい情報に処理していきます。

\HTML構造を理解しながら学べる/

GASのWebスクレイピング入門講座 > icon

Paserライブラリで文字列を処理する

対象となる情報部分のHTMLテキストを抽出する

ここまではサイト全体のMTMLテキストを取得しただけなので、目的としていたトップニュースのリンクとテキストを抽出する作業に入ります。

まずは該当部分のMTML記述を確認してください。ブラウザでページにアクセスし「F12をクリック」または「ページ上で右クリック→検証」でデベロッパーツールを開くとソースコードを見ることができます。

コードを見てみるとトップニュースのブロックはsc-ewMkZo jIVpTCというクラス名がついたdivタグで囲まれています。また、そのブロックの中で各ニュースがulタグ・liタグで囲まれているのが確認できますね。このコード仕様に従って処理を記述することで、トップニュースの情報を抽出します。

Parser.data(text).from(startText).to(endText).build()

Parser.data(text).from(startText).to(endText).iterate()

  • text:処理対象の文字列
  • startText:抽出開始位置となる文字列
  • endText:抽出終了位置となる文字列

今回はclass属性の名前で指定するのが早いので、開始位置をclass="sc-ewMkZo jIVpTC"、終了位置を</div>としました。

  //トップニュースのブロックを抽出
  let topic_block = Parser.data(text).from('class="sc-ewMkZo jIVpTC"').to('</div>').build();
  // console.log(topic_block);

console.log(topic_block)で確認するとわかりますが、上記のままでは取得したいニュース以外のリンク等も含まれてしまってます。ニュースのリンクだけになるように、ulタグでさらに抜き出します。

  //ulタグで囲まれている記述(トップニュース)を抽出
  let content_block = Parser.data(topic_block).from('<ul>').to('</ul>').build();
  // console.log(content_block);
builtメソッドとiterateメソッド

Parserライブラリを使う際、buildメソッドではto~fromで指定された条件の最も最初に合致した文字列を一回のみ抽出iterateメソッドではto~fromで指定された条件に合致した文字列を合致した回数分抽出して配列に格納してくれます。

上記2つの例ではto~fromに該当する記載がいずれも1か所ずつしかないため、どちらのメソッドでも同じ結果が返ってきますが、次のパートのようにaタグをキーにしてすべてのニュースのリストを取得する場合などはiterateメソッドを使います。

とても便利な機能でスクレイピングを実施すると必ずと言っても良いほど利用するので、ぜひ押さえておきたいですね。

取得した情報を整理・加工する

■ニュース1つの情報が含まれる文字列に分けて配列に格納する

分析や書き出しができるように、ここまで抽出した文字列から記事単位の処理を行っていきます。ここでもParserが大活躍です。

最初にタイトルとURLの記述を抽出できるようにニュース単位の文字列の集合を取得します。 liタグaタグどちらでも分割することはできそうですが今回はaタグをキーにしてみます。先ほどと異なるのは、iterateメソッドで条件に該当する複数の文字列が配列として格納される点です。

    // content_blockの要素のうち、aタグに囲まれている記述を抽出
     topics = Parser.data(content_block).from('<a').to('</a>').iterate();
■ニュース単位で掲載順位 / タイトル / URLを取得する

ニュースごとの情報を取得する反復処理を行っていきます。

for(element of array){・・・}で、配列の要素数分の反復処理、かつelementをarray要素の値として扱えます。

    // aタグに囲まれた記述の回数分、順位/タイトル/URLを抽出する
    for(news of topics){
  ・・・
   }

Array.indexOf(element)でその要素の配列内における位置(インデックス)を取得できます。インデックスは0からなので、topics.indexOf(news) + 1とすることで掲載順位を得られます。

      //配列内のインデックス番号+1を取得(ニュース掲載順位として利用)
      let newsRank = topics.indexOf(news) + 1;

URLとタイトルはHTMLコードの構造をよく見て、該当する文字列を取得できるようにreplaceメソッドを使います。コードの内容によってはmatchメソッドを使って取得したい文字列を取得できるので状況に応じて使い分けてみてください。

      //URL取得
      let newsUrl = news.replace(/.*href="/,"").replace(/".*/,"");
      //タイトル取得
      let newsTitle = news.replace(/.*class="sc-iELTvK ejAUqE">/,"").replace(/<.*>/,"");

ニュース情報をリスト化する

最後にニュース順位、URL、タイトルを一つの配列として組み合わせ、反復処理外で宣言しておいたニュースリスト用の配列に格納していきます。

 // ニュースリスト用の配列変数を宣言
  let newsList= new Array();

    // aタグに囲まれた記述の回数分、順位/タイトル/URLを抽出する
    for(news of topics){

   ・・・・・

      // ニュース順位、URL、タイトルの組を作成
      let newsInfo = [newsRank, newsUrl, newsTitle];

      //ニュースリストに格納
      newsList.push(newsInfo);
   }

  //console.log(newsList);
実行結果

// console.log(newsInfo);

[ [ 1,’https://news.yahoo.co.jp/pickup/6437279′,’台風11号 夜にかけて沖縄に接近へ’ ],
[ 2,’https://news.yahoo.co.jp/pickup/6437280′,’都1万5428人感染 先週から1万人減’ ],
[ 3,’https://news.yahoo.co.jp/pickup/6437276′,’林外相 支援県議に教会系団体会長’ ],
[ 4,’https://news.yahoo.co.jp/pickup/6437281′,’偽の議員バッジで外務省侵入 逮捕’ ],
[ 5,’https://news.yahoo.co.jp/pickup/6437284′,’スシロー運営 マグロ偽装疑惑否定’ ],
[ 6,’https://news.yahoo.co.jp/pickup/6437283′,’プロ野球現役ドラフト 12月開催へ’ ],
[ 7,’https://news.yahoo.co.jp/pickup/6437286′,’丸山礼 容姿からかう物まねしない’ ],
[ 8,’https://news.yahoo.co.jp/pickup/6437273′,’回数未定? 消えた連ドラ打ち切り’ ] ]

うまく情報を取得できました。

発展:取得したリンクのページ情報を取得する

基本的な操作方法はここまでです。発展として上記で取得したURLをさらにスクレイピングして、各URL内の情報を取得してみます。下記のサンプルでは各ニュースページに存在するニュースカテゴリを取得しています

記事単位のURLを取得したループ内で、Yahoo!ニュースにアクセスしたのと同様にUrlFetchApp.fetchを実行して各ニュースページを読み込み、getContentTextメソッド呼び出し後に行いたい処理を実行します。実際にニュースぺージを見てみて、お好きな処理を考えてみてください!

      // 各ニュースページからカテゴリを取得
        let newsResponse = UrlFetchApp.fetch(newsUrl);
        let newsText = newsResponse.getContentText("utf-8");

        let newsCategory = Parser.data(newsText).from('トピックス(').to(')').build();

      let newsInfo = [newsRank, newsUrl, newsTitle, newsCategory];

      //ニュースリストに格納
      newsList.push(newsInfo);
実行結果

// console.log(newsInfo);

[ [ 1,’https://news.yahoo.co.jp/pickup/6437279′,’台風11号 夜にかけて沖縄に接近へ’,’国内’ ],
[ 2,’https://news.yahoo.co.jp/pickup/6437280′,’都1万5428人感染 先週から1万人減’,’地域’ ],
[ 3,’https://news.yahoo.co.jp/pickup/6437288′,’堺市の母子殺害事件 夫を公開手配’,’地域’ ],
[ 4,’https://news.yahoo.co.jp/pickup/6437276′,’林外相 支援県議に教会系団体会長’,’国内’ ],
[ 5,’https://news.yahoo.co.jp/pickup/6437284′,’スシロー運営 マグロ偽装疑惑否定’,’経済’ ],
[ 6,’https://news.yahoo.co.jp/pickup/6437283′,’プロ野球現役ドラフト 12月開催へ’,’スポーツ’ ],
[ 7,’https://news.yahoo.co.jp/pickup/6437286′,’丸山礼 容姿からかう物まねしない’,’エンタメ’ ],
[ 8,’https://news.yahoo.co.jp/pickup/6437273′,’回数未定? 消えた連ドラ打ち切り’,’エンタメ’ ] ]

まとめ

Yahoo!ニュースのトップニュースの「掲載順位」「タイトル」「URL」取得をお題として、Google Apps Script(GAS)を使ってスクレイピングし、Parserライブラリを使った分析方法について解説しました。

スクレイピングして取得/分析対象として抽出したデータをスプレッドシートに書き出す方法を下記の記事でご紹介しています。

\未経験から1時間で学べる/

GASのWebスクレイピング入門講座 >

その他のGASスクレイピングに関する解説記事はこちら。

この記事を書いた人

てつお
広告代理店出身、事業会社でWebマーケティングや開発の仕事をしている26歳です。プロフィール詳細はこちら
■Google広告認定資格|Google アナリティクス個人認定資格(GAIQ)|TOEIC920点