SITEINFOの書き方入門

SITEINFOは次のページへのリンクがどれかを示すnextLinkと、ページの中の本文部分を示すpageElementとでできています。

nextLinkは複数にマッチするXPathでも大丈夫です。複数の要素にマッチするときは、一番はじめにマッチしたものが使われます。よくページの上部と下部に同じナビゲーションが入っているページがありますが、そのときも片方だけの次のページへのリンクにマッチするようにXpathを書かなくてもAutoPagerizeがマッチしたものの中で一番はじめのものを使ってくれます。(実装はそうなってるけど仕様としてどうなのかは知らない)

AutoPagerizeのSITEINFOと同様な仕組みはLDRizeやLDR Full Feedでも用いられているので、書けるようになると他のところでも役に立ちますよ。他にもまじめにXSLTでバリバリ使われます。GRDDLとかも。 だからXPathがわかるようになるといいですよ。

XPathって何?(参考ページ)

JavaScript初級者から中級者になろう:十章第一回 XPathとは

じっさいにSITEINFOを作ってみましょう

前準備

SITEINFOのXPathを作るにはFirebug :: Firefox Add-onsがないと大変です。まずはFirebugをインストールしておいてください。

pageElement部分を見つける

FirebugをインストールしたらAutopagerizeしたいページを開いて、Firefoxのステータスバーに表示されるFirebugのアイコンをクリックして開きます。

開いたらウインドウの下のほうにFirebugのコンソールが出てきます。Console,HTML,CSSなどとタブが並んでいるのからHTMLを選んでクリックするとページのHTMLの構造を見ることができます。

http://f.hatena.ne.jp/ku0522/20080420234655

表示されているHTMLタグの上にマウスを移動させると、そのタグに対応する部分がブラウザのウインドウの中で強調表示されて、どこにあるのかがわかるようになっています。

pageElementにあたる部分をinspect elementして探す。

HTMLツリー上で対応する部分が表示されるので、それを見ながらfirebugコンソールで$x()を使ってXPathを調整する。$x()はFirebugの組み込み関数で、XPathを評価し、マッチするノードの配列を返します。例: $x("//input[@type='checkbox']")

おんなじことをnextLinkでもやる。

SITEINFOの書き方のこつ

次にデザイン、マークアップの観点から分類、それぞれのアプローチについて解説。

nextLink

"次のページ"へのリンクがあるもの

上の画像のはてなブックマークのページのように、今みているページのページ数に依存しないで、常に今みているページの"次のページ"へのリンクが決まった位置に存在するデザインのナビゲーションになっているときは、その次のページへのリンクを表すXPathを書くのが簡単です。

この場合、たいていは以下のどれかのケースに当てはまります。

rel="next"でマークアップされているケース

次のページへのリンクにrel="next"という属性がつけられていることがあります。このときは

//a[@rel="next"]
と書けるので精度が高く、変化に強いXPathになります。

特定の属性(classやidなど)が指定されているケース
id("nextpageID")/a
とか
//a[@class="nextpageClass"]
とか。 class指定は厳密に書くと
//a[contains(concat(" ", normalize-space(@class), " "), " nextpageClass ")]
次のページのリンクに特定の文言、画像などが含まれるケース

a[contains(text(), "")] で書けるけど、気まぐれだしi18nの面でもよくないです。operaのアプローチ。»とかいれるのもいいです。

なにもついてないけど右端に置かれているもの

ある要素を指定して、その最後の子要素を取得するといいです。

a[last()]なかんじ。

数字だけのもの

Userscripts.orgの検索結果のように、ページ番号だけが表示されて次のページへのリンクが独立して存在しないようなデザインのナビゲーションもあります。

このときはちょっと厄介です。

いまのページの次の要素を指定するケース

ふつうはいまのページだけ、わかりやすいように強調されていたりするので、それを目印にして b/following-sibling::a というかんじで指定できます。

pageElement

tableで組まれていてclassやidがなくて書きにくいケース

何番目のtableかで指定したり、cellpaddingの微妙な値で指定すると、変化に弱いXPathになってしまいます。

pageElementになる部分にだけ含まれている画像がある場合、その画像を基準にしてXPathを書きます。その画像の一番近い祖先のtableという書き方をすると、変化に強いXPathになります。

例: ヤフーオークション検索結果のpageElement

//img[contains(@src,"down.gif") or contains(@src,"up.gif")]/ancestor::table[1]

pageElementが複数のpでできていたりするケース

CNETの記事のように、長文を複数のページに分割しているものに多いタイプです。HTMLの組まれかたによって難しくなります。 following-siblingを駆使すると表現できることもあります。

following-sibling::node()[ following::kokomade ]

id属性が重複しないようにする

AutoPagerizeがページを継ぎ足すことにより、本来ページにひとつだけであるべき同名のid属性を持つ要素が複数存在するようになると、ページ内スクリプトや他のGreaseMonkeyスクリプトが正常に機能しなくなることがあります。こういった場合、id属性が重複しないようにXPathの書き方を工夫する必要があります。

たとえばはてなダイアリーの場合、id属性が"days"であるdiv要素の中に、class属性が"day"であるdiv要素が個別記事として入っています。この場合、単に

id("days")

ではなく、

id("days")/div[contains(concat(" ", @class, " "), " day ")]

としたほうが不具合は起こりにくくなります。

other tools

Perl

実行例

% scraper 'http://sample.example.com/path/to'

scraper> process 'id("pageElement")' , WARN

references

changed September 23, 2014 delete history edit