Ответ 1
почему вы не используете группы в своем шаблоне? например.
/http[s]?:\/\/(.+)/i
поэтому первая группа уже будет ссылкой, которую вы искали.
Я пытаюсь получить каждую внешнюю ссылку веб-страницы с помощью Ruby. Я использую String.scan
с этим регулярным выражением:
/href="#" onclick="location.href='https?:[^'; return false;"]*|href='https?:[^']*/i
Затем я могу использовать gsub для удаления части href:
str.gsub(/href=['"]/)
Это отлично работает, но я не уверен, насколько он эффективен с точки зрения производительности. Это нормально использовать, или я должен работать с более конкретным парсером (например, nokogiri)? Какой способ лучше?
Спасибо!
почему вы не используете группы в своем шаблоне? например.
/http[s]?:\/\/(.+)/i
поэтому первая группа уже будет ссылкой, которую вы искали.
Использование регулярных выражений отлично подходит для быстрого и грязного script, но Nokogiri очень прост в использовании:
require 'nokogiri'
require 'open-uri'
fail("Usage: extract_links URL [URL ...]") if ARGV.empty?
ARGV.each do |url|
doc = Nokogiri::HTML(open(url))
hrefs = doc.css("a").map do |link|
if (href = link.attr("href")) && !href.empty?
URI::join(url, href)
end
end.compact.uniq
STDOUT.puts(hrefs.join("\n"))
end
Если вам нужен только этот метод, немного его реорганизовать:
def get_links(url)
Nokogiri::HTML(open(url).read).css("a").map do |link|
if (href = link.attr("href")) && href.match(/^https?:/)
href
end
end.compact
end
Mechanize использует Nokogiri под капотом, но имеет встроенные тонкости для разбора HTML, включая ссылки:
require 'mechanize'
agent = Mechanize.new
page = agent.get('http://example.com/')
page.links_with(:href => /^https?/).each do |link|
puts link.href
end
Использование анализатора обычно всегда лучше, чем использование регулярных выражений для синтаксического анализа HTML. Это часто задаваемый вопрос здесь о переполнении стека, причем этот является самым известным ответом. Почему это так? Поскольку создание надежного регулярного выражения, которое может обрабатывать версии HTML в реальном мире, некоторые некоторые некоторые из них не очень сложны и в конечном итоге сложнее простого решения синтаксического анализа, которое будет работать практически для всех страниц, которые будут отображаться в браузере.
Я большой поклонник Нокигири, но зачем изобретать колесо?
Ruby URI модуль уже имеет способ extract
для этого:
URI::extract(str[, schemes][,&blk])
Из документов:
Извлекает URI из строки. Если данный блок задан, выполняется итерация через все согласованные URI. Возвращает nil, если задан блок или массив со спичками.
require "uri"
URI.extract("text here http://foo.example.org/bla and here mailto:[email protected] and here also.")
# => ["http://foo.example.com/bla", "mailto:[email protected]"]
Вы можете использовать Nokogiri, чтобы пройти DOM и вытащить все теги с URL-адресами или получить только текст и передать его в URI.extract
или просто позволить URI.extract
сделать все это.
И зачем использовать парсер, например Nokogiri, вместо шаблонов регулярных выражений? Поскольку HTML и XML можно форматировать по-разному и по-прежнему правильно отображать на странице или эффективно передавать данные. Браузеры очень прощают, когда дело доходит до принятия плохой разметки. С другой стороны, шаблоны регулярных выражений работают в очень ограниченном диапазоне "приемлемости", где этот диапазон определяется тем, насколько хорошо вы ожидаете изменений в разметке или, наоборот, насколько хорошо вы ожидаете, что ваш шаблон может пойти не так, когда представлены неожиданными шаблонами.
Парсер не работает как регулярное выражение. Он создает внутреннее представление документа, а затем просматривает его. Неважно, как выкладывается файл/разметка, он выполняет свою работу по внутреннему представлению DOM. Nokogiri релаксирует свой синтаксический анализ для обработки HTML, потому что HTML известен тем, что плохо написан. Это помогает нам, потому что с большинством неадаптируемых HTML Nokogiri может это исправить. Иногда я сталкиваюсь с чем-то, что так плохо написано, что Nokogiri не может исправить это правильно, поэтому мне придется немного подтолкнуть его, изменив HTML, прежде чем передать его Nokogiri; Я все равно использую синтаксический анализатор, а не пытаюсь использовать шаблоны.
Можете ли вы поместить группы в свое регулярное выражение? Это уменьшит ваши регулярные выражения до 1 вместо 2.