スマホでもPCでも遊べます
抜けているのは一番右下のパネルです。
登場するのは可愛い動物たちですよ。
第1問目
3x3バージョン | 4x4バージョン |
第2問目
3x3バージョン | 4x4バージョン |
第3問目
3x3バージョン | 4x4バージョン |
第4問目
3x3バージョン | 4x4バージョン |
第5問目
3x3バージョン | 4x4バージョン |
動物園情報と自作ソフトに関する情報を、動物好きなフリープログラマがお届けします
3x3バージョン | 4x4バージョン |
3x3バージョン | 4x4バージョン |
3x3バージョン | 4x4バージョン |
3x3バージョン | 4x4バージョン |
3x3バージョン | 4x4バージョン |
とにかくurlwatchでうまくいかなかった部分ができるようになったスクリプトをPythonで書いてしまおうというのが目標です。
具体的にはこの3点でしょうか。これに加えてパフォーマンスがよければ言うことなしです。
urlwatchのソースを参考に、ファイルをWEBからとってくる部分と、ファイルを比較する部分に分けて考えていくことにしました。
そして、ファイルをWEBからとってくる部分については、ダウンロードした元ファイルを残すという方針があるわけですから、こちらは比較的簡単でした。
urlwatchを見習って、URLをハッシュ化したものをファイル名にすることにしました。
URLそのままですと、ファイル名に使えない文字が入ってしまう可能性があります。ファイル名に使えない文字というのはOSによって異なったりするので、変に置換すると収拾がつかなくなったりしますので、ハッシュ値のほうが取り回しやすいだろうと考えました。
次にフィルタ部分をどうするかを考えました。
ありがちなのは、例えば、「あなたは○人目のお客様です」とか「今日のお天気は晴れです」とかいった、更新をチェックする意味はないけれども、毎回のように更新されている部分をHTMLから取り外す処理です。
これは正規表現でやるにはかなり無理があります。
やはり正攻法で、HTMLをパースして、XPath式か、CSSセレクタのようなもので、読み取る範囲や削除する範囲を指定する方向で考えたほうがよいようです。
問題になるのは、動物園のWEBサイトがどれくらい正当なHTMLで記述されているかという部分です。
こればっかりはやってみないと分かりません。
とりあえず、WEBを検索して、2つのパーサが候補になりました。
一つはlxml。とにかく高速なのが売りです。
もう一つはbeautifulsoup。こちらはエラー含みのHTMLの処理が得意です。
安直に考えて、まずはlxmlで試して、どうしてもうまくいかなかったら、例えばそのサイトだけbeautifulsoupで処理すればとても効率がよさそうです。
というわけで、lxmlを使うところから始めたのでした。
lxmlを試すにあたって、まずは札幌市円山動物園のWEBサイトにアクセスしました。北から順、というか、都道府県コードでいくとどうしてもこの動物園がトップにきますので。
ここのWEBサイトはxhtmlでutf-8で書かれています。HTML-lintを通したところ、「53個のエラーがありました。このHTMLは 78点です。」という結果がでました。まずまずの出来ではないでしょうか。
で、これをlxml.htmlでパースすると、とりあえず、無事読み込んでくれているようです。
抽出したい部分をXPath式で指定すると、うまくいきます。
これはいけそうだというので、続いて旭山動物園。こちらはいきなりフレームレイアウトで文字コードはShift_JIS。これだけ人気の動物園でも、WEBサイトはこんなものなのですね。
どうもホームページビルダーを使っているようなのですが、WEBサイト担当の方とか、業務量的に大変ではないでしょうか。
こちらもlxml.htmlでパースしてみると、うまくいっているようです。
lxmlは、文字コードはHTML内に記述された、charsetを見てくれているようです。
と、ここで問題発生です。
出力が短すぎ。どうもHTMLを最後まで読み込んでくれていないらしいことが分かりました。
何もエラーなど出ていなかったはずなのですが。
lxmlの公式サイトを見ても、lxml.htmlの部分については、エラーハンドリングの記述がありません。
エラーがあるなら例外を吐いて止まってくれればいいのに、何も言わずに結果を切り詰めるなんて...
ちなみに、同じHTMLをbeautifulsoupでパースすると、文字化けします。が、これは文字コードを適切に指定すればうまくいきました。どうもbeautifulsoupは、HTML内のcharsetを見てくれていないようです。
文字コードの部分だけ解決すれば、beautifulsoupで最後までパースできているようなのですが、こちらはかなり遅いということが分かりました。
さて、困ったのは
といった2点で、これらについてはとりあえず、手動。すなわち、旭山動物園のサイトを処理する際には、beautifulsoupを使用して、あらかじめShift_JISという文字コードを与えてやるという対応にしたのでした。
それで先に進めるわけですから。
ここから先は同様で、まずlxml.htmlでパースをしてみて、うまくいかないようなら、beautifulsoupで試す、の繰り返しで、それぞれの動物園ごとの設定ファイルを書いていったのでした。
200サイトもあるので、この作業だけで3日くらいかかったのですけれど。
チェック対象のページ数からして、wgetとdiffでやっていくのが効率的だろうという考えには達しました。
しかしもちろん、手でwgetやdiffを動かすわけにはいきません。
wgetだけなら、あるいはdiffの実行までなら手動操縦もありえます、が、diffの結果のチェックまで目視でやるには無理があります。
少なくともdiffの結果は一つのテキストファイルにまとまっていてほしいものです。
それともう一つ、diffにかける前に、チェック対象外の部分を削除する方法も検討する必要があります。
このあたりの実験的なコード作成には、深く考えることなくPythonを選びました。
自分にとって一番手っ取り早いという理由です。
そして、チェック対象のページが決まっていて、Pythonを使うとなると、wgetすら必要はありません。
Pythonのurllib2を使うと、HTMLのダウンロードができてしまうからです。
しかし実は、そこまでやる必要すらないだろうと思っていました。
urlwatchというPythonスクリプトを見つけてあったからです。
HTMLの取得からdiffの適用まですべて自動で作業してくれる優れものです。
手でフィルターを書けば、diffにかける前にHTMLデータの不要な部分を削除しておくこともできます。
これで、動物園・水族館WEBサイトのウォッチが現実のものになる、と思ったものでした。
実際のところ、これでもがんばればどうにかなるレベルではありました。このブログ内で動物園・水族館のWEBサイトの更新状況を報告していた時は、このurlwatchを使用していたのでした。
しかし、urlwatchにはurlwatchなりの問題がありました。
urlwatchはすばらしいソリューションを私に提供してくれました。
けれども、十分といえる域には達していなかったのです。
まずurlwatchの挙動について、簡単に説明しておきます。
lynxを通した結果に対してdiffを適用することで、無関係なjavascriptの変更やcssの変更を気にする必要がなくなり、WEBサイト上の意味のある文言だけを比較できるわけです。
相手がセマンティックなWEBサイトならこれで十分ではありませんか。
しかし、動物園・水族館はそのような相手ではありませんでした。
まず、urlwatchは必ずしも日本語を正しく扱うことができません。UTF-8しかまともに扱えません。
Shift_JISやEUC-JPエンコーディングのサイトは文字化けしてしまいます。
文字化けしながらも新旧比較はできるので、サイトが更新されたということと、大体の更新箇所はわかるので、ブラウザでそのサイトを開いて実際の変更箇所を目視確認するという作業が必要になります。
動物園・水族館が日本語文字コードの問題について深く考えているはずもなく、普通にShift_JISやEUC-JPエンコーディングのサイトがあります。
そしてもう一つの大きな問題。
それは、urlwatchのセールスポイントの一つであるフィルタの使い方が難しいことです。状況によっては使い物になりません。
フィルタはlynxを通した後のテキストデータに対して適用されます。
フィルタが使えるには、この時点で文字化けしていないという前提が必要になります。これで半数近くのサイトではフィルタが機能しないことになりました。
さらに文字化けしていなかったとして、どのようなテキストデータが出力されているのか、ハッキングなしに確認する方法がないため、フィルタの書きようがありません。
対象のサイトをlynxで開いて実際に見てみるくらいしか手がありません。
そしてさらにやっかいなことに、そのフィルタが正しく動作しているかテストする方法が見当たりません。
urlwatchを動作させてしまうと、たとえフィルタが間違って書かれていたとしても、その間違ったフィルタを通した結果がキャッシュに書きこまれてしまいます。原本はどこにも残りません。
フィルタの間違いに気づいて修正したとしても、再実行することができないのです。
せめて原本がどこかに残っていてほしいものなのですが、urlwatchの仕様上、フィルタを通した後のファイルしか残されません。
また、動物園・水族館のサイトはセマンティックなものであるとは限りません。正規表現でのフィルタ作成すら困難です。親切に表示された今日のお天気をどうやって正規表現で切り抜けというのでしょうか。
というわけで、urlwatchをベースに、自分なりのツールを開発する必要性に迫られたのでした。
ちなみに、urlwatchで200のサイトを監視していたところ、次のような時間がかかっていました。
大体動物園・水族館が一日の業務を終えるのは午後6時くらいだろうと目途をつけていました。もちろん実際には、動物園・水族館の主業務はWEBサイトの更新ではありませんから、とっても遅い時間に残業してブログとか書いていらっしゃる職員さんがたくさんいることも今ではわかっています。が、こちらもこちらの作業時間の都合上、午後6時くらいというのが一つのタイムリミットでした。
で、午後6時を過ぎたあたりでurlwatchを走らせます。200のうち大体50から80のサイトで更新がかかっていることが分かります。
明らかに無関係な「あなたは○人目のお客様です」のような更新内容を除き、それらのサイトを一つ一つブラウザで開いて目視確認し、変更箇所を手でテキストエディタに入力していきます。
北海道から鹿児島まで、全データをチェックすると作業完了が早くて午後8時、遅い日は午後10時手前までかかりました。
ということは1回のチェックの作業に2時間から4時間をかけていたことになります。
これで給料がもらえるならまだしも。あるいは給料がもらえたとしても連日午後6時から10時まで拘束、かつ集中して作業というのはちょっときつすぎます。
urlwatchで監視を続けるのは非現実的と言わざるをえませんでした。