Nokogiri захватить только видимый inner_text - PullRequest
3 голосов
/ 09 марта 2012

Есть ли лучший способ извлечь видимый текст на веб-странице с помощью Nokogiri? В настоящее время я использую метод inner_text, однако этот метод учитывает много JavaScript как видимый текст. Единственный текст, который я хочу записать, - это видимый текст на экране.

Например, в IRB, если я сделаю следующее в Ruby 1.9.2-p290:

require 'nokogiri'
require 'open-uri'
doc = Nokogiri::HTML(open("http://www.bodybuilding.com/store/catalog/new-products.jsp?addFacet=REF_BRAND:BRAND_MET_RX"))
words = doc.inner_text
words.scan(/\w+/)

Если я ищу слово «функция», я вижу, что оно появляется в списке 20 раз, однако, если перейти к http://www.bodybuilding.com/store/catalog/new-products.jsp?addFacet=REF_BRAND:BRAND_MET_RX, слово «функция» не появляется нигде в видимом тексте.

Могу ли я игнорировать JavaScript или есть лучший способ сделать это?

Ответы [ 2 ]

6 голосов
/ 10 марта 2012

Вы можете попробовать:

require 'nokogiri'
require 'open-uri'

doc = Nokogiri::HTML(open("http://www.bodybuilding.com/store/catalog/new-products.jsp?addFacet=REF_BRAND:BRAND_MET_RX"))

doc.traverse{ |x|
    if x.text? && x.text !~ /^\s*$/
        puts x.text
    end
}

Я мало сделал с Нокогири, но я считаю, что это должно найти / вывести все текстовые узлы в документе, которые не являются пробелами.По крайней мере, это, по-видимому, игнорирует javascript, и весь текст, который я проверял, был виден на странице (хотя некоторые из них в выпадающих меню).

1 голос
/ 09 марта 2012

Вы можете игнорировать JavaScript, и есть лучший способ. Ты игнорируешь силу Нокогири. Нехорошо.

Вместо того, чтобы дать вам прямой ответ, вам будет полезно научиться "ловить рыбу" с помощью Нокогири.

В таком документе, как:

<html>
  <body>
    <p>foo</p>
    <p>bar</p>
  </body>
</html>

Я рекомендую начать с CSS-аксессоров, потому что они, как правило, более знакомы людям:

  • doc = Nokogiri::HTML(var_containing_html) проанализирует и вернет HTML DOM в doc.
  • doc.at('p') вернет узел, который в основном указывает на первый <p> узел.
  • doc.search('p') вернет NodeSet всех подходящих узлов, который действует как массив, в этом случае все <p> узлов.
  • doc.at('p').text вернет текст внутри узла.
  • doc.search('p').map{ |n| n.text } вернет весь текст в узлах <p> в виде массива текстовых строк.

Поскольку ваш документ становится все более сложным, вам необходимо углубиться в детали. Иногда вы можете сделать это, используя CSS-аксессор, такой как 'body p' или что-то подобное, а иногда вам нужно использовать XPath. Я не буду вдаваться в подробности, но есть отличные учебники и ссылки.

Уроки Nokogiri очень хороши. Пройдите через них, и они раскроют все, что вам нужно знать.

Кроме того, на Stack Overflow есть много ответов, обсуждающих проблему такого рода. Проверьте ссылки "Связанные" в правой части страницы.

...