読者です 読者をやめる 読者になる 読者になる

技術のメモ帳

気が向いたときに書いてます

[GAS]YQL(Yahoo Query Language)を使って、スクレイピングをする

今回は、YQL(Yahoo Query Language)を使って、スクレイピングするサンプルを実装します。

YQLとは?

YQLはYahoo.comが提供している、あらゆるWeb上のリソースにアクセスすることができる開発者向けのAPIです。

YQL - Yahoo Developer Network

ざっくりとメリットを説明すると…

  1. Webリソースのレスポンスを加工できる
  2. XML, HTML, RSS, CSVJSONPに変換できる
  3. 登録せずとも利用できる
  4. キャッシュしてくれる

実際のコードを見た方が分かりやすいと思いますので、本家のチュートリアルのコードをアレンジした、動作サンプルを紹介します(Google Apps Scriptとなります)。

レスポンスをXMLからJSONに変換

YQLを使うと、rssxml)をjsonフォーマットに変換できます。

実行クエリは次のようになっています。

select * from rss where url="http://rss.news.yahoo.com/rss/topstories"

以下がサンプル関数です。

function topStories() {
  var response = UrlFetchApp.fetch('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20rss%20where%20url%3D%22http%3A%2F%2Frss.news.yahoo.com%2Frss%2Ftopstories%22&format=json'),
      items    = JSON.parse(response).query.results.item,
      result   = [];
  for (var i in items) {
    result.push({
      title: items[i].title,
      link:  items[i].link,
      desc:  items[i].description
    })
  }
  Logger.log(result);
}

JSONに変換され、それぞれの値が取得できていることが確認できます。

YQLを使ってスクレイピングする(XPath

xpathを指定し、対象のドキュメントの必要な部分のみを抽出した関数を書きます。

この関数を書く際、次のエントリを参考にしました。

Scrape Web Pages with YQL and Apps Script

サンプルでは、cookpadのレシピ検索結果から、レシピ名とリンクをXPathを指定して取得しています。

function scrapeCookpadTest() {
  scrapeCookpad('ビスコッティ');
}

function scrapeCookpad(recipe) {
  var url      = "http://cookpad.com/search/"+recipe,
      xpath    = '//div[@class="recipe-preview"]/div[@class="recipe-text"]/span[1]/a',
      query    = "select * from html where url = '" + url + "' and xpath = '" + xpath + "'",
      response = UrlFetchApp.fetch("http://query.yahooapis.com/v1/public/yql?format=json&q="+encodeURIComponent(query)),
      urls     = JSON.parse(response).query.results.a,
      result   = [];
  for (var url in urls) {
    result.push({
      title: urls[url].content,
      link:  urls[url].href
    });
  }
  Logger.log(result);
}

サンプルの実行結果は次の通りです。

YQLを使ってスクレイピングする(CSSセレクタ

なお、XPathではなく、CSSセレクタでも指定できます。

function scrapeCookpad(recipe) {
  var url       = "http://cookpad.com/search/"+recipe,
      cssselect = 'span.title a',
      query     = 'select * from data.html.cssselect where url="' + url + '" and css="' + cssselect + '"';
      response  = UrlFetchApp.fetch("https://query.yahooapis.com/v1/public/yql?format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&q="+encodeURIComponent(query)),
      urls      = JSON.parse(response).query.results.results.a,
      result    = [];
  for (var url in urls) {
    result.push({
      title: urls[url].content,
      link:  urls[url].href
    });
  }
  Logger.log(result);
}

jQueryに慣れている場合、XPathよりもCSSセレクタの方が簡単に指定できると思いますが、YQL自体に癖があるため、慣れを要する部分はありそうです(上記、resultsがネストしてしまう原因が分かりませんでした)。

YQLについては、詳しくはリファレンスをご覧ください。

簡単なことをやるには、サクッとできるのですが、仕様書が読みにくいため、しっかり利用しようとする場合、学習コストは少しかかるかもしれません。