このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
例外クラスの設計が終わったところで、
MixiSession クラスを自動化プログラム用に改変しよう。
今回盛り込むのは以下の要素だ。
・通信失敗、ログイン失敗などの例外処理
・連続リクエストを防ぐための待ち処理
まず、コンストラクタだ。
待ち時間はコンストラクタで外部から受け取る事にしよう。
引数に wait を追加して、ミリ秒単位の数値を受け取る。
そして、コンストラクタで行っているログインは、
失敗したときに例外を投げるようにする。
mixi の login.pl は、ログインの成否に関わらず、
HTTP ステータスは、「200 OK」として HTML を返却するが、
ログインに失敗した場合は Cookie を返却しない。
それを使ってログイン失敗を判定することにしよう。
では、コンストラクタを作ってみる。
// クラスのコンストラクタ
function MixiSession(mailAddress, password, wait) {
// リクエストを発行する間隔
if (wait == undefined) wait = 0;
this._wait = parseInt(wait, 10);
if (this._wait < 0) this._wait = 0;
// 内部で利用する XMLHttpRequest を作成
this._client = new XMLHttpRequest();
// ログイン用のパラメータを用意し、
var form = {
next_url: "/home.pl",
email: String(mailAddress),
password: String(password)
};
// ログイン処理にアクセスして Cookie を得る
this.post("https://mixi.jp/login.pl", form);
// ログインに成功すれば Cookie が返るはず
var cookie = this._client.getResponseHeader("Set-Cookie");
// Cookie が空ならログイン失敗
if (cookie.length == 0) {
throw new MixiError("ログインに失敗しました。");
}
}
wait パラメータは数値として _wait プロパティに入れる。
また、post メソッドを呼び出した後、
サーバが返却した Cookie を調べる。
Cookie は、Set-Cookie というレスポンスヘッダとして、
サーバから返却されるので、その中身を取得し、
中身がなければ失敗として例外を送出する。
fetch や post メソッドでは、HTTP による接続をする前に
単純に wait ミリ秒待機することにしよう。
本当は、同一サーバに対するリクエストの場合だけでいい。
そして、XMLHttpRequest#send で送信した後は、
サーバが返した HTTP ステータスコードを確認し、
200 系(=成功)以外の場合はエラーとする。
100 や 300 はとりあえず考えないことにしよう。
このあたりは手抜き実装ということで、まあいいでしょ。
// GET を発行して結果の HTML を返す
MixiSession.prototype.fetch = function (url, query) {
// リクエスト前に指定ミリ秒待機する
WScript.Sleep(this._wait);
// クエリパラメータを用意
var content = HttpUtil.encodeForm(query);
if (content.length > 0) {
content = "?" + content;
}
// GET で送信
this._client.open("GET", url + content, false);
this._client.send("");
// HTTP ステータスを検証
this._validateStatus();
// テキストを返却
return this._client.responseText;
};
// POST を発行して結果の HTML を返す
MixiSession.prototype.post = function (url, form) {
// リクエスト前に指定ミリ秒待機する
WScript.Sleep(this._wait);
// リクエストボディを用意
var content = HttpUtil.encodeForm(form);
// POST で送信
this._client.open("POST", url, false);
this._client.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
this._client.send(content);
// HTTP ステータスを検証
this._validateStatus();
// テキストを返却
return this._client.responseText;
};
// ステータスコードが 200 系でなければ例外
MixiSession.prototype._validateStatus = function () {
if (Math.floor(this._client.status / 100) != 2) {
throw new MixiError(
"サーバが想定外の応答を返しました。"
+ "[HTTP " + this._client.status.toString()
+ " " + this._client.statusText + "]");
}
};
ざっくりとこんな感じだ。
WScript には、Sleep メソッドがあるので、
これを使えば指定して時間だけ待機することができる。
Sleep ばスレッド自身を完全に止めてしまうが、
自動化プログラムでは特に問題とならないはずだ。
そして、エラーのチェックをしているのが、
_validateStatus メソッドだ。
サーバの返す HTTP ステータスコードは、
status プロパティに数値として格納されているので、
100 で割って切り捨てた値が 2 かどうかで判断する。
JavaScript の / は、小数演算なので、
Math.floor を使って切り捨てを行う必要がある。
因みに、statusText には、
サーバが返す HTTP ステータスの文字列が入っている。
例えば、200 OK なら、「OK」が statusText だ。
エラーの場合、理由が分かるようにメッセージに含めよう。
明日は、これを使って、mixi から、
ページの連続取得を試してみよう。
このスクリプトでは、サーバのページを取得する際に、
外部の CSS や JavaScript、画像などを取得しないので、
適切な待機時間をおいてアクセスするのならば、
ブラウザで mixi にアクセスするよりも、
サーバに発行するリクエストは少ないはずだ。