Google SpreadsheetsにGreasemonkeyスクリプトとかの出力を保存する

もともとは普段みてるページにどれくらいメタデータ入ってるのか知りたいからログとりたくて、ログとるのはいいけどバックエンド用意するのめんどい、というのから。Google Spreadsheetsがわりと楽そうでした。

デスクトップアプリケーションですら、クラッシュレポータなんてものがついていて、ネットワーク経由でアプリケーションの異常を送信できるのだから、Greasemonkeyスクリプトでもおんなじことする、とかにも使えます。

記録用のシートを作る

シートにカラムは作っておく必要があります。シートに書かれてないパラメータは送ってもシートに記録されません。

キーとワークシートID

Google Spreadsheetsのドキュメントは、Excelでいうファイルがキーというもので管理されてて、ExcelでいうシートがworksheetIdというので管理されてます。これを知るのにAPI経由だとめんどくさいので、書き込みたいシートonlyでpublishして

more publishing optionsでRSSのURLをみるのが一番はやいです。

feeds/listの後にある長いやつがキーで、数文字のやつ(上のスクリーンショットだとod6)がworksheetIdです。

スクリプト

自分のシートに自分で記録する場合。自分のシートに人に書いてもらう場合は明示的な認証とか必要になってきてめんどくさくなります。

var key = 'o09670103056371318321.5625818402836282329';
var sheetid = 'od6';
function GoogleSpreadsheets(key, sheetid) {
  this.key = key;
  this.sheetid = sheetid;

}
GoogleSpreadsheets.prototype.toSpreadSheetXML = function (data) {
    var xml = ['<atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://schemas.google.com/spreadsheets/2006/extended">'];
    for (var name in data) {
      xml.push(
        '<' + name + '>' +
          data[name].replace(/</g, '<').replace(/</g, '>') + '</' + name + '>'
      );
    }
    xml.push('</atom:entry>');
    return xml.join("\n");
  }
GoogleSpreadsheets.prototype.addRow = function (data, onload) {
  var opts = {
    url: "http://spreadsheets.google.com/feeds/list/" + this.key + "/" + this.sheetid + "/private/full",
    method: "POST",
    headers: {
      "Content-Type": "application/atom+xml"
    },
    data: this.toSpreadSheetXML(data),
    onload: onload
  };
  GM_xmlhttpRequest(opts);
}
var sheet = new GoogleSpreadsheets(key, sheetid);
sheet.addRow( {
  url: document.location.href,
  generators: generators,
  relnext: relnext,
  relalternate: relalternate,
  relmeta: relmeta,
}, function (res) {
  console.log(res);
});

これを実行するとシートに1行ずつデータが追加されていきます。
Spreadsheetsの裏側にcomet入れてあるのかなんなのか、シートを開いているとデータが追加された瞬間にシートの表示にも反映される。

Google Spreadsheetsのドキュメントによると、10,000レコードまでしか記録できないのでそこは注意。

なんかあとFill formとかいうモードがあるらしいので、もしかしたらそれ使うと安全に(悪い人にカラム名を書き換えられたりすることなく)不特定多数に使ってもらえるのかも。

セルベースの場合

Spreadsheets APIにはデータの変更モードにrow-basedとcell-basedっていうのがあってcell-basedだとすごくめんどくさい。cell-basedのときはセルのバージョン(セルじゃなくてシートかも)をとってきて、それをパラメータにつけて送らないとだめ。

細かいこと忘れたけどZend_GDataが送信してたデータのログ貼っとく。一番難しいのはxmlどう書いたらいいのかわかんないことだった。

rawdata: <atom :entry xmlns:atom="http://www.w3.org/2005/Atom"><atom :category term="http://schemas.google.com/spreadsheets/2006#cell" scheme="http://schemas.google.com/spreadsheets/2006"/></atom><atom :id>http://spreadsheets.google.com/feeds/cells/o09670103056371318321.5625818402836282329/od6/private/full/R1C1</atom><atom :link href="http://spreadsheets.google.com/feeds/cells/o09670103056371318321.5625818402836282329/od6/private/full/R1C1" rel="self" type="application/atom+xml"/><atom :link href="http://spreadsheets.google.com/feeds/cells/o09670103056371318321.5625818402836282329/od6/private/full/R1C1/11ip" rel="edit" type="application/atom+xml"/><atom :title type="text">A1</atom><atom :updated>2008-04-03T08:32:39.842Z</atom><atom :content type="text">100</atom><gs :cell xmlns:gs="http://schemas.google.com/spreadsheets/2006" row="1" col="1" inputValue="100"/>
contentType: application/atom+xml
uri: http://spreadsheets.google.com/feeds/cells/o09670103056371318321.5625818402836282329/od6/private/full/R1C1/11ip

About this entry