LoginSignup
1
2

More than 5 years have passed since last update.

Dirty Mashup用の小汚い秘技を貴女に

Last updated at Posted at 2015-05-21

【正しいのは最終出力だけ度:あたたたた!】

いや、秘技だけに。

後ろ指さされる系TIPSはまだまだ続くぜ!

ダダ漏れ系になっております。

そう言えば、私が、ほとんど「Hello, World」並にあらゆる言語で書いてきた、お手軽Dirty Mashup用の処理があります。(電車賃管理用に、Excel VBAですら書きました)

その名も、getBetweenAll。どんな環境でも手軽で高速にマッシュアップ用のコードが書きたいと思っても、必ずしもドキュメントツリーの解析ができるライブラリが手元にあるとは限りません。かといって、正規表現ではノイズをたくさん拾ってきてしまうので、ちょっと厳しいです。もちろん、このやり方でも、最後は正規表現で値を取り出すことが多いですが、どう考えても最初から正規表現では、思わぬものを拾いすぎます。

例えば、絞り込みのために、「最終更新日」~「<form」の中の、「<ul」~「</ul>」の中の、という風にタグもインライン要素も関係なく、単純に文字列で絞り込んでいくと、あら不思議、正規表現で簡単に取り出せるようになるのです。汚いですが、超手軽。うまく絞り込みのキーワードを見つけると、対象サイトががらりとリニューアルされても、案外耐えたりします。ラッキーロバストな性質、と呼びたい感じです。indexOfだけなので、ムダに速いです。ほんとは文字列コピーがされないような作りにできればさらにパフォーマンスが良いのですが(そもそもの出自は、遠い昔Cで書いたCGIの一部なので、メモリコピーなしの実装でした)、それやろうとすると頑張るか凝るかになりそうなので、これ以上はいらんかな、と思います。

と言うわけで、以下。CoffeeScript版とJavascript版です。

dirtymashup.coffee
http = require('http')

getBetweenAll = (buff,sstr,estr) ->
  result = []
  slen = sstr.length
  elen = estr.length
  spos = 0
  epos = -elen

  while 1
    spos = buff.indexOf(sstr,epos+elen)
    if spos == -1 then return result
    epos = buff.indexOf(estr,spos+slen)
    if epos == -1 then return result
    testspos = buff.indexOf(sstr,spos+1)
    while (testspos+slen <= epos)
      spos = testspos
      testspos = buff.indexOf(sstr,spos+1)
      if testspos == -1
        break
      if testspos+slen == epos
        spos = testspos
        break
    result.push(buff.slice(spos+slen,epos-1))

download = (url,next) ->
  buff = ''
  req = http.get url,(res) ->
    res.setEncoding 'utf8'
    res.on 'data',(xml) ->
      buff += xml
    res.on 'end', ->
      #console.log 'ok '+buff.length
      return next(buff)
  req.on 'error',(err) ->
    #console.log 'error: '+err
    buff = ''
    return next(buff)
  return

# test

url = 'http://qiita.com/mm-git/items/ced8482a41cd070c245a'

download url, (buff) ->
  result = getBetweenAll buff,'profile_image_url&quot;:&quot;','&quot;}</script>'
  for str in result
    console.log str
dirtymashup.js
(function() {
  var http;//import module
  var getBetweenAll;
  var download;
  var url;//test

  http = require("http");

  getBetweenAll = function(_this) {
    return function(buff, sstr, estr) {
      var elen;
      var epos;
      var result;
      var slen;
      var spos;
      var testspos;

      result = [];
      slen = sstr.length;
      elen = estr.length;
      spos = 0;
      epos = -elen;
      for (;1;) {
        spos = buff.indexOf(sstr, epos + elen);
        if (spos === -1) {
          return result;
        }
        epos = buff.indexOf(estr, spos + slen);
        if (epos === -1) {
          return result;
        }
        testspos = buff.indexOf(sstr, spos + 1);
        for (;testspos + slen <= epos;) {
          spos = testspos;
          testspos = buff.indexOf(sstr, spos + 1);
          if (testspos === -1) {
            break;
          }
          if (testspos + slen === epos) {
            spos = testspos;
            break;
          }
        }
        result.push(buff.slice(spos + slen, epos - 1));
      }
    };
  }(this);

  download = function(_this) {
    return function(url, next) {
      var buff;
      var req;

      buff = "";
      req = http.get(url, function(res) {
        res.setEncoding("utf8");
        res.on("data", function(xml) {
          return buff += xml;
        });
        return res.on("end", function() {
          return next(buff);
        });
      });
      req.on("error", function(err) {
        buff = "";
        return next(buff);
      });
    };
  }(this);

// test

  url = "http://qiita.com/mm-git/items/ced8482a41cd070c245a";
  download(url, function(buff) {
    var i;
    var len;
    var result;

    result = getBetweenAll(buff, "profile_image_url&quot;:&quot;", "&quot;}\x3c/script>");
    i = 0;
    len = result.length;
    for (;i < len;i++) {
      console.log(result[i]);
    }
    return;
  });
}).call(this);
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2