Получение значения атрибута в Nokogiri для извлечения URL-адресов ссылок
У меня есть документ, который выглядит так:
<div id="block">
<a href="#" onclick="location.href='http://google.com'; return false;">link</a>
</div>
Я не могу получить Nokogiri, чтобы получить значение атрибута href
. Я хотел бы сохранить адрес в переменной Ruby как строку.
Ответы
Ответ 1
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"
Ответ 2
doc = Nokogiri::HTML(open("[insert URL here]"))
href = doc.css('#block a')[0]["href"]
Переменная href
присваивается значению атрибута "href"
для элемента <a>
внутри элемента с id 'block'
. Строка doc.css('#block a')
возвращает один массив элементов, содержащий атрибуты #block a
. [0]
указывает на тот единственный элемент, который является хешем, содержащим все имена и значения атрибутов. ["href"]
задает ключ "href"
внутри этого хэша и возвращает значение, которое является строкой, содержащей URL-адрес.
Ответ 3
Борясь с этим вопросом в различных формах, я решил написать себе учебник, замаскированный под ответ. Это может быть полезно другим.
Начиная с этого фрагмента:
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"
Если вы знаете, что ищете только одну ссылку, вы можете вместо этого использовать 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, я наткнулся на некоторые полезные ссылки при написании:
Ответ 4
doc = Nokogiri::HTML("HTML ...")
href = doc.css("div[id='block'] > a")
result = href['href'] #http://google.com
Ответ 5
data = '<html lang="en" class="">
<head>
<a href="#" onclick="location.href='https://example.com/9f40a.css'; return false;" media="all" rel="stylesheet" /> link1</a>
<a href="#" onclick="location.href='https://example.com/4e5fb.css'; return false;" media="all" rel="stylesheet" />link2</a>
<a href="#" onclick="location.href='https://example.com/5s5fb.css'; return false;" 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]