Hatena::Diary

素人がプログラミングを勉強するブログ

 

2008-12-19

livedoorReaderのフィードをマルコフ連鎖で作ったワードサラダと入れ換えるGreasemonkeyスクリプト

0.5の確率でフィードのitemを、それを元にマルコフ連鎖で作ったワードサラダと入れ換える。

gist: 37913 — GitHubにスクリプトを置いた。

インストールすると、フィードのitemが下のような支離滅裂な文章になる。

 MOONGIFT: » PHP開発が変わる!PHP実行環境をクラウド提供「Aptana Studio」:オープンソースを毎日紹介 (Markov)
元記事 | 2時間前
これの恐ろしい所はPHP開発し、実行ができてしまうのが、実行が、そのままAptana Cloudだ。Amazon EC2の実行がAptana Cloudだ。Amazon EC2の恐ろしい所はPHP開発が変わる!PHP実行がAptana Cloudだ。MOONGIFT: そして最近発表されたのだ。Amazon EC2のだ。MOONGIFT: » PHPのだ。Amazon EC2のライバルと言われている点に近い。MOONGIFT: そして最近発表されてしまう

// ==UserScript==
// @name           MarkovLDR
// @namespace      http://d.hatena.ne.jp/javascripter/
// @include        http://reader.livedoor.com/reader/
// @require        http://chasen.org/~taku/software/TinySegmenter/tiny_segmenter-0.1.js
// ==/UserScript==

function Markov() {
  this._dic = {};
  this._segment = null;
}

Markov.prototype.make = function (source) {
  var segmenter = new TinySegmenter();
  var ary = this._segment = segmenter.segment(source);
  var dic = this._dic;
  for (var i = 0, l = ary.length; i < l; ++i) {
    var word = ary[i % l];
    var next = ary[(i + 1) % l];
    if (word in dic) {
      dic[word].push(next);
    } else {
      dic[word] = [next];
    }
  }
  return this;
};

Markov.prototype.take = function (size) {
  var ary = this._segment;
  var dic = this._dic;
  if (!size) {
    size = ary.length;
  }
  function pickup(ary) {
    return ary[Math.floor(Math.random() * ary.length)];
  }
  var ret = [];
  var current = ary;
  for (var i = 0; i < size; ++i) {
    var s = pickup(current);
    ret.push(s);
    current = dic[s]
  }
  return ret.join('');
};

with (unsafeWindow) {
  LDR.register_hook('before_printfeed', function (feed) {
    if (feed._markov) return feed;
    feed._markov = true;
    feed.items.forEach(function (item) {
      if (Math.random() < 0.5) return;
      item.title += ' (Markov)';
      var div = document.createElement('div');
      div.innerHTML = item.body;
      item.body = new Markov().make(div.textContent).take();
    });
  });
}

参考にしたサイト:

マルコフ連鎖してみた - hitode909のダイアリー

イテレータ

Object.prototype.__iterator__を拡張する場合、その中でfor in構文を使うと無限に再帰してしまうので、下のようにする。

Object.prototype.__iterator__ = function __iterator__(isKey) {
  delete Object.prototype.__iterator__;
  for (var k in this) if (this.hasOwnProperty(k)) {
    yield isKey ? k : this[k];
  }
  Object.prototype.__iterator__ = __iterator__;
};

2008-12-16

Ad4Uでどのサイトの情報が抜かれているかを調べる

gist: 36272 — GitHubにHTMLファイルを置いた。downloadのリンクからダウンロードして解凍してhtmlファイルを開くか、

Macだったら、

$ curl http://gist.github.com/36272.txt > ad4u.html && open ad4u.html

とする。

2008-12-14

FastladderでLDRのクローラを使うGreasemonkey

追記:console.logとかが残ってたので、gistのほうは直しておいた。

no titleからインストール。

LDRの画面が狭くて嫌でFastladderに乗り換えようとしたけど、LDRと比較してクローラの巡回が遅くて困っていた僕のために。

// ==UserScript==
// @name           FastLDR
// @namespace      http://d.hatena.ne.jp/javascripter/
// @include        http://fastladder.com/reader/
// ==/UserScript==

var native_post = unsafeWindow.API.prototype.post;
var api_key = null;

GM_xmlhttpRequest({
  method: "GET",
  url: "http://reader.livedoor.com/reader/",
  onload: function (res) {
   var m = res.responseText.match(/^var ApiKey = "(.*)";/m);
   if (m) {
     api_key = m[1];
   } else {
     unsafeWindow.message("API key not found.(Please login to LDR)");
   }
  }
});

unsafeWindow.API.prototype.post =  function(param, onload){
  if (/^\/api\/config\//.test(this.ap)) {
    return native_post.apply(this, arguments);
  }
  unsafeWindow.console.log(api_key);
  var onload = onload || this.onload;
  var oncomplete = this.onComplete;
  if (typeof onload != "function") {
    onload = function() {};
  }
  param.ApiKey = api_key;
  setTimeout(GM_xmlhttpRequest, 0, {
    method: "post",
    url: "http://reader.livedoor.com/" + this.ap,
    data: unsafeWindow.Object.toQuery(param),
    headers: { "Content-Type" : "application/x-www-form-urlencoded" },
    onload: function(res) {
      oncomplete();
      unsafeWindow.API.last_response = res.responseText;
      var json = unsafeWindow.JSON.parse(res.responseText);
      if (json) {
        onload(json);
      } else {
        unsafeWindow.message("can't load data");
        unsafeWindow.show_error();
      }
    }
  });
  this.onCreate();
  return this;
};

2008-12-13

XBLとuserContent.cssとGreasemonkey

userContent.cssに

@-moz-document domain("reader.livedoor.com") {
  #right_body > .item {
    -moz-binding: url("ldr.xml#filter") !important;
  }
}

と書いて、同じchromeディレクトリに、ldr.xmlという名前で

<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl">
<binding id="filter">
<implementation><constructor><![CDATA[
if (/^[\s【]*(AD|PR|AD|PR)[\s】]*[::]/i.test(this.getElementsByTagName('h2').item(0).textContent)) {
  this.parentNode.removeChild(this);
}
]]></constructor></implementation>
</binding>
</bindings>

と書いて保存すると、livedoor Reader上でbindingが実行されて、広告エントリが自動削除される。

ということで、Firefoxでは拡張を入れなくてもGreasemonkeyみたいなことができる。

セレクタによってはDOMContentLoadedより先に実行されることがあるので、高速。

あと、DOMContentLoaded時に実行したい場合は、

:root {
  -moz-binding: url("binding.xml#exec") !important;
}
<?xml version="1.0"?>
<bindings xmlns="http://www.mozilla.org/xbl">
<binding id="exec">
<implementation><constructor><![CDATA[
document.addEventListener('DOMContentLoaded', function (e) {
 // do something
}, false);
]]></constructor></implementation>
</binding>
</bindings>

こんな感じにするといいかも。

2008-12-12

最後に更新されたファイルを調べる

こうすればいい。

require "pathname"

Pathname.glob("**/*").sort_by {|f| f.mtime }.last