Разбор таблицы с использованием Nokogiri - PullRequest
3 голосов
/ 31 января 2011

Я бы хотел разобрать таблицу с помощью Nokogiri. Я делаю это так

def parse_table_nokogiri(html)

    doc = Nokogiri::HTML(html)

    doc.search('table > tr').each do |row|
        row.search('td/font/text()').each do |col|
            p col.to_s
        end
    end

end

В некоторых таблицах, которые у меня есть, есть такие строки:

<tr>
  <td>
     Some text
  </td>
</tr>

... а у некоторых это есть.

<tr>
  <td>
     <font> Some text </font>
  </td>
</tr>

Мое выражение XPath работает для второго сценария, но не для первого. Можно ли использовать выражение XPath, которое бы дало мне текст из самого внутреннего узла ячейки, чтобы я мог обрабатывать оба сценария?


Я включил изменения в мой фрагмент

def parse_table_nokogiri(html)

    doc = Nokogiri::HTML(html)
    table = doc.xpath('//table').max_by {|table| table.xpath('.//tr').length}

    rows = table.search('tr')[1..-1]
    rows.each do |row|

        cells = row.search('td//text()').collect {|text| CGI.unescapeHTML(text.to_s.strip)}
        cells.each do |col|

            puts col
            puts "_____________"

        end

    end

end

Ответы [ 3 ]

6 голосов
/ 31 января 2011

Используйте

td//text()[normalize-space()]

Это выбирает всех потомков текстовых узлов, не только для пробелов, любого потомка td текущего узла (tr, уже выбранного в вашем коде).

Или, если вы хотите выбрать все потомки текстовых узлов, выясните, являются ли они пустыми или нет:

td//text()

UPDATE

ОП сообщил в комментарии, что получает нежелательный td с содержимым всего лишь '&#160;' (он же неразрывный пробел).

Чтобы исключить также td s, содержимое которых состоит только из (одного или нескольких) символов nbsp, используйте:

td//text()[translate(normalize-space(), '&#160;', '')]
2 голосов
/ 31 января 2011

Simple:

doc.search('//td').each do |cell|
  puts cell.content
end
1 голос
/ 31 января 2011

Простой (но не СУХОЙ) способ использования чередования:

require 'nokogiri'

doc = Nokogiri::HTML <<ENDHTML
<body><table><thead><tr><td>NOT THIS</td></tr></thead><tr>
  <td>foo</td>
  <td><font>bar</font></td>
</tr></table></body>
ENDHTML

p doc.xpath( '//table/tr/td/text()|//table/tr/td/font/text()' )
#=> [#<Nokogiri::XML::Text:0x80428814 "foo">,
#=>  #<Nokogiri::XML::Text:0x804286fc "bar">]

См. XPath с необязательным элементом в иерархии для получения более СУХОГО ответа.

В этомОднако в этом случае вы можете просто сделать:

p doc.xpath( '//table/tr/td//text()' )
#=> [#<Nokogiri::XML::Text:0x80428814 "foo">,
#=>  #<Nokogiri::XML::Text:0x804286fc "bar">]

Обратите внимание, что ваша структура таблицы (и моя выше), у которой нет явного элемента tbody, недопустима для XHTML.Однако, учитывая ваше явное table > tr выше, я предполагаю, что у вас есть причина для этого.

...