ウェブ上のデータを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の下に配置してください。
同梱するようにしました。
URL集合の集合演算
union
"http://www.google.co.jp/" | "http://www.yahoo.co.jp/"
intersection
"http://www.google.co.jp/" & "http://www.google.co.jp/"
difference
"http://www.google.co.jp/" - "http://www.google.co.jp/"
symmetric difference
"http://www.google.co.jp/" ^ "http://www.yahoo.co.jp/"
Crawl Executeの内部で行われていること
新しいURL集合に現在のURL集合を追加。
現在のURL集合のそれぞれに対して、
- URLの抽出。
- 抽出したURLが新しいものならばテンポラリURL集合に追加。
テンポラリURL集合のそれぞれに対して、
- レスポンスコードの評価。200のみを対象とする。30Xなら追跡 など
- Content-Typeの評価。htmlかtextのみを対象とする。
- 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
- パーサのエラー回復
- テンプレート拡張
- エディタで候補推定
- クエリをサーバに保存する機能