Как извлечь из строки URL-адрес с неанглийскими символами? - PullRequest
9 голосов
/ 31 января 2012

Вот простой скрипт, который берет якорный тег с немецким URL и извлекает URL:

# encoding: utf-8

require 'uri'

url = URI.extract('<a href="http://www.example.com/wp content/uploads/2012/01/München.jpg">München</a>')

puts url

http://www.example.com/wp-content/uploads/2012/01/M

Метод extract останавливается на ü. Как я могу заставить его работать с неанглийскими буквами? Я использую ruby-1.9.3-p0.

Ответы [ 3 ]

12 голосов
/ 31 января 2012

Встроенный в Ruby URI полезен для некоторых вещей, но это не лучший выбор при работе с международными символами или адресами IDNA.Для этого я рекомендую использовать Addressable gem.

Вот какой-то очищенный вывод IRB:

require 'addressable/uri'
url = 'http://www.example.com/wp content/uploads/2012/01/München.jpg'
uri = Addressable::URI.parse(url)

Вот что теперь знает Ruby:

#<Addressable::URI:0x102c1ca20
    @uri_string = nil,
    @validation_deferred = false,
    attr_accessor :authority = nil,
    attr_accessor :host = "www.example.com",
    attr_accessor :path = "/wp content/uploads/2012/01/München.jpg",
    attr_accessor :scheme = "http",
    attr_reader :hash = nil,
    attr_reader :normalized_host = nil,
    attr_reader :normalized_path = nil,
    attr_reader :normalized_scheme = nil
>

И, глядя на путь, вы можете видеть его как есть или как оно должно быть:

1.9.2-p290 :004 > uri.path            # => "/wp content/uploads/2012/01/München.jpg"
1.9.2-p290 :005 > uri.normalized_path # => "/wp%20content/uploads/2012/01/M%C3%BCnchen.jpg"

Адресность действительно должна быть выбрана для замены URI в Ruby, учитывая то, как Интернет переходит на более сложные URI.и смешанные символы Юникода.

Теперь получить строку тоже очень просто, но зависит от того, сколько текста вам нужно просмотреть.

Если у вас полный документ HTML, лучше всегодолжен использовать Nokogiri для анализа HTML и извлечения параметров href из тегов <a>.Это то место, с которого нужно начинать отдельный <a>:

require 'nokogiri'
html = '<a href="http://www.example.com/wp content/uploads/2012/01/München.jpg">München</a>'
doc = Nokogiri::HTML::DocumentFragment.parse(html)

doc.at('a')['href'] # => "http://www.example.com/wp content/uploads/2012/01/München.jpg"

Синтаксический анализ с использованием DocumentFragment позволяет избежать упаковки фрагмента в обычные теги <html><body>.Для полного документа, который вы хотите использовать:

doc = Nokogiri::HTML.parse(html)

Вот разница между ними:

irb(main):006:0> Nokogiri::HTML::DocumentFragment.parse(html).to_html
=> "<a href=\"http://www.example.com/wp%20content/uploads/2012/01/M%C3%BCnchen.jpg\">München</a>"

против:

irb(main):007:0> Nokogiri::HTML.parse(html).to_html
=> "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n<html><body><a href=\"http://www.example.com/wp%20content/uploads/2012/01/M%C3%BCnchen.jpg\">München</a></body></html>\n"

Итак, используйтевторой для полного HTML-документа и для небольшого частичного фрагмента, используйте первый.

Чтобы отсканировать весь документ, извлекая все hrefs, используйте:

hrefs = doc.search('a').map{ |a| a['href'] }

Если выесть только небольшие строки, как показано в вашем примере, вы можете использовать простое регулярное выражение, чтобы выделить необходимые href:

html[/href="([^"]+)"/, 1]
=> "http://www.example.com/wp content/uploads/2012/01/München.jpg"
4 голосов
/ 31 января 2012

Вы должны сначала закодировать URL:

URI.extract(URI.encode('<a href="http://www.example.com/wp_content/uploads/2012/01/München.jpg">München</a>'))
0 голосов
/ 31 января 2012

Модуль URI, вероятно, ограничен 7-битными символами ASCII. Хотя UTF-8 является предполагаемым стандартом для многих вещей, это никогда не гарантируется, и нет способа указать кодировку URI, как вы можете для полного обмена HTTP.

Одним из решений является отображение не-ASCII символов в качестве их% эквивалентов. Связанное сообщение переполнения стека: Unicode-символы в URL-адресах

Если вы имеете дело с данными, которые уже искажены, вы можете сначала вызвать URI.encode для их процентирования, а затем сопоставить с ними снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...