2006 年 8 月 14 日 23 時 56 分

実際の日記を書き出す


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


さすがにお盆は忙しいなぁ。
時間がないので、今日はコード一色でいこう。
とにかく、ページの出力をしてみたいので、
コードを吐き出すところまで一気にいこう。

========== Main.js ==========

// 起動関数
function main() {

    try {

        // 名前なし引数
        var unnamed = WScript.Arguments.Unnamed;

        // 名前つき引数
        var named = WScript.Arguments.Named;

        // /? でヘルプ
        if (named.Exists("?")) {
            WScript.Arguments.ShowUsage();
            WScript.Quit();
        }

        // 引数チェック

        if (unnamed.length < 1 || unnamed.Item(0) == undefined
                || unnamed.Item(0).length == 0) {
            showErrorAndExit("エクスポート先のフォルダが指定されていません。");
        }
        var folder = unnamed.Item(0);

        if (!named.Exists("user") || named.Item("user") == undefined
                || named.Item("user").length == 0) {
            showErrorAndExit("メールアドレスが指定されていません。");
        }
        var user = named.Item("user");

        if (!named.Exists("password") || named.Item("password") == undefined
                || named.Item("password").length == 0) {
            showErrorAndExit("パスワードが指定されていません。");
        }
        var password = named.Item("password");
       
        var template = "default.html";
        if (named.Exists("template")) {
            template = named.Item("template");
            if (template == undefined || template.length == 0) {
                showErrorAndExit("テンプレートのファイル名が指定されていません。");
            }
        }

        _export(user, password, template, folder);
   
    } catch (ex) {
   
        showErrorAndExit(ex.message);

    }

}

// エクスポータの実装
function _export(user, password, template, outDir) {

    // フォルダ名の最後に \ をつける
    if (outDir.charAt(outDir.length - 1) != "\\") {
        outDir += "\\";
    }

    // テンプレートのマクロを表す正規表現
    // $title とか $$ とか
    var macro = /\$(\w+|\$)/ig;
   
    // 日記格納用変数
    var item;

    // item を参照するマクロ置換クロージャ
    var func = function (match, name) {
        switch (name) {
        case "$":
            return "$";
        case "title":
            return item.getTitle();
        case "body":
            return item.getContent();
        case "date":
            return item.getDate().format();
        default:
            return "";
        }
    };
   
    // テンプレートの拡張子を得る
    var match = template.match(/\.([^.]+)$/);
    var extension = match == null ? "html" : match[1];

    // テンプレートを読み込む
    var template = _readFileText(template, "UTF-8");


    // ログイン(接続前に 3000 ミリ秒待機)
    var session = new MixiSession(
            user, password, 3000);

    // 日記オブジェクトを作成
    var diary = new MixiDiary(session);

    // 日記列挙オブジェクトを作成
    var iterator = diary.iterator();

    // 項目を列挙
    while (iterator.hasNext()) {

        // 項目を取得
        var item = iterator.next();

        // HTML を作成
        var html = template.replace(macro, func);
       
        // ファイル名を決める
        var date = item.getDate();
        var filename = date.getFullYear().formatLeadingZeroes(4)
                + "-" + (date.getMonth() + 1).formatLeadingZeroes(2)
                + "-" + date.getDate().formatLeadingZeroes(2)
                + "-" + date.getHours().formatLeadingZeroes(2)
                + "-" + date.getMinutes().formatLeadingZeroes(2)
                + "." + extension;

        _writeFileText(outDir + filename, "UTF-8", html);

        // テストなので 1 件だけ
        break;
    }

}

// ファイルにテキストを書き出す
function _writeFileText(path, encoding, text) {

    // 省略時は UTF-8 を利用
    if (encoding == undefined) {
        encoding = "UTF-8";
    }

    // オブジェクトを作成
    var output = new ActiveXObject("ADODB.Stream");

    // ストリームを開く
    output.Open();

    // テキスト入出力モード
    output.Type = adTypeText;

    // 入出力の文字符号化
    output.Charset = encoding;

    // 本文を書き込む
    output.WriteText(text);

    // ストリームをファイルに流し込む
    output.SaveToFile(path, adSaveCreateOverWrite);

    // ストリームを閉じる   
    output.Close();
}

// ファイルのテキストを読み出す
function _readFileText(path, encoding) {

    // 省略時は UTF-8 を利用
    if (encoding == undefined) {
        encoding = "UTF-8";
    }

    // オブジェクトを作成
    var input = new ActiveXObject("ADODB.Stream");
   
    // ストリームを開く
    input.Open();

    // テキスト入出力モード
    input.Type = adTypeText;

    // 入出力の文字符号化
    input.Charset = encoding;

    // ファイルをストリームに流し込む
    input.LoadFromFile(path);
   
    // ポインタを最初の位置に戻す
    input.Position = 0;
   
    // ストリームの全テキストを取り出す
    var text = input.ReadText();

    // ストリームを閉じる   
    input.Close();
   
    return text;
}

// 自然数をゼロ拡張した固定長文字列で返す
Number.prototype.formatLeadingZeroes = function (digits) {
    var text = String(this);
    while (text.length < digits) {
        text = "0" + text;
    }
    return text;
};

// yyyy/m/d h:mm 式書式で出力
Date.prototype.format = function () {
    return this.getFullYear()
            + "/" + (this.getMonth() + 1)
            + "/" + this.getDate()
            + " " + this.getHours()
            + ":" + this.getMinutes().formatLeadingZeroes(2);
};

// エラーを出力して終了
function showErrorAndExit(message) {
WScript.StdErr.WriteLine(message);
WScript.Quit(1);
}

main();

========== end of Main.js ==========

説明は少なめだが、それほど新しいことはしていない。
最新の日記を 1 つだけ出力するように書いてみた。

出力先はカレントディレクトリ内の out フォルダとする。
今のところフォルダを作成する処理を入れてないので、
コマンド実行前に手動で作っておく。

では実行してみよう。

$ MixiExporter.wsf out /user:アドレス /password:パスワード

out フォルダに、2006-08-13-23-56.html ができた。
中身を開いてみると、「ライブラリ定数の利用」の日記が、
ちゃんと保存されていた。

現在、HTML ⇒ HTML への保存をしているので問題はないが、
XML や単なるテキストに書き出す場合、
以前話題とした HTML の参照を処理する必要はある。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.