• Virtual Server 2005と IE8

    Active Directoryの挙動で確認したいことがあったので久しぶりにVirtual Server上の仮想マシンを起動しようとした。
    前回の起動から今回の起動の間にIE7→IE8に更新したためか、管理ページから仮想マシンをオンにできない!
    (Javascriptがエラーになる)

    なんじゃそりゃ~、ActiveXを使ってスクリプト経由で操作したらどうかなどと思案しつつ検索したらあっさり正解が
    気晴日記: IE8の[互換表示]ボタンとVirtual Server
    ・・・そりゃそうか。とにかく助かった。
    最初は互換表示ボタンがステータスバーの横並びにあるのかと思って見つけられずとまどった。アドレスバーの脇か・・

    Vista Ultimate x64
    VIrtual Server 2005 SP1
    IE8

  • Plaggerで TECH総研の連載をウォッチする

    セミコン見ル野のシブすぎ技術に男泣き! が大好きでTECH総研のフィードを購読している。

    のだけど、このフィードはなんだかエントリ数が少ない。今(2009/03/25 21:20)確認しても、25日9:00更新の二件だけが含まれている。
    使っているアグリゲータの巡回タイミングと合わないのか、時々とりこぼしがある。

    同連載に特化した過去記事一覧ページがあるのでこれをフィードにしたらとりこぼしもなくせそう。


    よろしい、ならばPipes

    と思ってさっそくYQLを書いてみる。class指定で1記事分を楽勝で特定できる。
    が、なぜかresultがnull。
    なんでだ、と思ったらクッキーを食べないと「クッキー受け入れて」ページが表示されるというオチ。

    仕方ないので自分のサーバでPlaggerを定期実行してフィードを生成しweb公開→これをアグリゲータに食わせる、という方針に。

    Config::PitとWeb::ScraperとPlaggerで24時間365日のゲーム監視体制 を参考(パクって)にWeb::ScraperしてYAMLで出力するperlスクリプトを用意。これをplaggerから呼び出してPublish::Feedでフィードに。

    ■perlスクリプト:scrape_semicon.pl
    #!/usr/bin/perl

    use utf8;
    use strict;
    use warnings;
    no warnings 'uninitialized';

    use URI;
    use WWW::Mechanize;
    use Web::Scraper;
    use DateTime;
    use YAML;
    use DateTime::Format::W3CDTF;

    my $uri = URI->new(q|http://rikunabi-next.yahoo.co.jp/tech/docs/ct_s01300.jsp?p=028|);
    my $mech = WWW::Mechanize->new(cookie_jar => {});
    $mech->show_progress(1);
    my $res = $mech->get($uri);
    if(!$res->is_success)
    {
    die $res->status_line;
    }

    my $result = scraper {
    process '//title', 'title' => 'TEXT';
    process '//td[@class="j-18-120"]', 'entry[]' => scraper {
    process '//a', 'title' => 'TEXT';
    process '//a', 'link' => sub {
    my($n) = @_;
    return URI->new_abs($n->attr('href'), $uri)->as_string;
    };
    process '//span' , 'date' => sub {
    my($n) = @_;
    my $t = $n->as_trimmed_text;
    if($t =~ /\(([0-9]+)\.([0-9]+)\.([0-9]+)\)/)
    {
    my($y, $m, $d) = ($1, $2, $3);
    $y += 2000 if $y < 100;
    my $dt = DateTime->new(
    year => $y,
    month => $m,
    day => $d,
    time_zone => 'local',
    );

    my $f = DateTime::Format::W3CDTF->new;
    return $f->format_datetime($dt);
    }
    return undef;
    };
    };
    }->scrape($res->decoded_content);

    $result->{link} = $uri->as_string;

    binmode STDOUT, ":utf8";
    print YAML::Dump $result;

    0;
    「link」を「@href」を指定せずにぐりぐりと文字列でreturnしている。
    過去記事一覧ページにおいて当該記事へのhrefは相対URLで書かれている。scrape()の第二引数にURIを渡して「@href」を用いればWeb:ScraperがURI->new_absしてくれるのだけど、この結果Publish::FeedにURIオブジェクトが渡ってくるためフィードエントリのリンク先が「URI::http=SCALAR(0xxxxxxx)」になってしまったから。
    (追記)Dump前に$YAML::Stringify = 1 で文字列で出力してURIオブジェクトに復元されないようにしたらいいみたい。
     
    ■yaml
    plugins:
    - module: Subscription::Config
    config:
    feed:
    - url: script:/path/to/scrape_semicon.pl
    - module: CustomFeed::Script
    - module: Publish::Feed
    config:
    format: Atom
    dir: /path/to/out
    filename: semicon.xml


    後はplagger -c YAMLを実行するシェルスクリプトを作って(loggerでログ出力したいので)、crontabに登録。


    一定の構造のyamlをSTDOUTに吐くところまでをtry&errorで繰り返して、後はplaggerで実行するだけ、という手順が楽でいい。


  • Pipesを使って RubyForgeのプロジェクトのリリースを RSSでウォッチする

    libxml-rubyのAPIの変更に気がつかずにはまったので、リリースをウォッチしようとRubyForgeのページを確認するも、フィードが見つからない(あったりして)。
    RubyForge全体のnewsのフィードと、プロジェクトのnewsのフィードはあった。
    だけどリリースとnewsは連動しているわけではないらしく投稿するかしないかは管理者次第のようだ。
    RubyForge: LibXML: ニュース
    RubyForge: LibXML: ファイルリスト
    じゃあPipesでも使ってみるかと気軽に始めたのだけどかなり手間取った。

    やりたいこと
    • libxml-rubyのリリース(「libxml-ruby-0.9.8」「libxml-ruby-0.9.7」部分)を抜き出してフィードに。
    • descriptionに上記文字列のリンク先(リリースノート)の内容を入れる
    最初のリリース一覧の抜出からしてなかなか意図した結果にならない。XPathでさくっと取り出してぇ、と試行錯誤。結局YQLで大枠を抜き出してOperators/Renameでちまちまとtitle要素/link要素にとり出すことに。

    select  * from html
    where
    url="http://rubyforge.org/frs/?group_id=494"
    and
    xpath="/html/body/div[3]/table/tr/td[2]/table/tr[position()>=4 and td/p/strong/text()]"
    得られたtrリストの直下の一番目のtdと二番目のtdを指定する方法でまた悩む。
    item.td.0.p.strong.a.href  →link
    item.td.0.p.strong.a.content →title
    item.td.1.p.strong →日時
    てな感じ。

    リリースノートの内容は、<pre>の中身でざくっと指定できたのでLoop+Fetch Pageの結果をdescriptionにassign。

    日時をフィードのpubDateにどう反映するのかがまたよくわからなくて、他の人のPipesを参考にLoop+Date Builderでitem.y:publishedにassignした。フィード出力の時点でpubDateに突っ込まれるようだ。

    ようやく出来たのが↓のPipes。Livedoor Readerに食わせてウォッチ中。
    http://pipes.yahoo.com/pipes/pipe.info?_id=78e1182d42024a179dfda9fc6f708550

    面白いしすごく便利だけど、やりたいことをPipes流の発想に変換するのがなかなか大変。。。
    YQLを使えばXPathでスクレイピング可能なのが救い。



  • libxml-ruby のI/Fが変わってた

    ふと気づいたらlibxml-rubyが0.9.8になってた。
    gemで0.8.3からupdateしたら動かないスクリプトが出てきた。
    XML::Document#to_s がエラーになる。

    CHANGESを見ると
    • 出力オプションをHash指定に変えた
    • エンコード名を文字列指定からLibXML::XML::Encoding下の定数指定に変えた
    ということらしい。
    前者はともかく後者は面倒だなー。というのもjrubyでも使うスクリプトなのでtransformer.setOutputProperty(javax.xml.transform.OutputKeys::ENCODING, エンコード名な文字列) とI/Fを合わせて文字列指定で作ってたから。

    libxml-rubyのマニュアルによればエンコード名文字列から定数を得るI/Fがあるみたいなんだけど、どうも期待した結果にならない。
    (マニュアル上はInput.s_to_encoding("UTF_8") なんだけどext/libxml/ruby_xml_encoding.cを見るとfrom_sのようで混乱する

    $ irb
    irb(main):001:0> require 'rubygems'
    => true
    irb(main):002:0> require 'libxml'
    => true
    irb(main):003:0> LibXML::XML::Encoding.from_s("UTF_8")
    => -1
    irb(main):004:0> LibXML::XML::Encoding.from_s("UTF-8")
    => false
    irb(main):005:0> LibXML::XML::Encoding.from_s("utf8")
    => false
    irb(main):006:0> LibXML::XML::Encoding.from_s("utf-8")
    => false
    irb(main):007:0> LibXML::XML::Encoding.from_s("utf_8")
    => -1
    irb(main):008:0>

    とりあえず文字列をいじくって定数名とみなしてお茶にごす。
    alias名が困るなー

          const_name = encoding_name.gsub(/-/, "_").upcase
    encoding = LibXML::XML::Encoding.const_get(const_name)
    doc.to_s(:encoding => encoding)

    環境
        - CentOS 5.2 i686
        - libxml2: 2.6.26-2.1.2.7
        - ruby: 1.8.5-5.el5_2.6
        - rubygems: 1.3.1
        - libxml-ruby: 0.9.8 (gem)

  • X40を SSDに換装した

    1.8インチHDDを8GBのCFに換装して快適に使って一年ちょい。
    Thinkpad X40のHDDをCFに換装してVista
    CF 8GBな X40に Vista SP1統合セットアップ
    魔が差したというかなんというかWindowsサーチ4.0をインストールしてしまったあたりから残容量が低空飛行。とうとう1月の定例updateで容量不足に。

    困ったなぁと思ってたら日立型I/Fで1.8インチなSSDが出たじゃないですか。
    容量も32GBと8GB環境から見れば4LDK級。
    PhotoFast SSD 1.8 IDE 32GB MLC
    月初に買いに出かけたのだけどすでに次回入荷待ち。買えないとなるとなおさら今欲しいんだ。

    ~以下自己責任でお願いします~
    MTRON製 SSD 1.8インチ ZIF(PATA)接続MSD-PATA3018-032ZIF2
    カッとなって、MTRON製 SSD 1.8インチ ZIF(PATA)接続MSD-PATA3018-032ZIF2と、ZIF変換アダプタを購入した。

    電源の違いがあるそうで通常の変換アダプタに手をいれないといけないらしい、のだけど若松で加工済みのものを入手。
    ブログ等を見ていると自分で改造してる方もいるようですげぇなと尊敬しつつお金で解決(^^)

    上記若松のページやこちらとリンク先のIBM公式保守マニュアルを見ながら、バッテリ、キーボード、上部ケースを外す。
    ネットで検索するとあっさり換装されているようなのだけど、不器用なのかとにかく上部ケースが外せなくて苦労した・・・・

    保守マニュアルの86ページの「1」の加減がわからなくて困った。結構大きなバキィって感じの音がして持ち上がったので「やってもうた~」と思ったけどセーフだった。
    「3」のラッチというのをケース底面側から見える銀色のツメ的な部分と勘違いしてひたすら責めてたんだけど、これは関係なかった。。
    HDDが収まるスペースにある枠も外す。

    上記の加工済み変換アダプタには、フレキケーブルが2つ同梱されてた。
    僕が買ったのだと、両端が青いのと片方が白いの。
    厚さが違うことに気がつかず「こんなすっぽぬける感じでいいんだろうか???」と悩んだがSSD側を白い方にしたら深く入った。SSDのコネクタ部分にあるロックをおろして固定。

    断線しちゃうんじゃないか、と思うぐらいケーブルをぐねっと曲げてなんとか納める。
    SSDと底面の間に隙間が出来るので緩衝材を突っ込んだ。

    で今度は、上部ケース、キーボード、HDDカバー、バッテリを元に戻す。
    電源を入れてBIOS画面でHDD認識を確認する。どうやら問題ないみたい。

    またVistaをセットアップするわけだけど、以前このX40用にSP1統合ディスクを作ったので再利用。
    これはあっさり完了。

    • ページファイルなし運用
    • ハイバネーション(休止)も無効に
    とりあえずlenovo公式から「ThinkVantage System update」を入手して、ドライバ周りを一度にそろえた。前回はCFだったから必要なものだけ個別にインストールしたけど32GBもあるから豪勢に。それになんだかんだで結構便利だSystem Update。

    後は直近使うアプリだけインストール。
    • アンチウイルス:
      いつものESET NOD32アンチウイルス V3.0。やはり軽快なのがいい。
    • RAMディスク:
      今度はGavotte。256MB割り当てた。これはもっと少なくてもいいかも。
      RAM PhantomはX60に入れたときにハングしたので不採用に。せっかく購入したけど。
    • ブラウザ:
      Firefox 3。これもいつもの。
    • ターミナル:
      TeraTerm。これもいつもの。
    • PDFリーダ:
      以前はFoxit ReaderだったけどAdobe Readerをおごってみた(^^
    • テキストエディタ:
      サクラエディタ
    • その他:
      TortoiseSVN。自宅サーバとの間の文書/ソースの出し入れに。
    CPUパワーとメモリのバランスと考えるとMTRON製 SSD 1.8インチ ZIF(PATA)接続MSD-PATA3018-032ZIF2のスペックを完全には引き出せないんだろうな~、という感じはする。
    体感する快適さではCFの時とあまり違いを感じないけど、ディスクの残量が17GBもあるのは精神衛生にいい(^^
    残量不足になってからX60常用(こっちもSSDに換装済み)に逃げてたけどまたまたX40復活。キーボードの感触はX40の方が好きなので地味にうれしい。

    インターネット側にデータ(ブックマークとかRSSリーダとかメール)を置いていることが功を奏しセットアップが簡単でいい。OSの準備が出来たらいつもの状態でシームレスに継続できるってすごいことだ。ネットを普遍に押し上げた(下げた?)人々に感謝だなぁ。