Как я могу проверить, является ли строка действительным 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-адресов.