web-dev-qa-db-ja.com

Nokogiriで属性値を取得してリンクURLを抽出する

次のようなドキュメントがあります。

<div id="block">
    <a href="http://google.com">link</a>
</div>

href属性の値を取得するためにNokogiriを取得できません。アドレスをRuby変数に文字列として保存します。

29
Kreeki
html = <<HTML
  <div id="block">
    <a href="http://google.com">link</a>
  </div>
HTML
doc = Nokogiri::HTML(html)
doc.xpath('//div/a/@href')
#=> [#<Nokogiri::XML::Attr:0x80887798 name="href" value="http://google.com">]

または、divについてより具体的にしたい場合:

>> doc.xpath('//div[@id="block"]/a/@href')
=> [#<Nokogiri::XML::Attr:0x80887798 name="href" value="http://google.com">]
>> doc.xpath('//div[@id="block"]/a/@href').first.value
=> "http://google.com"
46
Michael Kohl
_doc = Nokogiri::HTML(open("[insert URL here]"))
href = doc.css('#block a')[0]["href"]
_

変数hrefは、ID _"href"_を持つ要素内の_<a>_要素の_'block'_属性の値に割り当てられます。 doc.css('#block a')行は、_#block a_の属性を含む単一の項目配列を返します。 _[0]_は、その単一の要素をターゲットにします。これは、すべての属性名と値を含むハッシュです。 _["href"]_は、そのハッシュ内の_"href"_のキーを対象とし、URLを含む文字列である値を返します。

27
seldomatt

さまざまな形でこの質問に苦労したので、私は答えとして偽装したチュートリアルを自分で書くことにしました。他の人に役立つかもしれません。

このスニペットから始めます:

require 'rubygems'
require 'nokogiri'

html = <<HTML
<div id="block1">
    <a href="http://google.com">link1</a>
</div>
<div id="block2">
    <a href="http://stackoverflow.com">link2</a>
    <a id="tips">just a bookmark</a>
</div>
HTML

doc = Nokogiri::HTML(html)

すべてのリンクを抽出する

Xpathまたはcssを使用してすべての要素を検索し、href属性を持つ要素のみを保持できます。

nodeset = doc.xpath('//a')      # Get all anchors via xpath
nodeset.map {|element| element["href"]}.compact  # => ["http://google.com", "http://stackoverflow.com"]

nodeset = doc.css('a')          # Get all anchors via css
nodeset.map {|element| element["href"]}.compact  # => ["http://google.com", "http://stackoverflow.com"]

しかし、より良い方法があります。上記の場合、検索は「単なるブックマーク」要素を返すため、.compactが必要です。より洗練された検索を使用して、href属性を含む要素のみを見つけることができます。

attrs = doc.xpath('//a/@href')  # Get anchors w href attribute via xpath
attrs.map {|attr| attr.value}   # => ["http://google.com", "http://stackoverflow.com"]

nodeset = doc.css('a[href]')    # Get anchors w href attribute via css
nodeset.map {|element| element["href"]}  # => ["http://google.com", "http://stackoverflow.com"]

特定のリンクを見つける

<div id="block2">内のリンクを見つけるには

nodeset = doc.xpath('//div[@id="block2"]/a/@href')
nodeset.first.value # => "http://stackoverflow.com"

nodeset = doc.css('div#block2 a[href]')
nodeset.first['href'] # => "http://stackoverflow.com"

1つのリンクのみを検索していることがわかっている場合は、代わりにat_xpathまたはat_cssを使用できます。

attr = doc.at_xpath('//div[@id="block2"]/a/@href')
attr.value          # => "http://stackoverflow.com"

element = doc.at_css('div#block2 a[href]')
element['href']        # => "http://stackoverflow.com"

関連するテキストからリンクを見つける

リンクに関連付けられたテキストを知っていて、そのURLを見つけたい場合はどうしますか?小さなxpath-fu(またはcss-fu)が便利です:

element = doc.at_xpath('//a[text()="link2"]')
element["href"]     # => "http://stackoverflow.com"

element = doc.at_css('a:contains("link2")')
element["href"]     # => "http://stackoverflow.com"

リンクからテキストを見つける

また、特定のリンクに関連付けられているテキストを検索する場合はどうなりますか?問題ない:

element = doc.at_xpath('//a[@href="http://stackoverflow.com"]')
element.text     # => "link2"

element = doc.at_css('a[href="http://stackoverflow.com"]')
element.text     # => "link2"

便利なリファレンス

広範な Nokorigi documentation に加えて、これを書いている間にいくつかの便利なリンクに出会いました。

15
fearless_fool
doc = Nokogiri::HTML("HTML ...")
href = doc.css("div[id='block'] > a")
result = href['href'] #http://google.com
4
bor1s
data = '<html lang="en" class="">
    <head>
    <a href="https://example.com/9f40a.css" media="all" rel="stylesheet" /> link1</a>
    <a href="https://example.com/4e5fb.css" media="all" rel="stylesheet" />link2</a>
    <a href="https://example.com/5s5fb.css" media="all" rel="stylesheet" />link3</a>
   </head>
  </html>'

上記のHTMLコードのサンプルを試してみましょう。

doc = Nokogiri::HTML(data)
doc.xpath('//@href').map(&:value)
=> [https://example.com/9f40a.css, https://example.com/4e5fb.css, https://example.com/5s5fb.css]
1
Gagan Gami
document.css("#block a")["href"]

ここで、documentは解析されたNokogiri HTMLです。

0
Oscar Albert