XPathの動作にまつわる試行錯誤

本題はこちら。XPathのよく分からない動作に悩まされた。

例えばこの記事(http://sankei.jp.msn.com/affairs/news/110320/dst11032018460075-n1.htm)に画像部分をくっつけようと考えたとき、指定すべきnextLinkとなるアンカーとpageElementになる記事本文+画像の部分の選択はそれほど難しくない。単純に選択するだけなら。

画像部分(例:http://sankei.jp.msn.com/affairs/photos/110320/dst11032018460075-p1.htm)も、nextLinkとpageElementの選択は問題じゃない。
問題になるのは、選択しすぎないようにすること。

際限なく画像を読み込むのをやめさせる

画像部分の、特にnextLinkに絡む構造を抜粋。

<div class="contentDisplayFix">
  <div id="MainContent">
    <div class="pager">
      <div class="pagerModule">
        <ul>
          <li>
            <a href="../../../affairs/photos/110320/dst11032019130076-p1.htm">&lt; 前の写真</a>
          </li>
          <li>
            <a href="../../../affairs/news/110320/dst11032018460075-n1.htm">記事を読む</a>
          </li>
          <li>
            <a href="../../../affairs/photos/110320/dst11032018460075-p2.htm">次の写真 &gt;</a>
          </li>
        </ul>
      </div>
    </div>
    <div class="PhotoNews">
      <div class="img450">
        <a href="../../../affairs/photos/110320/dst11032018460075-p2.htm">
          <span id="__r_photo_img__">
            <img src="../../../images/news/110320/dst11032018460075-p1.jpg" />
          </span>
        </a>
      </div>
    </div>
    (略)
  </div>
  (略)
  <div class="img90 imgleft">
    <a href="../../../affairs/photos/110320/dst11032018460075-p1.htm">
      <img src="../../../images/news/110320/dst11032018460075-s1.jpg" />
    </a>
  </div>
  <div class="img90 imgleft">
    <a href="../../../affairs/photos/110320/dst11032018460075-p2.htm">
      <img src="../../../images/news/110320/dst11032018460075-s2.jpg" />
    </a>
  </div>
  <div class="img90 imgleft">
    <a href="../../../affairs/photos/110320/dst11032018460075-p3.htm">
      <img src="../../../images/news/110320/dst11032018460075-s3.jpg" />
    </a>
  </div>
  (略)
</div>

大雑把にいって、「pager」か、「画像のリンク」か、「サムネイル」かの3択。どれを選んでも構わないのだけれど、どれを選んでも何らかの問題がある。
「pager」か「画像のリンク」の場合、画像ページの構造が記事に関係なく同じために、該当記事以外の画像かどうかに関係なく、際限なく読み込まれる。「サムネイル」の場合、際限なく読み込まれる問題は気にしなくて済むが、そもそも適切に選択しようと思ったら大変面倒くさい。XPath式で直接現在参照しているページのURLが拾えると便利なのだけれど、それは出来ないし、Javascriptで拾うことは出来るだろうけれどAutoPagerizeに手を加えてまでやりたいわけではないのでそれも除外。「画像のリンク」周辺から現在参照しているページの情報を取り出しても良いのだが、その場合はよほど「画像のリンク」を適切に選択するほうがやりやすい。

意図したものと違うリンクが選ばれる

それで、最初は「pager」で解決しようと考えた。「記事に戻る」リンクは同一記事に関しては共通で、つまりその記事に属するリンクのみ選択すれば良い。

<div class="pagerModule">
  <ul>
    <li>
      <a href="../../../affairs/photos/110320/dst11032019130076-p1.htm">&lt; 前の写真</a>
    </li>
    <li>
      <a href="../../../affairs/news/110320/dst11032018460075-n1.htm">記事を読む</a>
    </li>
    <li>
      <a href="../../../affairs/photos/110320/dst11032018460075-p2.htm">次の写真 &gt;</a>
    </li>
  </ul>
</div>

この例だと、dst以降の数字を上手く比較できれば解決できるはず……と考えて、次のようなXPathを書いた。実際に比較に使っているのは/photos/、/news/以降。

nextLink:     'id("MainContent")/div[@class="pager"]/div/ul/li[substring-before(substring-after(self::li/a/@href,"/photos/"),"-p") = substring-before(substring-after(preceding-sibling::li/a/@href,"/news/"),"-n")]/a',

が、しかし、動かない……! 何故か記事を読むのリンクが選択され、真っ当な読み込みがなされない。なんとなく、絶対パスで指定して比較すれば成功するのでは、と思ってそれっぽいXPathを試してみても、やっぱりダメ。

で、結局「画像のリンク」を使って指定。やってること自体はほとんど同じ。これが成功するので、上のXPathが動作しない理由がすっきりしない。

nextLink:     'id("__r_photo_img__")/ancestor::a[substring-before(substring-after(self::a/@href,"/photos/"),"-p") = substring-before(substring-after(self::a/span/img/@src,"/news/"),"-p")]',

まとめ

XPathの実装を確認しないとよく分からない。