Google Script Api で Webサイトスクレイピング

移転しました。

特定サイトページの商品金額を抜き出してgoogle spreadsheetに書き込むために、スクリプトエディタの Google Script Api で Webサイトスクレイピング やることになったのでいろいろ Google Spreadsheetと連携できるGoogle Script Api で Webサイトスクレイピングできる方法をさぐってみた

HTMLの一部分を抜き出せる

Easy data scraping with Google Apps Script in 5 minutes ~ kutil.org

これだと1ページで何箇所か金額部分だけ抜き出すときなど、苦労しそう。

正規表現でごりごりスクレイピング

GoogleAppsScriptでWebスクレイピング

正規表現マスターしてると楽なんでしょうが、DOM操作できるようなライブラリが欲しいな、と。

XML Service Service

googleが提供している XML Parserあるんですが、

XML Service Service  |  Apps Script  |  Google Developers

以下ページを見ると有効なXMLしか扱えないようで、使い勝手が悪いようです。 * 既存のHTMLベージはだいたい有効なXML形式になってないですからね、下記ページでもそのことに触れられています

stackoverflow.com

結局どの方法がいいんだ? -> Xml.parse で解析したデータに、XmlService.parse して解析する

stackoverflowでも取り上げられてました。

stackoverflow.com

Xml.parse で解析したデータに、XmlService.parse して解析すると良さそうとのこと。 Xml.parse で有効なXML形式に変えてくれるんですね。

var page = UrlFetchApp.fetch(contestURL);
var doc = Xml.parse(page, true);
var bodyHtml = doc.html.body.toXmlString();
doc = XmlService.parse(bodyHtml);
var root = doc.getRootElement();

試しに上記で実際にPGうごかしてもたら body が複数配列で取れてしまう場合もあるらしいのでその場合は

var bodyHtml = doc.html.body[1].toXmlString();

などして切り抜ける

さらにDom操作しやすくする

以下のページのソースを拝借するとDom操作しやすくなりますので、こちらも使用するとさらに使い勝手よくなります。これでしばらくいけるんじゃないか説。

yoshiyuki-hirano.hatenablog.jp

サンプル

function sample() {
  
  // dom取得
  var contestURLBase = "https://www.makuake.com/discover/projects/search/";
  var contestURL = contestURLBase + "1";
  var page = UrlFetchApp.fetch(contestURL),
      doc = Xml.parse(page, true),
      bodyHtml = doc.html.body[1].toXmlString(), // なぜかbodyが2つとれるので[1]の方のみ対象
      xmldoc = XmlService.parse(bodyHtml),
      xml   = xmldoc.getRootElement(),
      projects = getElementsByClassName(xml, 'projectBox');
  
  for (var i = 0; i < projects.length; i++) { 
    var project = projects[i];
    // タイトル取得
    var item = getElementsByTagName(project, 'h2');
      Logger.log(item[0].getValue()); 
  }
  
}