Làm cách nào để kiểm tra xem một chuỗi có phải là URL hợp lệ hay không?
Ví dụ:
http://hello.it => yes
http:||bra.ziz, => no
Nếu đây là một URL hợp lệ, làm cách nào để kiểm tra xem nó có liên quan đến tệp hình ảnh không?
Làm cách nào để kiểm tra xem một chuỗi có phải là URL hợp lệ hay không?
Ví dụ:
http://hello.it => yes
http:||bra.ziz, => no
Nếu đây là một URL hợp lệ, làm cách nào để kiểm tra xem nó có liên quan đến tệp hình ảnh không?
Câu trả lời:
Sử dụng URI
mô-đun được phân phối với Ruby:
require 'uri'
if url =~ URI::regexp
# Correct URL
end
Giống như Alexander Günther đã nói trong các nhận xét, nó kiểm tra xem một chuỗi có chứa URL hay không.
Để kiểm tra xem chuỗi có phải là URL hay không, hãy sử dụng:
url =~ /\A#{URI::regexp}\z/
Nếu bạn chỉ muốn kiểm tra các URL web ( http
hoặc https
), hãy sử dụng cái này:
url =~ /\A#{URI::regexp(['http', 'https'])}\z/
'http://:5984/asdf' =~ URI::regexp
và 'http::5984/asdf' =~ URI::regexp
cả hai đều trả về 0. Tôi đã mong đợi chúng trả về nil vì không ai trong số chúng là URI hợp lệ.
"http:"
vượt qua regexp này.
Tương tự như các câu trả lời ở trên, tôi thấy sử dụng regex này chính xác hơn một chút:
URI::DEFAULT_PARSER.regexp[:ABS_URI]
Điều đó sẽ làm mất hiệu lực các URL có khoảng trắng, trái ngược với URI.regexp
nó cho phép khoảng trắng vì một số lý do.
Gần đây tôi đã tìm thấy một lối tắt được cung cấp cho các rgexps URI khác nhau. Bạn có thể truy cập URI::DEFAULT_PARSER.regexp.keys
trực tiếp từ bất kỳ URI::#{key}
.
Ví dụ, :ABS_URI
regexp có thể được truy cập từ URI::ABS_URI
.
/^#{URI.regexp}$/
. Vấn đề là URI.regexp
nó không neo. Chuỗi có khoảng trắng không xác thực không gian như một phần của URI, nhưng mọi thứ dẫn đến khoảng trắng. Nếu phân đoạn đó trông giống như một URI hợp lệ, kết quả khớp sẽ thành công.
'http://:5984/asdf' =~ URI::DEFAULT_PARSER.regexp[:ABS_URI]
đưa ra 0, không phải số không; 'http::5984/asdf'=~ URI::DEFAULT_PARSER.regexp[:ABS_URI]
cho 0; 'http://:5984/asdf' =~ /^#{URI.regexp}$/
cho 0; 'http::5984/asdf' =~ /^#{URI.regexp}$/
cũng cho 0. Không có regexps nào ở trên là chính xác hoàn toàn, tuy nhiên chúng chỉ thất bại trong những tình huống rất kỳ quặc và đây không phải là vấn đề lớn trong hầu hết các trường hợp.
URI::DEFAULT_PARSER.regexp[:ABS_URI]
giống với/\A\s*#{URI::regexp}\s*\z/
Vấn đề với các câu trả lời hiện tại là URI không phải là URL .
URI có thể được phân loại thêm dưới dạng định vị, tên hoặc cả hai. Thuật ngữ "Bộ định vị tài nguyên thống nhất" (URL) đề cập đến tập hợp con của các URI, ngoài việc xác định tài nguyên, còn cung cấp phương tiện định vị tài nguyên bằng cách mô tả cơ chế truy cập chính của nó (ví dụ: "vị trí" mạng của nó).
Vì URL là một tập hợp con của các URI, rõ ràng là đối sánh cụ thể cho các URI sẽ khớp thành công các giá trị không mong muốn. Ví dụ : URN :
"urn:isbn:0451450523" =~ URI::regexp
=> 0
Điều đó đang được nói, theo như tôi biết, Ruby không có cách mặc định để phân tích cú pháp URL, vì vậy rất có thể bạn sẽ cần một viên ngọc để làm như vậy. Nếu bạn cần khớp các URL cụ thể ở định dạng HTTP hoặc HTTPS, bạn có thể làm như sau:
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)
dường như là đủ cho cả hai trường hợp (http và https), ít nhất là trong ruby 1.9.3.
URI.parse(string_to_be_checked).kind_of?(URI::HTTP)
làm tốt công việc.
Tôi thích đá quý Địa chỉ hơn . Tôi nhận thấy rằng nó xử lý URL thông minh hơn.
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
không trả về nil với đầu vào không hợp lệ.
Đây là một mục khá cũ, nhưng tôi nghĩ tôi sẽ tiếp tục và đóng góp:
String.class_eval do
def is_valid_url?
uri = URI.parse self
uri.kind_of? URI::HTTP
rescue URI::InvalidURIError
false
end
end
Bây giờ bạn có thể làm điều gì đó như:
if "http://www.omg.wtf".is_valid_url?
p "huzzah!"
end
http:/
, có thể không như ý bạn muốn.
Đối với tôi, tôi sử dụng cụm từ thông dụng này:
/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
Lựa chọn:
i
- trường hợp không nhạy cảmx
- bỏ qua khoảng trắng trong regexBạn có thể đặt phương pháp này để kiểm tra xác thực 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
Để dùng nó:
valid_url?("http://stackoverflow.com/questions/1805761/check-if-url-is-valid-ruby")
Kiểm tra với các URL sai:
http://ruby3arabi
- kết quả không hợp lệhttp://http://ruby3arabi.com
- kết quả không hợp lệhttp://
- kết quả không hợp lệKiểm tra với các URL chính xác:
http://ruby3arabi.com
- kết quả là hợp lệhttp://www.ruby3arabi.com
- kết quả là hợp lệhttps://www.ruby3arabi.com
- kết quả là hợp lệhttps://www.ruby3arabi.com/article/1
- kết quả là hợp lệhttps://www.ruby3arabi.com/websites/58e212ff6d275e4bf9000000?locale=en
- kết quả là hợp lệ"http://test.com\n<script src=\"nasty.js\">"
Tên miền sau được đánh dấu là hợp lệ: và bất kỳ tên miền nào sử dụng một trong 683 TLD dài hơn 5 ký tự hoặc có hai hoặc nhiều dấu gạch ngang liên tiếp, đều được đánh dấu là không hợp lệ. Số cổng bên ngoài phạm vi 0-65535 được cho phép. Địa chỉ FTP và IP rõ ràng là không được phép, nhưng đáng chú ý.
Điều này hơi cũ một chút nhưng đây là cách tôi làm điều đó. Sử dụng mô-đun URI của Ruby để phân tích cú pháp URL. Nếu nó có thể được phân tích cú pháp thì đó là một URL hợp lệ. (Nhưng điều đó không có nghĩa là có thể truy cập được.)
URI hỗ trợ nhiều lược đồ, ngoài ra bạn có thể tự thêm các lược đồ tùy chỉnh:
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}
Xem tài liệu để biết thêm thông tin về mô-đun URI.
URI.parse
thực sự là nguyên nhân của điều này trong Ruby 2.5.5 - Tôi đã chuyển sang câu trả lời @jonuts bên dưới nếu bạn không bận tâm đến một số trường hợp kỳ quặc. Đối với mục đích của tôi, tôi không quan tâm đến điều đó là lý tưởng.
Nói chung,
/^#{URI::regexp}$/
sẽ hoạt động tốt, nhưng nếu bạn chỉ muốn đối sánh http
hoặc https
, bạn có thể chuyển chúng vào dưới dạng tùy chọn cho phương thức:
/^#{URI::regexp(%w(http https))}$/
Điều đó có xu hướng hoạt động tốt hơn một chút, nếu bạn muốn từ chối các giao thức như ftp://
.
Bạn cũng có thể sử dụng regex, có thể giống như http://www.geekzilla.co.uk/View2D3B0109-C1B2-4B4E-BFFD-E8088CBC85FD.htm giả sử regex này là chính xác (tôi chưa kiểm tra hoàn toàn) như sau hiển thị tính hợp lệ của 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
}
Ví dụ trên cho kết quả:
http://hello.it is valid
http:||bra.ziz not valid
URI
gì có thể làm trên thực tế đã bị hỏng. Xem các bình luận bên dưới rất nhiều câu trả lời được ủng hộ ở trên. Không chắc câu trả lời của Janie có đúng không nhưng rất ủng hộ nên hy vọng mọi người hãy xem xét nó nghiêm túc hơn. TBH mà tôi kết thúc url.start_with?("http://") || url.start_with?("https://")
vì tôi chỉ cần HTTP và người dùng phải có trách nhiệm sử dụng các URL thích hợp.