Использование Ruby Mechanize links_with для захвата текста, но получения дополнительного контента

Когда я получаю группу ссылок с помощью метода Mechanize links_with, мне нужен только текст, показывающий ссылку, но я получаю ряд дополнительных символов:

links = @some_page.links_with(text: /V\s.*(BENCH|EARCX)|(BENCH|EARCX).*V/)

links.each do |link|
  link.text
end

Ссылки отображаются в моем браузере как «23409BENCH092834» и «20193BENCH092339», что именно то, что я хочу, однако, когда я иду, чтобы сохранить их в своей базе данных, они сохраняются как

\r\n\t\t\t\t\r\n\t\t\t\t\t 23409BENCH092834\r\n\t\t\t\t\r\n\t\t\t\t

Откуда взялись эти дополнительные символы и что они обозначают? Я пытался использовать на них text и to_s, но это не избавляет от этих случайных символов.


Я думаю, что это могут быть escape-коды, но если да, то как мне их удалить?


person bkunzi01    schedule 03.06.2015    source источник
comment
С regex я с этим справляюсь.   -  person JonB    schedule 11.06.2015


Ответы (1)


Вы не предоставили нам пример HTML, показывающий разметку, с которой вы работаете. Из-за этого вам очень трудно помочь. Не делай этого; Помогите нам помочь вам.

Mechanize использует Nokogiri для внутренних целей и может вернуть вам документ Nokogiri, так что вам нужно его получить. Оттуда вы попадаете во владения Нокогири, что дает вам больше контроля над поиском.

Использование Mechanize links_with находит все соответствующие ссылки в документе и возвращает их в виде массива Node, также известного как NodeSet. Они, вероятно, содержат много других узлов внутри них, которые отвечают за вкладки и возвращаемые значения, которые вы видите. Хотя links_with полезен, вы всегда должны знать, что что-то возвращает вам, чтобы вы могли правильно на это реагировать.

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

Учти это:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<p>foo</p>
|
<p>bar</p>
</body>
</html>
EOT

Извлечение текста из более высокого тега (родительского), чем тот, который вы должны, вернет все в этом родительском:

doc.search('body').text # => "\nfoo\n|\nbar\n"

Обратите внимание, что он улавливает разрывы строк и | между тегами. Это связано с тем, что text возвращает все текстовые узлы, а не только те, что находятся внутри дочернего тега. Поэтому очень важно четко указать, чего вы хотите.

Точно так же поиск только тегов p возвращает весь текст, найденный внутри них:

doc.search('p').text # => "foobar"

Это также обычно не работает, так как text объединяет весь текст в узлах, найденных в NodeSet, возвращаемом search, что обычно не очень полезно.

Вместо этого найдите нужный узел и получите его текст:

doc.at('p').text # => "foo"

at возвращает первый соответствующий узел и эквивалентен search('p').first.

Если вам нужен весь текст из узлов p, выполните итерацию по ним:

doc.search('p').map(&:text) # => ["foo", "bar"]

В более сложных документах нам часто приходится находить определенный ориентир в иерархии тегов и переходить к нему, а затем искать дальше, но это отдельная проблема.

Собрав все это вместе, вот пример, который помогает визуализировать то, с чем вы сталкиваетесь, и как с этим бороться:

require 'nokogiri'

doc = Nokogiri::HTML(<<EOT)
<html>
<body>
  <a href="http://example.com">
    <span class="hubbub">foo</span>
  </a>
  |
  <a href="http://example.com">
    <span class="hubbub">bar</span>
  </a>
</body>
</html>
EOT

Не делайте этого:

doc.search('body').text # => "\n  \n    foo\n  \n  |\n  \n    bar\n  \n"
doc.search('a').text # => "\n    foo\n  \n    bar\n  "

Сделай это:

doc.search('a span').map(&:text) # => ["foo", "bar"]

Or:

spans = doc.search('a').map{ |link|
  link.at('span').text
}
spans # => ["foo", "bar"]

Первый способ быстрее, потому что он использует код libXML2 для поиска соответствующих узлов span, определенных в селекторе CSS 'a span'. Второй медленнее, но более гибкий и позволяет вам использовать язык Ruby для итерации и просмотра тегов.

См. «Как избежать объединения всего текста с узлов при очистке." также.

person the Tin Man    schedule 15.07.2015