URLが有効かどうかを確認する方法


93

文字列が有効なURLかどうかを確認するにはどうすればよいですか?

例えば:

http://hello.it => yes
http:||bra.ziz, => no

これが有効なURLである場合、これが画像ファイルに関連しているかどうかを確認するにはどうすればよいですか?


あなたが提供したURLは絶対URLのようです、画像ファイルと比較してどういう意味
ですか

回答:


177

URIRubyで配布されているモジュールを使用します。

require 'uri'

if url =~ URI::regexp
    # Correct URL
end

同様アレクサンダー・ギュンターがコメントで言った文字列があれば、それはチェックが含ま URLを。

文字列 URL かどうかを確認するには、次を使用します。

url =~ /\A#{URI::regexp}\z/

Web URL(httpまたはhttps)のみを確認したい場合は、次のようにします。

url =~ /\A#{URI::regexp(['http', 'https'])}\z/

24
それは動作していないよう:'http://:5984/asdf' =~ URI::regexp及び'http::5984/asdf' =~ URI::regexpそれらのどれもが有効なURIではないので、両方の戻り0は、私は彼らがnilを返すと予想しました。
awendt

4
ローカルホストの:5984ポート5984ではありませんか?
mxcl 2012

3
実際には、変数に有効なURLが含まれているかどうかをチェックします。「example com」を有効なURLとして受け入れます。それが含まれているからです。しかし、全体がURLであると予想しても、役に立ちません。
AlexanderGünther12年

2
gotqn:RFC 1738によると、これは有効なURLではありません。
ミカエルS 14年

12
これを使用しないでください"http:"。この正規表現を通過するのは非常に悪いです。
smathy

43

上記の回答と同様に、この正規表現を使用する方が少し正確であることがわかります。

URI::DEFAULT_PARSER.regexp[:ABS_URI]

これはURI.regexp、何らかの理由でスペースを許可するのではなく、スペースを含むURLを無効にします。

最近、さまざまなURI rgexpsに提供されているショートカットを見つけました。のいずれかにURI::DEFAULT_PARSER.regexp.keys直接アクセスできますURI::#{key}

たとえば、:ABS_URI正規表現はからアクセスできますURI::ABS_URI


3
URI.parseを使用する予定がある場合は、これが間違いなく進むべき道です。URI :: regexpは、後でURI.parseを使用すると失敗する特定のURLに一致します。先端をありがとう。
markquezada '19年

残念ながら、これはRuby 1.9でのみ利用でき、1.8では利用できません。
Steve Madsen

1
しかし、これは機能します/^#{URI.regexp}$/。問題は、それURI.regexpが固定されないことです。スペースを含む文字列は、URIの一部としてスペースを検証するのではなく、スペースに至るまでのすべてを検証します。そのフラグメントが有効なURIのように見える場合、一致は成功します。
Steve Madsen、

3
awendtのコメントを提案に適用する:'http://:5984/asdf' =~ URI::DEFAULT_PARSER.regexp[:ABS_URI]nilではなく0を与えます。'http::5984/asdf'=~ URI::DEFAULT_PARSER.regexp[:ABS_URI]0を与える; 'http://:5984/asdf' =~ /^#{URI.regexp}$/0を与える; 'http::5984/asdf' =~ /^#{URI.regexp}$/0も与えます。上記の正規表現はどれも完全に正しいわけではありませんが、非常に奇妙な状況でのみ失敗し、ほとんどの場合これは大した問題ではありません。
1

1
FYI、URI::DEFAULT_PARSER.regexp[:ABS_URI]と同じです/\A\s*#{URI::regexp}\s*\z/
エイダン

34

現在の回答の問題は、URIがURLではないことです。

URIは、ロケーター、名前、またはその両方にさらに分類できます。「Uniform Resource Locator」(URL)という用語は、URIのサブセットを指し、リソースの識別に加えて、その主要なアクセスメカニズム(たとえば、そのネットワーク「ロケーション」)を記述することによってリソースを特定する手段を提供します。

