Очистить URL-адреса из Интернета - PullRequest
0 голосов
/ 24 июня 2011
<a href="http://www.utoronto.ca/gdrs/" title="Rehabilitation Science"> Rehabilitation Science</a>

В приведенном выше примере я хочу получить название отделения "Реабилитационная наука" и URL-адрес его домашней страницы "http://www.utoronto.ca/gdrs/" одновременно.

Может кто-нибудь предложить какие-нибудь умные регулярные выражения, которые бы сделали эту работу для меня?

Ответы [ 5 ]

4 голосов
/ 26 июня 2011

Нет никаких причин использовать регулярные выражения для этого вообще. Вот решение, использующее Nokogiri , который является обычным анализатором Ruby HTML / XML:

html = <<EOT
<p><a href="http://www.example.com/foo">foo</a></p>
<p><a href='http://www.example.com/foo1'>foo1</p></a>
<p><a href=http://www.example.com/foo2>foo2</a></p>
<p><a href = http://www.example.com/bar>bar</p>
<p><a 
  href="http://www.example.com/foobar"
  >foobar</a></p>
  <p><a 
    href="http://www.example.com/foobar2"
    >foobar2</p>
EOT

require 'nokogiri'

doc = Nokogiri::HTML(html)

links = Hash[
  *doc.search('a').map { |a| 
      [
        a['href'],
        a.content
      ]
    }.flatten
  ]

require 'pp'
pp links
# >> {"http://www.example.com/foo"=>"foo",
# >>  "http://www.example.com/foo1"=>"foo1",
# >>  "http://www.example.com/foo2"=>"foo2",
# >>  "http://www.example.com/bar"=>"bar",
# >>  "http://www.example.com/foobar"=>"foobar",
# >>  "http://www.example.com/foobar2"=>"foobar2"}

Возвращает хэш URL-адресов в виде ключей со связанным содержимым тега <a> в качестве значения. Это означает, что вы будете захватывать только уникальные URL, выбрасывая дубликаты. Если вы хотите, чтобы все URL использовали:

links = doc.search('a').map { |a| 
    [
      a['href'],
      a.content
    ]
  }

, что приводит к:

# >> [["http://www.example.com/foo", "foo"],
# >>  ["http://www.example.com/foo1", "foo1"],
# >>  ["http://www.example.com/foo2", "foo2"],
# >>  ["http://www.example.com/bar", "bar"],
# >>  ["http://www.example.com/foobar", "foobar"],
# >>  ["http://www.example.com/foobar2", "foobar2"]]

Я использовал CSS-аксессор 'a', чтобы найти теги. Я мог бы использовать 'a[href]', если бы хотел захватывать только ссылки, игнорируя якоря.

Regex очень хрупки при работе с HTML и XML, потому что форматы разметки слишком свободны; Они могут различаться по своему формату, оставаясь при этом действительными, особенно HTML, который может сильно различаться по своей «правильности». Если вы не владеете генерацией анализируемого файла, тогда ваш код зависит от того, кто сгенерирует его при использовании регулярных выражений; Простое изменение в файле может сильно испортить схему, что приведет к постоянной головной боли при обслуживании.

Парсер, потому что он на самом деле понимает внутреннюю структуру файла, может противостоять этим изменениям. Обратите внимание, что я намеренно создал какой-то искаженный HTML, но код не заботился. Сравните простоту версии синтаксического анализатора с решением регулярных выражений и подумайте о долговременной поддержке.

1 голос
/ 25 июня 2011

Если вы строите паука, то Ruby's Mechanize - отличный выбор.Чтобы получить страницу и извлечь ссылки:

require 'rubygems'
require 'mechanize'

agent = Mechanize.new
page = agent.get "http://google.com/"

page.links.each do |link|
  puts link.href
  puts link.text
end

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

1 голос
/ 25 июня 2011

Я бы предложил использовать HTML-парсер, как предложено @mrk. Затем, взяв результат, вы вернулись и отправили его через искатель регулярных выражений. Мне нравится использовать Rubular. Это покажет вам, что вы захватываете регулярное выражение, и вы можете избежать нежелательных результатов. Я обнаружил, что использование выражения regex / http [^ "] + / работает в такой ситуации, потому что он захватывает весь URL, даже если нет" www. "И вы избегаете ввода кавычек.

0 голосов
/ 24 июня 2011

Вот мой подход Ruby:

require 'open-uri'

class HTMLScraper
    def initialize(page)
      @src = page
      open(@src) do |x|
          @html = x.read
      end
    end
    def parseLinks
      links = @html.scan(/<a\s+href\s*=\s*"([^"]+)"[^>]*>\s*([^<]+)\s*<\/a>/ui)
      puts "Link(s) Found:"
      i = 0
      while i < links.length
        puts "\t#{links[i]}"
        i += 1
      end
    end
  end

url = "http://stackoverflow.com/questions"
test = HTMLScraper.new(url)
test.parseLinks

Это даст вам массив массивов, в котором первый элемент каждого (внутреннего) массива является URL-адресом, а второй - заголовком.Надеюсь, это поможет, и обратите внимание на переключатель u на регулярном выражении, чтобы избежать проблем с кодированием.

0 голосов
/ 24 июня 2011

Стараемся не делать это слишком сложно:

#<a .*?href="([^"]*)".*>([^<]+)</a>#i
...