ウェブページをクロールして結果をアレコレするツール

ウェブ上のデータをiPhoneなどの端末で閲覧するようなシーンで

現状で一番優れているのはinstapaperというアプリ(専用アプリあり。ブックマークレット1クリックでページを登録可能。自動同期可能)だと思うのですが、このアプリはブラウザコンポーネントベースであるため、大きなページで動作に問題があり、また数メガを超えるような場合、そもそも閲覧不可能であったりします。
それに加え、instapaper、並びにその他類似サービスはそもそも1ページのみを対象としたものであり、"あるblog上の特定のカテゴリの記事全てをあとで読みたい"などの複雑な要求を叶えることはできません。

そこで「クローラを記述し、結果をテキストで取得する」アプリを作ってみました

ある”範囲”のページを集め、ソートして結合、テキストを出力する、というだけですが、それなりに使えるシーンはあるのではないかと思います。
生成したテキストをiBunko、GoodReaderあたりで閲覧するとGoodです。

注意

このソフトウェアはDoS攻撃を推奨するものではありません。用法、用量を守って正しくお使いください。。
データは可能な限りキャッシュしています。が、超深いクロールなどはヤバいかもしれません…





ダウンロードはこちら
http://dl.dropbox.com/u/1651917/hosting/etc/cqpad/dropindex.html




記述は以下の簡単な言語で行います。

基本は以下の5つ。

URL

URLをダブルクォートで囲みます。

  "http://www.google.co.jp/"

複数のURLを与えることもできます。

  "http://www.google.co.jp/",  "http://www.yahoo.co.jp/"

前者のクエリの結果は、 "http://www.google.co.jp/" のURL集合。
後者は "http://www.google.co.jp/" と "http://www.yahoo.co.jp/" を足したURL集合です。

Crawl Execute

クロールの実行。
指定階層までクロールを繰り返します。

  "http://www.google.co.jp/"  >  1

このクエリの結果は、 "http://www.google.co.jp/" と、 "http://www.google.co.jp/ から深さ1" のURLを足したURL集合です。

Set Condition

クローラに条件を与えます。

  "http://www.google.co.jp/"  >  $ url /www/  >  1

このクエリの結果は、 "http://www.google.co.jp/" と、"「url /www/」という条件に合致する、 http://www.google.co.jp/ から深さ1" のURLを足したURL集合です。
フィールドは url, title, body, text を指定可能です。
また、フィールドは省略可能で、「$ /www/」は「$ url /www/」と解釈されます。

Filter

条件を与え、URL集合をフィルタします。

  "http://www.google.co.jp/"  >  1  >  # url /www/

このクエリの結果は、 "http://www.google.co.jp/" と、 "http://www.google.co.jp/ から深さ1のURLを足したURL集合" から、"「url /www/」という条件に合致しないURLを除いた" URL集合です。
フィールドは url, title, body, text を指定可能です。
また、フィールドは省略可能で、「# /www/」は「# url /www/」と解釈されます。

Sort

結果をソートします。

  "http://www.google.co.jp/"  >  1  > @ url ASC

このクエリの結果は、 "http://www.google.co.jp/" と、 "http://www.google.co.jp/ から深さ1" のURLを足したURL集合を、"urlについて昇順にソートしたもの" です。
オーダーは ASC, DESC を指定可能です。
フィールドは id, url, title, body, text を指定可能です。
また、フィールドは省略可能で、「@ ASC」は「@ url ASC」と解釈されます。
なお、デフォルトのソートは「@ id ASC」であり、これはURLの出現順の昇順です。




以下を使いこなせばあなたもエキスパートです。

高速化のために
  • Set Conditionのススメ

深さ1以上のクロールを行う場合は、極力Set Conditionを使いましょう。無制限なクロールの後にFilterを行うより高速です。

  • いきなり深いクロールを行わない

無駄なアクセスは極力省きましょう。クロールの後に、遅いフィールドへのアクセスがあればなおさらです。全てのURLに対し(初めてのアクセスであれば)コンテンツの取得が発生するので、場合によっては非常に時間がかかるでしょう。

  • 高速なフィールド - url, id

urlについてのCondition、idに対するSortは、値をメモリに保持しているため高速です。

  • 低速なフィールド - title, body, text

title, body, textについてのCondition、textについてのSortは、初回に必ずコンテンツの取得が発生し、キャッシュ後も最低一回のデータベースアクセスが発生するため低速です。

拡張

/ext 以下のpythonファイルを拡張としてロードします。
拡張により、結果のテキストをそのまま保存したりどこかに投げたり、柔軟にアレコレできます。
Jython標準ライブラリは同梱していませんので、必要ならJython環境をダウンロードし、/lib/Libとなるよう、その中のLibディレクトリを/libの下に配置してください。
同梱するようにしました。

Crawl Executeの内部で行われていること

新しいURL集合に現在のURL集合を追加。
現在のURL集合のそれぞれに対して、

  1. URLの抽出。
  2. 抽出したURLが新しいものならばテンポラリURL集合に追加。

テンポラリURL集合のそれぞれに対して、

  1. レスポンスコードの評価。200のみを対象とする。30Xなら追跡 など
  2. Content-Typeの評価。htmlかtextのみを対象とする。
  3. Set ConditionでセットされたConditionの評価。

新しいURL集合に、テンポラリURL集合に追加
現在のURL集合に、テンポラリURL集合を代入
が行われます。

Set Conditionの働き

「 URL > ... > 1 」をCrawlとします。このCrawlでは、セットされたConditionを使って、Crawl Executeの一階層ごとにフィルタが実行されます。

  "http://www.google.co.jp/"  >  $ url /www/  >  2  >  $ url /co\.jp/  >  2

このクエリでは計4回のクロールが行われますが、「$ url /www/」は4回に共通して、「$ url /co\.jp/」は最後の2回だけ適用されます。

Set Conditionの範囲

Crawlは「 ( URL > ... > 1 ) 」という形に括弧で囲むこともでき、括弧の中でSetされたConditionはその中だけで有効です。
つまり、Set Conditionは括弧を抜けると無効になります。

  (  "http://www.google.co.jp/"  >  $ url /www/  )  >  1

このクエリは、

  "http://www.google.co.jp/"  >  1

と等価です。

Condition

Set Condition, Filter, Sortで使用する条件(Condition)は、正規表現をベースとする論理演算での指定が可能です。
A か B

  /foo/ | /bar/

A かつ B

  /foo/ & /bar/

A でない

  !/foo/

オプション

  /foo/ig
SortでのCondition
  "http://www.google.co.jp/"  >  1  > @ title /Google/

このクエリの結果は、 "http://www.google.co.jp/" と、 "http://www.google.co.jp/" から深さ1のURLを足したURL集合を、titleについて、/Google/に合致するかどうかでソートしたものです。
フィールドは url, title, body, text を指定可能です。
また、フィールドは省略可能で、「@ /Google/」は「@ url /Google/」と解釈されます。

多重Sort
  "http://www.google.co.jp/"  >  1  > @ url ASC, title /Google/

このクエリの結果は、 "http://www.google.co.jp/" と、 "http://www.google.co.jp/" から深さ1のURLを足したURL集合を、urlで昇順、titleに/Google/で合致するかどうかでソートしたものです。

感想

いざ使ってみたらgoo blogはランダムなURLだわ、綺麗にタイトルがつけられてるサイトは滅多にないわ、漢数字のソートはバラバラになっちゃうわで思ったより使えないシーンが多かった。無念!

TODO

  • パーサのエラー回復
  • テンプレート拡張
  • エディタで候補推定
  • クエリをサーバに保存する機能