Возьмите выходной браузером и инструментом такого типа, как wget
, curl
или nokogiri
, и вы найдете HTML-браузер, который может отличаться от исходного HTML-кода.
Браузеры в эти дни могут обрабатывать DHTML, Nokogiri этого не делает. Вы можете получить только текст, используя что-то, что позволяет просматривать контент без браузера, например, вышеупомянутые инструменты, а затем сравнить его с тем, что вы видите в текстовом редакторе, или то, что показывает nokogiri
. Не доверяйте браузеру - они, как известно, лгут, потому что хотят сделать вас счастливыми.
Вот быстрый взгляд на то, что исходный HTML содержит, генерируется с помощью:
$ nokogiri "https://www.ctgoodjobs.hk/jobs/part-time"
Nokogiri высадил меня в IRB:
Your document is stored in @doc...
Welcome to NOKOGIRI. You are using ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]. Have fun ;)
Counting хиты, найденного возвращается селекторных:
>> @doc.search('.job-title > a').size
30
Просмотреть результаты поиска:
>> @doc.search('.job-title > a').map(&:text)
[
[ 0] "嬰 兒 奶 粉 沖 調 機 - 兼 職 產 品 推 廣 員 Part Time Promoter (時 薪 高 達 HK$90, 另 設 銷 售 佣 金)",
...
[29] "Customer Services Representative (Part-time)"
]
Глядя на фактическое href
:
>> @doc.search('.job-title > a').map{ |n| n['href'] }
[
[ 0] "javascript:void(0);",
...
[29] "javascript:void(0);"
]
Вы можете сказать HTML не содержит ничего, кроме того, что Nokogiri говорит вам, так что браузер после обработки HTML, DHTML обработки и изменение страницы, которую вы видите, если вы используете что-то, чтобы посмотреть на HTML. Итак, короткое исправление, не доверяйте браузеру, если вы хотите знать, что сервер отправляет вам.
Вот почему скребок не очень надежный, и вы должны использовать API, если это вообще возможно.Если вы не можете, тогда вам придется сворачивать рукава и копаться в JavaScript и вручную интерпретировать, что он делает, а затем извлекать данные и анализировать их во что-то полезное.
Ваш код может быть очищен и упрощен. Я пишу это гораздо проще, как:
url = "https://www.ctgoodjobs.hk/jobs/part-time"
doc = Nokogiri::HTML(open(url))
links = doc.search('.job-title > a').map(&:text)
Использование search(...).text
является большой ошибкой. text
, применяемый к NodeSet, объединяет текст каждого содержащегося узла, что чрезвычайно затрудняет получение отдельного текста. Рассмотрим это:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<p>foo</p>
<p>bar</p>
</body>
</html>
EOT
doc.search('p').class # => Nokogiri::XML::NodeSet
doc.search('p').text # => "foobar"
doc.search('p').map(&:text) # => ["foo", "bar"]
Первый результат foobar
потребует быть разделены друг от друга, чтобы быть полезным, и если у вас нет специальных знаний о содержании, пытаясь выяснить, как сделать это будет основной головной болью.
Вместо этого используйте map
для повторения элементов и применения &:text
к каждому, возвращая массив текста каждого элемента.
См. Также "How to avoid joining all text from Nodes when scraping" и "Taking apart a DHTML page".
Пожалуйста, прочтите «[mcve]». Когда вы спрашиваете о коде, который вы написали, мы ожидаем минимальный код и минимальные входные данные в вопросе, который демонстрирует проблему. Не делая этого заставляет нас работать из огромных HTML-файлов и разделять их на полезные и важные части, теряя время, замедляя нашу способность помочь вам и потенциально отвлекаться от реальной проблемы. –