Как использовать Mechanize для разбора локального файла - PullRequest
0 голосов
/ 07 февраля 2020

Я использую Ruby и Mechanize для анализа локального HTML файла, но я не могу этого сделать. Это работает, если я использую URL, хотя:

agent = Mechanize.new
#THIS WORKS
#url = 'http://www.sample.com/sample.htm'
#page = agent.get(url) #this seems to work just fine but the following below doesn't

#THIS FAILS
file = File.read('/home/user/files/sample.htm') #this is a regular html file
page = Nokogiri::HTML(file)
pp page.body #errors here

page.search('/div[@class="product_name"]').each do |node|
  text = node.text  
  puts "product name: " + text.to_s
end

Ошибка:

/home/user/code/myapp/app/models/program.rb:35:in `main': undefined method `body' for #<Nokogiri::HTML::Document:0x000000011552b0> (NoMethodError)

Как мне получить объект страницы, чтобы я мог искать по нему?

1 Ответ

1 голос
/ 07 февраля 2020

Механизация использует строки URI, чтобы указать, что он должен анализировать. Обычно мы использовали бы схему «http» или «https» для указания на веб-сервер, и в этом сильные стороны Mechanize, но доступны и другие схемы, включая «file ", который можно использовать для загрузки локального файла.

У меня есть небольшой HTML файл на рабочем столе с именем" test.rb ":

<!DOCTYPE html>
<html>
<head></head>
<body>
<p>
Hello World!
</p>
</body>
</html>

Запуск этого кода:

require 'mechanize'

agent = Mechanize.new
page = agent.get('file:/Users/ttm/Desktop/test.html')
puts page.body

Выходы:

<!DOCTYPE html>
<html>
<head></head>
<body>
<p>
Hello World!
</p>
</body>
</html>

Что говорит мне, что Mechanize загрузил файл, проанализировал его, затем получил доступ к body.

Однако, если вам не нужно на самом деле манипулировать формами и / или перемещаться по страницам, то Механизация, вероятно, не то, что вы хотите использовать. Вместо этого Nokogiri, который находится под Mechanize, является лучшим выбором для анализа, извлечения данных или манипулирования разметкой, и это зависит от c относительно того, какая схема использовалась или где файл фактически находится:

require 'nokogiri'

doc = Nokogiri::HTML(File.read('/Users/ttm/Desktop/test.html'))
puts doc.to_html

который затем выводит тот же файл после анализа.

Возвращаясь к вашему вопросу, как найти узел только с помощью Nokogiri:

Изменение test.html на:

<!DOCTYPE html>
<html>
<head></head>
<body>
<div class="product_name">Hello World!</div>
</body>
</html>

и работает:

require 'nokogiri'

doc = Nokogiri::HTML(File.read('/Users/ttm/Desktop/test.html'))
doc.search('div.product_name').map(&:text)
# => ["Hello World!"]

показывает, что Nokogiri нашел узел и возвратил текст.

Этот код в вашем примере может быть лучше:

text = node.text  
puts "product name: " + text.to_s

node.text возвращает строку:

doc = Nokogiri::HTML('<p>hello world!</p>')
doc.at('p').text # => "hello world!"
doc.at('p').text.class # => String

Так что text.to_s является избыточным. Просто используйте text.

...