Initial Site

Initial Site

Initial Site

【難しくない】GASでwebスクレイピングして正規表現でデータを集める

  • ヨシモト  2018/11/02 17:18
dance_shoot_dance

営業部 ヨシモトです。

以前に、スプレッドシートを使って簡単なスクレイピングをしてみようという記事を書きました。
この記事ではスプレッドシートの関数(主にIMPORTXML関数)だけを使って簡単なスクレイピングをしてみよう、という内容でした。

今回はこれに近いことをGoogle Apps Script(以下、GAS)でやってみようという内容です。

スプレッドシート関数だけの場合はできることもある程度限定されますが、今回の内容は仕組みがわかれば広く応用が利きますのでぜひ覚えてみましょう。

 

今回おこなうこと

今回は、いまご覧いただいてる弊社のトップページに掲載されている記事の「タイトル」と「記事のURL」を取得してスプレッドシートに書き込みます。

 

どうやってやるか

topSS

このページに掲載されている記事のタイトルと、そのURLを取得します。
ちょっと厄介なのが、このページでは記事のタイトルの文字数が一定以上あると全て表示されていないことです。
とすれば、取得した記事URLのページから記事タイトルを取得することになります。

大まかな手順は、下記の通りです。

トップページの情報を全て取得する

その中から、記事のURLを正規表現を使って取得する

取得した記事URLにアクセスし、正規表現を使って記事のタイトルを取得する

これをトップぺージに掲載されている記事数分繰り返す

取得したURLとタイトルをスプレッドシートに書き込み

さらに嚙み砕くと基本的には、

正規表現でマッチさせたものを配列に格納する←これを繰り返す

となります。

 

以下にコードを記載します。

 

コード

