2012-03-09 3 views
3

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

Например, в IRB, если я следующий в Руби 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 или есть лучший способ сделать это?

ответ

3

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

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 
} 

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

+0

Удивительный! Это работает намного лучше, спасибо! – akaDanPaul

+0

это работает, но вы должны избегать «и» в условном режиме, поскольку он предназначен для потока управления и имеет другой порядок операций, чем предполагаемый оператор '&&'. Кроме того, существует оператор '! ~', Который вы можете использовать вместо 'not = ~' – Ben

1

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

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

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

<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's tutorials очень хорошие. Пройдите через них, и они откроют все, что вам нужно знать.

Кроме того, есть много ответов на переполнение стека, обсуждающих эту проблему. Проверьте ссылки «Связанные» справа от страницы.

+0

Хороший ответ, функция карты для массива, безусловно, будет полезна для меня позже – abcde123483

+1

Этот ответ отключен от темы, вопрос состоял в том, чтобы захватить видимый внутренний текст всей страницы, а не кучу элементов. Даже используя 'body', OP не сможет избавиться от тега' javascript'. – sidney

+0

Не в теме? Едва. OP не использовал Nokogiri правильно, и вместо того, чтобы пытаться найти нужные узлы, он пытался сделать полный захват всего текста и в итоге оказался с JavaScript, который является текстовым. Вместо этого, путем выборочного выбора вишней требуемых узлов, те, которые фактически отображались, текст на экране можно было извлечь без мусора. OP хотел «лучший способ сделать это», и это подразумевает понимание того, как правильно извлекать данные, что и дает этот ответ. Ваш комментарий только подтверждает мою точку зрения. –

Смежные вопросы