URLはURIのサブセットであるため、特にURIを照合すると、望ましくない値との照合が成功することは明らかです。たとえば、URN

 "urn:isbn:0451450523" =~ URI::regexp
 => 0 

そうは言っても、私が知る限り、RubyにはURLを解析するデフォルトの方法がないため、そのためにはgemが必要になる可能性が高いです。特にHTTPまたはHTTPS形式のURLを照合する必要がある場合は、次のようにすることができます。

uri = URI.parse(my_possible_url)
if uri.kind_of?(URI::HTTP) or uri.kind_of?(URI::HTTPS)
  # do your stuff
end

@フィリップは役に立ち、適切でした。どうもありがとうございました!
fotanus 2013

2
uri.kind_of?(URI::HTTP)少なくともruby 1.9.3では、両方のケース(httpおよびhttps)で十分であるようです。
Andrea Salicetti 2014

ジョナットの答えの下で、@ skaleeによって説明された問題が依然として残っています
akostadinov

1
まとめ、URI.parse(string_to_be_checked).kind_of?(URI::HTTP)仕事はうまくいきます。
2017

19

私はアドレス可能な宝石を好みます。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

3
Addressable :: URI.parse()に最も奇妙な文字列を与えて、何が拒否されるかを確認しました。それはクレイジーなものを受け入れました。ただし、受け入れなかった最初の文字列は ":-)"でした。うーん。
mvw

1
これはどのようにして多くの賛成票を獲得するのですか?Addressable::URI.parse無効な入力でnilを返しません。
garbagecollector 2018年

11

これはかなり古いエントリですが、私は先に進んで貢献すると思いました:

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

2
これは、上記のソリューションよりもはるかにうまく機能します。上記の警告はなく、javascript:alert( 'spam')のようなURIも受け入れません。
bchurchill 2013

2
しかし、それもと一致しhttp:/ます。
Bo Jeanes 2013

10

私は、次の正規表現を使用しています。

/^(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 -結果は有効です

以下は有効としてマークされます。5文字を超える683 TLDの"http://test.com\n<script src=\"nasty.js\">" 1つを使用するドメイン、または2つ以上のハイフンが連続するドメインは無効としてマークされます。0〜65535の範囲外のポート番号を使用できます。FTPおよびIPアドレスは明らかに禁止されていますが、注目に値します。
エイダン

1
簡単にURLをすばやくチェックするための最適なソリューションです。おかげで
一部の方向付け

4

これは少し古いですが、ここに私がそれをする方法があります。RubyのURIモジュールを使用して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に切り替えます。私の目的のために私は気にしなかったのでそれは理想的でした。
el n00b

3

一般に、

/^#{URI::regexp}$/

うまく機能しますが、httpまたはのみを一致させたい場合はhttps、それらをオプションとしてメソッドに渡すことができます。

/^#{URI::regexp(%w(http https))}$/

のようなプロトコルを拒否したい場合は、少しうまくいく傾向がありますftp://


-2

また、多分のようなもの、正規表現を使用することができ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

5
mailtoスキームはどうですか?または、telnet、gopher、nntp、rsync、ssh、またはその他のスキームのいずれか?URLは、HTTPとFTPだけではなく少し複雑です。
muが短すぎる

URLを検証するための正規表現を書くことは困難です。なぜわざわざ?
リミアン2012

@Rimian、あなたがURIできることはすべて実際に壊れているので、あなたはわざわざする必要があります。上記の非常に多くの投票された回答の下のコメントを参照してください。ジャニーの答えが正しいかどうかはわかりませんが、賛成票を投じているので、人々はそれをより真剣に考えていると思います。TBH url.start_with?("http://") || url.start_with?("https://")必要なのはHTTPだけで、ユーザーは適切なURLを使用する必要があるためです。
akostadinov
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.