function scrapSample() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
  var getUrl = 'http://www.initialsite.com/page/1';
  var content = UrlFetchApp.fetch(getUrl).getContentText('UTF-8');
  
  var itemRegexp = new RegExp(/<a href=.*?" class="n\d{1,2}">/g);
  var item = content.match(itemRegexp);
  var items = [];
  
  for (var i = 0; i < item.length; i++) {
    var itemURL = item[i]
      .replace('<a href=','')
      .replace(/"/g,'')
      .replace(/class=n\d{1,2}>/,'');
    items.push([itemURL]);
       }
  
  var titleRegexp = new RegExp(/<title>.*?<\/title>/);
  var titles = [];
  
  for (var j = 0; j < items.length; j++) {
    var itemCont = UrlFetchApp.fetch(items[j]).getContentText('UTF-8');
    var title = itemCont.match(titleRegexp)[0]
      .replace(/<\/*title>/g,'')
      .replace(' | 株式会社InitialSite','');
    titles.push([title]);
       }
  sheet.getRange(2, 1, titles.length, 1).setValues(titles);
  sheet.getRange(2, 2, titles.length, 1).setValues(items);
}

 

解説

コンテンツの取得

  var getUrl = 'http://www.initialsite.com/page/1';
  var content = UrlFetchApp.fetch(getUrl).getContentText('UTF-8');

UrlFetchApp.fetch() でトップページのURLへアクセスします。

これに対してgetContentText() することでトップページのテキストデータが取得できます。

参考

Class UrlFetchApp | Apps Script | Google Developers

取得したものをLogger.log(content ) で見てみるとこんな感じになってます。

contentSS

次はここで取得したcontent から正規表現を使って記事URLを抜き出していきます。

正規表現で記事URLを取得

  var itemRegexp = new RegExp(/<a href=.*?" class="n\d{1,2}">/g);
  var item = content.match(itemRegexp);
  var items = [];
  
  for (var i = 0; i < item.length; i++) {
    var itemURL = item[i]
      .replace('<a href=','')
      .replace(/"/g,'')
      .replace(/class=n\d{1,2}>/,'');
    items.push([itemURL]);
       }

new RegExp で記事URLの正規表現をitemRegexp として作成します。
トップページのソースを見てみると(Chromeブラウザなら「Ctrl+U」で見られます)、
各記事のURLはclassがn02,n03などのaタグなのがわかります。

これの正規表現を/<a href=.*?” class=”n\d{1,2}”>/として作成します。
n\d{1,2}は「nと1回以上、2回以下の数字」となり、
/正規表現/g のようにオプションにgを選択して、一致するものを全てをマッチさせるようにしています。
(n\d{2}でも大丈夫です)

参考

RegExp – JavaScript | MDN

正規表現の基本 – Qiita

var item = content.match(itemRegexp)で、
content のうち、この条件にマッチした部分をitem に配列として格納します。
item に格納したURLはaタグやclass名がついたままなのでreplace() でURLの文字列だけにしたものをitemURL へ代入します。
replace() にも正規表現が使えますのでこれを利用してタグ部分を空にします。

参考

String.prototype.replace() – JavaScript | MDN

items へpush() して二次元配列として格納します。
二次元配列に格納するのは、最後にスプレッドシートへsetValues() で書き込むためです。
(setValues は二次元配列でないと書き込めません)
これをfor文でitem の数だけ繰り返します。

この場合の二次元配列について

var items = []でitems という空の配列を用意しておきます。
items.push(itemURL) とすると一次元配列として格納されますが、
items.push([itemURL]) とすれば二次元配列として格納できます。

 

各記事URLへアクセスしてタイトルを取得する

  var titleRegexp = new RegExp(/<title>.*?<\/title>/);
  var titles = [];
  
  for (var j = 0; j < items.length; j++) {
    var itemCont = UrlFetchApp.fetch(items[j]).getContentText('UTF-8');
    var title = itemCont.match(titleRegexp)[0]
      .replace(/<\/*title>/g,'')
      .replace(' | 株式会社InitialSite','');
    titles.push([title]);
       }

記事ページではtitleタグを取得すれば記事タイトルが得られますので、titleタグの正規表現をtitleRegexp として作成しておきます。
UrlFetchApp.fetch() で先ほどitems に格納した記事URLへアクセスし、取得したテキストデータをitemCont へ代入します。
itemCont からtitleRegexp にマッチしたタイトルからタグをreplace()で取り除きtitleへ格納します。記事タイトルの後ろにサイト名(会社名)も併記されますので同じく取り除きます。
そして、こちらも記事URLと同じようにtitles へpush()して二次元配列として格納し、これをfor文でitemsの数だけ繰り返します。

ちなみにLogger.log(titles)  で見てみるとこんな感じです。

titlesSS

スプレッドシートへ書き込む

  sheet.getRange(2, 1, titles.length, 1).setValues(titles);
  sheet.getRange(2, 2, titles.length, 1).setValues(items);

最後にsheet.getRange() で範囲を指定し、setValues() 二次元配列に格納してある記事タイトルと記事URLを書き込みます。

これで完成です!

titleAndUrlSS

ちなみにトップページのURLは http://www.initialsite.com ですが、
 http://www.initialsite.com/page/1 としてあるのは、
最後のページ数を取得しておけば、/page/1 の1へ変数を代入し、for文で全ページ分取得できるようにするためです。
(今回はしてません。)

今回ご紹介した方法を応用して他のサイトでもスクレイピングできますし、
UrlFetchApp.fetch()へパラメータを渡せばログインが必要なサイトでも応用できるようになります。
ぜひいろいろ応用してみましょう。

 

TwitterWikipediaなど、スクレイピングが禁止されているサイトもありますので、他人・他社が運営するサイトの場合は必ず利用規約を読んでから行ってください。

また、スクレイピングの禁止が明示されていないサイトであっても、短時間で大量のリクエストを送ること等は管理者や利用者に迷惑がかかる場合もありますのでご注意ください。

 

今回参考にさせていただいたサイトはこちらです。
ありがとうございました。

Class UrlFetchApp | Apps Script | Google Developers

RegExp – JavaScript | MDN

String.prototype.replace() – JavaScript | MDN

正規表現の基本 – Qiita

 

その他、スプレッドシートやGASに関する記事はこちらからどうぞ。

GASを使ってGmailから本文の一部を抜き出す

スプレッドシート独自の便利な関数

QUERY関数の便利な使い方

スプレッドシートを使って簡単なスクレイピングをしてみよう

【GAS】正規表現を使ってGmailの本文から文章を抜き出す

【簡単】GASでスプレッドシートの送信リストからメールを送る

【GAS】正規表現を使って複数行の文章をGmailから抜き出す

【GAS】Gmailの添付ファイルを一括でGoogleドライブへ保存する

【難しくない】GASでwebスクレイピングして正規表現でデータを集める


コメントをどうぞ

ツールの記事

  1. dance_shoot_dance
    【難しくない】GASでwebスクレイピングして正規表現でデータを集める
  2. bg_kaitenzushi
    【GAS】Gmailの添付ファイルを一括でGoogleドライブへ保存する
  3. kid_job_boy_programmer
    【GAS】正規表現を使って複数行の文章をGmailから抜き出す
  4. createSSAsan
    【簡単】Google Apps Script(GAS)でメールを送る

おすすめ記事

  1. スギ花粉
    鼻がムズムズ目がカユカユな花粉症についてまとめてみた
  2. 『テレビ観ないんだよね…』と言うのがかっこいいと思っている人に告ぐ!
  3. 出典:無料壁紙:格闘技がテーマの写真やイラスト画像まとめ(格闘家・ブルースリー)
    ブルース・リーの出身地ってどこだかわかりますか?
  4. ハイビスカス
    ウチナーンチュが沖縄に帰った時に必ず行くお店10選+α
  5. イニシャルサイトコーポレートサイト
    コーポレートサイトをリニューアルしました
  6. なんでもQ
    相談Q&Aサイト「なんでもQ」開発中です!
  7. さんぽすフォトコンペ開催中
    今年もさんぽすフォトコンペ開催しました!

人気の記事

  1. クロックスの偽物と本物の違い
    クロックスの本物と偽物の違いを比べてみました
  2. ファミコン
    パズドラ、モンスト、白猫に続く次のゲームは…?
  3. konagaya_20150303
    日常でつい使ってしまう間違えやすい日本語
  4. Doctor scanning mri patient with MRI scanner machine technology
    MRI検査(造影剤付き)の感想と注意点