Как я могу проверить, является ли строка действительным 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. Я ожидал, что они вернут nil, потому что ни один из них не является допустимым URI.
"http:"проходит это регулярное выражение.
Как и в ответах выше, я считаю, что это регулярное выражение немного более точное:
URI::DEFAULT_PARSER.regexp[:ABS_URI]
Это сделает недействительными URL-адреса с пробелами, в отличие от тех, URI.regexpкоторые по какой-то причине допускают пробелы.
Недавно я нашел ярлык, который предоставляется для различных URI rgexps. Вы можете получить доступ к любому из 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?
Я предпочитаю Addressable gem . Я обнаружил, что он обрабатывает 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не возвращает nil с недопустимым вводом.
Это довольно старая запись, но я решил пойти дальше и внести свой вклад:
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)
return false if url.include?("<script")
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:// - результат неверныйhttp://test.com\n<script src=\"nasty.js\"> (Просто отметьте «<скрипт»)Протестируйте с правильными 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 TLD , длина которого превышает 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-адресов.