#librahack で頻出するループのFAQメモ

 
 まとめに反映させる前にメモ程度で。
 

中川さんの目的は「新着がどれか知る」ことだった。
だからクロールして「前日のクロール結果との差分」をとることが必要だった。
差分のとり方は「DBに新たにInsertされたデータ」を見ること。
TosCodeやISBNを主キー(重複不可)にしておけば,登録済みの本は新規にInsertできない(エラーになる)
DBのInsert文のエラーを捨てれば,新たに挿入されたデータが新規登録分,つまり新着
ロジック例
1:新着図書のトップページを見る(http://www.library.okazaki.aichi.jp/tosho/Newbook/0200.asp
2:カテゴリ別ページに移動する(http://www.library.okazaki.aichi.jp/tosho/Newbook/0201j.asp
3:書誌情報を見る(http://www.library.okazaki.aichi.jp/tosho/Asp/Syousai_g.asp?TosCode=00600643400&RetPage=../Newbook/0201j.asp
4:ISBNを主キーに,書名,著者名,出版社,出版年,内容紹介,予約人数,クロールした日付をデータベースに投げる
4−1:Insertに成功すれば未登録だったデータ=新着データ
4−2:Insertに失敗すれば登録済みデータ=既存データ
5:3:の書誌がなくなるまで実施
6:2:のカテゴリがなくなるまで実施

「DBに当日の日付のレコードが挿入されていれば,目的は達成できていた」ことに注意。
HTTPで取りこぼしがあった場合,翌日以降キャッチアップできる。
「今日入った書籍を今日取らなければならない」という厳密さは求められていなかった。
→少々取りこぼしても構わない,という品質で要求が満たされた

よって,
・HTTPレスポンスを確認する必要はなかった
 →一件も取れない等の状況があれば異常とみなす運用で十分だった
・データベースエラーはスキップするだけでよかった
 →同上

運用開始時にデータをまず取り込み,次に差分を取ることができているところまで確認していた
→3月の自宅からのアクセス

うまく動いたと判断できたのでさくらのレンタルサーバに移した
→以降,DBのアップデート件数を見て動作を確認

うまく取れなかった時,異常の原因を切り分けている
→最初の「URL変更」は,図書館にアクセスして仕様変更の事実をつかんでいる
→二度目の「アクセス遮断」では,図書館の仕様変更ではない→さくらに遮断されたと推測し,自宅からは問題なく処理できたことからそれでよしとした

図書館が検索できなくなったのは,クロール中の断続的な数分間のみ(ハズレクッキータイム
ハズレクッキーを食った人だけがアクセスできなかった。ハズレクッキータイムでも当たりクッキーを持っている人は正常に検索できた
中川さんがハズレクッキータイムの存在に気づくことができた可能性はゼロ
→クローラがデータを取ってこられていることから,異常が発生していることが認識できなかった
→仮に異常を検知したとしても,確認するのはクローラが停止した後であるため,ハズレクッキーを掴むことは無かったと推測できる

FAQ
・中川さんはクローラの動作をチェックしていなかったのか?
→していた。データベースが正常にアップデートされているかどうかで動作状況を見ていた。
・クローラがエラーハンドリングしていたら逮捕されずに済んだのでは?
→おそらく逮捕されてた。エラーハンドリングしていても500番しか帰っていなかったため,ふつうのHTTPクライアントなら絵エラーを捨てて次のデータをアクセスしにいくか,リロードするかのいずれかの動作を行う。
例:wget 取得エラー時のリロード回数はデフォルトで20回。404または接続が拒否された場合のみスキップ。
・ふつうエラーハンドリングするよね?
→厳密にデータを取得しなければならない場合はそう。しかし,エラーが発生した場合,たいていはリロードかスキップして次の処理を行う。404エラー(要求されたファイルが無い),接続拒否の場合は諦める。この動作を簡単に実装すれば,HTTPエラーレスポンスを無視して次のアドレスにアクセスすればよいことになる。なぜなら,404ならリロードする必要がない,接続拒否ならすべて拒否されるのでデータが取れないだけで終わる,その他のエラーについても同様。中川氏のクローラがデータ取得に失敗したときリロードしていたという情報が無く,エラーレスポンスをスキップしていたと考えると,「どうしても取得したい」とまで要求していなかったことが推測できる。逆に言えば,「とりあえず新着がわかればいいや」「ついでに予約人数取れば注目度合いもわかるよね」程度の要求を満たすのに必要な条件は実装されていたといえる。
・なんで図書館で検索できなくなってたことに気づけなかったのさ
→データベースに数件ずつでも格納されていればニーズが満たされたため。また,本来の新着件数が不明であるため,「新着件数が合わない」といった確認ができなかったため,一件も取れない日に初めて取得できていないことに気づけた。このときも,「途中で断続的に検索できていなかった」ことを検出できるだけの情報はなかった。
・動作中,相手のサーバの状況をちゃんと見ていればよかったのに
→無茶言うな
・ログを吐き出したりしなかったのは何故?
→前述の通り,エラーをスキップしていればよかったため。どんなエラーが出てもすべてスキップして次の処理をすればよい設計だったので,エラーをいちいち確認する理由が無かった。また,ごく普通に作ったWEBサービスなら,毎秒最大2回程度のクローラに耐えられなくなることは想定できず*1,新着件数も不明なため,1件以上のデータが取れているかどうかだけを見ればよかった。1件も取れていなかったときすぐ対応しただけでも褒められてしかるべきで,本来なら「今日は新着が無かったのかな」とそのまま放置することもありえた。

 

*1:http://d.hatena.ne.jp/Tariki/20100919/p2 を参照。普通,業務系で納入されるサーバ機が,その五年前のクライアントPCより性能が低いとは想定できない。