Як я можу перевірити, чи рядок є дійсною URL-адресою?
Наприклад:
http://hello.it => yes
http:||bra.ziz, => no
Якщо це дійсна URL-адреса, як я можу перевірити, чи є вона відносно файлу зображення?
Як я можу перевірити, чи рядок є дійсною URL-адресою?
Наприклад:
http://hello.it => yes
http:||bra.ziz, => no
Якщо це дійсна URL-адреса, як я можу перевірити, чи є вона відносно файлу зображення?
Відповіді:
Використовуйте URI
модуль, розподілений разом з Ruby:
require 'uri'
if url =~ URI::regexp
# Correct URL
end
Як сказав Олександр Гюнтер у коментарях, він перевіряє, чи містить рядок URL-адресу.
Для того, щоб перевірити , якщо рядок є URL - адреса, використання:
url =~ /\A#{URI::regexp}\z/
Якщо ви хочете лише перевірити веб-URL-адреси ( http
або https
), використовуйте це:
url =~ /\A#{URI::regexp(['http', 'https'])}\z/
'http://:5984/asdf' =~ URI::regexp
і 'http::5984/asdf' =~ URI::regexp
обидва повертають 0. Я очікував, що вони повернуть нуль, оскільки жоден з них не є дійсними URI.
"http:"
проходить цей регулярний вираз.
Подібно до відповідей вище, я вважаю, що використання цього регулярного виразу є дещо точнішим:
URI::DEFAULT_PARSER.regexp[:ABS_URI]
Це призведе до анулювання URL-адрес із пробілами, на відміну від URI.regexp
яких з якихось причин допускає пробіли.
Нещодавно я знайшов ярлик, який надається для різних rgexps URI. Ви можете отримати доступ до будь-якого URI::DEFAULT_PARSER.regexp.keys
безпосередньо з URI::#{key}
.
Наприклад, :ABS_URI
регулярний вираз можна отримати з URI::ABS_URI
.
/^#{URI.regexp}$/
. Біда в тому, що URI.regexp
не закріплюється. Рядок з пробілом не перевіряє пробіл як частину URI, а все, що веде до пробілу. Якщо цей фрагмент виглядає як дійсний URI, збіг вдається.
'http://:5984/asdf' =~ URI::DEFAULT_PARSER.regexp[:ABS_URI]
дає 0, не нуль; 'http::5984/asdf'=~ URI::DEFAULT_PARSER.regexp[:ABS_URI]
дає 0; 'http://:5984/asdf' =~ /^#{URI.regexp}$/
дає 0; 'http::5984/asdf' =~ /^#{URI.regexp}$/
дає також 0. Жоден з наведених вище регулярних виразів не є повністю правильним, однак вони дають збій лише у дуже дивних ситуаціях, і це в більшості випадків не є великою проблемою.
URI::DEFAULT_PARSER.regexp[:ABS_URI]
ідентично/\A\s*#{URI::regexp}\s*\z/
Проблема поточних відповідей полягає в тому, що URI не є URL-адресою .
URI може бути далі класифікований як локатор, назва або як те, так і інше. Термін "Уніфікований локатор ресурсів" (URL) відноситься до підмножини URI, які, крім ідентифікації ресурсу, забезпечують спосіб пошуку ресурсу, описуючи його основний механізм доступу (наприклад, його "мережеве розташування").
Оскільки URL-адреси є підмножиною URI, очевидно, що відповідність спеціально для URI успішно відповідатиме небажаним значенням. Наприклад, URN :
"urn:isbn:0451450523" =~ URI::regexp
=> 0
Однак, наскільки мені відомо, у Ruby немає стандартного способу синтаксичного аналізу URL-адрес, тому вам, швидше за все, знадобиться самоцвіт. Якщо вам потрібно зіставити URL-адреси конкретно у форматі HTTP або HTTPS, ви можете зробити щось подібне:
uri = URI.parse(my_possible_url)
if uri.kind_of?(URI::HTTP) or uri.kind_of?(URI::HTTPS)
# do your stuff
end
uri.kind_of?(URI::HTTP)
здається достатнім для обох випадків (http і https), принаймні в ruby 1.9.3.
URI.parse(string_to_be_checked).kind_of?(URI::HTTP)
робить роботу добре.
http:///neopets.com
що, на жаль, також є дійсним. Перевірка наявності імені хоста виправляє це:uri = URI(str) ; %w[http https].include?(uri.scheme) && !uri.host.nil?
Мені більше подобається Адресивний самоцвіт . Я виявив, що він обробляє URL-адреси більш розумно.
require 'addressable/uri'
SCHEMES = %w(http https)
def valid_url?(url)
parsed = Addressable::URI.parse(url) or return false
SCHEMES.include?(parsed.scheme)
rescue Addressable::URI::InvalidURIError
false
end
Addressable::URI.parse
не повертає нуль з недійсним введенням.
Це досить старий запис, але я думав, що піду далі:
String.class_eval do
def is_valid_url?
uri = URI.parse self
uri.kind_of? URI::HTTP
rescue URI::InvalidURIError
false
end
end
Тепер ви можете зробити щось на зразок:
if "http://www.omg.wtf".is_valid_url?
p "huzzah!"
end
http:/
, що може бути не тим, що ви хочете.
Для мене я використовую цей регулярний вираз:
/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
Варіант:
i
- регістр не чутливийx
- ігнорувати пробіли в регулярному виразі -Ви можете встановити цей метод для перевірки перевірки URL-адреси:
def valid_url?(url)
url_regexp = /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
url =~ url_regexp ? true : false
end
Щоб використовувати його:
valid_url?("http://stackoverflow.com/questions/1805761/check-if-url-is-valid-ruby")
Тестування з помилковими URL-адресами:
http://ruby3arabi
- результат недійснийhttp://http://ruby3arabi.com
- результат недійснийhttp://
- результат недійснийПеревірте правильні URL-адреси:
http://ruby3arabi.com
- результат дійснийhttp://www.ruby3arabi.com
- результат дійснийhttps://www.ruby3arabi.com
- результат дійснийhttps://www.ruby3arabi.com/article/1
- результат дійснийhttps://www.ruby3arabi.com/websites/58e212ff6d275e4bf9000000?locale=en
- результат дійсний"http://test.com\n<script src=\"nasty.js\">"
а будь-який домен, який використовує один із 683 доменів верхнього рівня, що має більше 5 символів, або має два або більше послідовних дефісів, позначений як недійсний. Дозволені номери портів поза діапазоном 0-65535. FTP та IP адреси, очевидно, заборонені, але варті уваги.
Це трохи старе, але ось як я це роблю. Використовуйте модуль URI Ruby для синтаксичного аналізу URL-адреси. Якщо його можна проаналізувати, це дійсний URL. (Але це не означає доступність.)
URI підтримує багато схем, плюс ви можете додати власні схеми самостійно:
irb> uri = URI.parse "http://hello.it" rescue nil
=> #<URI::HTTP:0x10755c50 URL:http://hello.it>
irb> uri.instance_values
=> {"fragment"=>nil,
"registry"=>nil,
"scheme"=>"http",
"query"=>nil,
"port"=>80,
"path"=>"",
"host"=>"hello.it",
"password"=>nil,
"user"=>nil,
"opaque"=>nil}
irb> uri = URI.parse "http:||bra.ziz" rescue nil
=> nil
irb> uri = URI.parse "ssh://hello.it:5888" rescue nil
=> #<URI::Generic:0x105fe938 URL:ssh://hello.it:5888>
[26] pry(main)> uri.instance_values
=> {"fragment"=>nil,
"registry"=>nil,
"scheme"=>"ssh",
"query"=>nil,
"port"=>5888,
"path"=>"",
"host"=>"hello.it",
"password"=>nil,
"user"=>nil,
"opaque"=>nil}
Дивіться документацію для отримання додаткової інформації про модуль URI.
URI.parse
було насправді причиною цього в Ruby 2.5.5 - я перейшов до відповіді @jonuts нижче, якщо ви не проти, щоб пропали якісь дивні випадки. Для моїх цілей мені було байдуже, тому це було ідеально.
В загальному,
/^#{URI::regexp}$/
буде працювати добре, але якщо ви хочете лише відповідати http
або https
, ви можете передати їх як варіанти методу:
/^#{URI::regexp(%w(http https))}$/
Це, як правило, працює трохи краще, якщо ви хочете відхилити протоколи типу ftp://
.
Ви також можете використовувати регулярний вираз, можливо щось на зразок http://www.geekzilla.co.uk/View2D3B0109-C1B2-4B4E-BFFD-E8088CBC85FD.htm, припускаючи, що цей регулярний вираз правильний (я не перевірив його повністю), наступне буде показати дійсність URL-адреси.
url_regex = Regexp.new("((https?|ftp|file):((//)|(\\\\))+[\w\d:\#@%/;$()~_?\+-=\\\\.&]*)")
urls = [
"http://hello.it",
"http:||bra.ziz"
]
urls.each { |url|
if url =~ url_regex then
puts "%s is valid" % url
else
puts "%s not valid" % url
end
}
Наведений вище приклад виводить:
http://hello.it is valid
http:||bra.ziz not valid
URI
можна зробити, насправді зламане. Див. Коментарі під стільки прихильних відповідей вище. Не впевнений, що відповідь Дженні правильна, але голосую, тому, сподіваємось, люди розглядають це більш серйозно. TBH Я в підсумку роблю, url.start_with?("http://") || url.start_with?("https://")
тому що мені потрібен лише HTTP, і користувачі повинні нести відповідальність за використання належних URL-адрес.