特定の単語を含むリンクをどうやって得るか
w3m-autopagerizeでは、サイトが登録されていない場合はOperaのfast forwardのように「次」が含まれているリンクをたどるようにしてある。
しかし、ここで問題発生。
# -*- coding: utf-8 -*- require 'nokogiri' html = <<EOH <html><body> <a href="next1.html">次</a> <a href="next2.html">次へ</a> <a href="next3.html"><b>次</b></a> </body></html> EOH nokogiri = Nokogiri::HTML.parse(html) nokogiri.xpath(%{//a[text() = "次"]}).map {|e| e["href"] } # => ["next1.html"] nokogiri.xpath(%{//a[contains(text(),"次")]}).map {|e| e["href"] } # => ["next1.html", "next2.html"] nokogiri.xpath(%{//a[contains(self::node(),"次")]}).map {|e| e["href"] } # => ["next1.html", "next2.html", "next3.html"] nokogiri.xpath(%{//a[self::node() = "次"]}).map {|e| e["href"] } # => ["next1.html", "next3.html"]
[text() = "次"] で「次」というテキストのリンクを得るし、 [contains(text(), "次")] で「次」を含むテキストのリンクを得ることはわかった。しかし、next3.htmlのように他のタグに囲まれていたらマッチしない。かといってすべてのA要素をスキャンしてinner_textにマッチさせるというのも効率悪そうだ。う〜ん…
XPathにはまだそんなに精通していないのでエレガントな解決方法があるかもしれない。
追記
text()をself::node()に置き換えるとうまくいきました。id:mayokara384さん、情報ありがとうございます。
さらに「self::node()」は「.」に省略できることがわかった。ぐっと簡単になった。
nokogiri.xpath(%{//a[.="次"]/@href}).map(&:content) # => ["next1.html", "next3.html"]