So überprüfen Sie, ob eine URL gültig ist


93

Wie kann ich überprüfen, ob eine Zeichenfolge eine gültige URL ist?

Beispielsweise:

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

Wenn dies eine gültige URL ist, wie kann ich überprüfen, ob dies relativ zu einer Bilddatei ist?


Die URL, die Sie angegeben haben, scheint eine absolute URL zu sein. Was meinen Sie mit relativ zu einer Bilddatei
Johannes

Ich habe einen UriValidator mit Spezifikationen gepostet .
JJD

Antworten:


177

Verwenden Sie das URImit Ruby verteilte Modul:

require 'uri'

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

Wie Alexander Günther in den Kommentaren sagte, wird geprüft, ob eine Zeichenfolge eine URL enthält .

Um zu überprüfen , ob die Zeichenfolge ist eine URL, zu verwenden:

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

Wenn Sie nur nach Web-URLs ( httpoder https) suchen möchten , verwenden Sie Folgendes:

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

24
Das scheint nicht zu funktionieren: 'http://:5984/asdf' =~ URI::regexpund 'http::5984/asdf' =~ URI::regexpbeide geben 0 zurück. Ich habe erwartet, dass sie null zurückgeben, da keiner von ihnen gültige URIs sind.
Awendt

4
Ist nicht: 5984 Port 5984 auf localhost?
mxcl

3
Es wird tatsächlich geprüft, ob eine Variable eine gültige URL enthält. Es wird " example com" als gültige URL akzeptiert . Weil es eins enthält. Es ist jedoch nicht hilfreich, wenn Sie erwarten, dass das Ganze die URL ist.
Alexander Günther

2
gotqn: Dies ist jedoch keine gültige URL gemäß RFC 1738.
Mikael S

12
Verwenden Sie dies nicht, es ist so schlimm, dass "http:"dieser reguläre Ausdruck besteht.
smathy

43

Ähnlich wie bei den obigen Antworten finde ich die Verwendung dieses regulären Ausdrucks etwas genauer:

URI::DEFAULT_PARSER.regexp[:ABS_URI]

Dadurch werden URLs mit Leerzeichen ungültig, während URI.regexpLeerzeichen aus irgendeinem Grund zulässig sind.

Ich habe kürzlich eine Verknüpfung gefunden, die für die verschiedenen URI-Rgexps bereitgestellt wird. Sie können URI::DEFAULT_PARSER.regexp.keysdirekt von auf zugreifen URI::#{key}.

Auf den :ABS_URIregulären Ausdruck kann beispielsweise von zugegriffen werden URI::ABS_URI.


3
Wenn Sie URI.parse zu irgendeinem Zeitpunkt verwenden möchten, ist dies definitiv der richtige Weg. URI :: regexp stimmt mit bestimmten URLs überein, die bei späterer Verwendung von URI.parse fehlschlagen. Danke für den Tipp.
Markquezada

Leider ist dies nur für Ruby 1.9 verfügbar, nicht für 1.8.
Steve Madsen

1
Aber das funktioniert : /^#{URI.regexp}$/. Das Problem ist, dass URI.regexpnicht verankert wird. Eine Zeichenfolge mit einem Leerzeichen überprüft nicht das Leerzeichen als Teil des URI, sondern alles, was zum Leerzeichen führt. Wenn dieses Fragment wie ein gültiger URI aussieht, ist die Übereinstimmung erfolgreich.
Steve Madsen

3
Anwenden des Kommentars von awendt auf Ihre Vorschläge: 'http://:5984/asdf' =~ URI::DEFAULT_PARSER.regexp[:ABS_URI]ergibt 0, nicht null; 'http::5984/asdf'=~ URI::DEFAULT_PARSER.regexp[:ABS_URI]gibt 0; 'http://:5984/asdf' =~ /^#{URI.regexp}$/gibt 0; 'http::5984/asdf' =~ /^#{URI.regexp}$/gibt auch 0. Keiner der oben genannten regulären Ausdrücke ist vollständig korrekt, jedoch scheitern sie nur in sehr, sehr seltsamen Situationen, und dies ist in den meisten Fällen keine große Sache.
Skalee

1
Zu URI::DEFAULT_PARSER.regexp[:ABS_URI]/\A\s*#{URI::regexp}\s*\z/
Ihrer Information

34

Das Problem mit den aktuellen Antworten ist, dass ein URI keine URL ist .

Ein URI kann weiter als Locator, Name oder beides klassifiziert werden. Der Begriff "Uniform Resource Locator" (URL) bezieht sich auf die Teilmenge von URIs, die zusätzlich zur Identifizierung einer Ressource ein Mittel zum Auffinden der Ressource bereitstellen, indem sie ihren primären Zugriffsmechanismus (z. B. ihren "Netzwerkstandort") beschreiben.

Da URLs eine Teilmenge von URIs sind, ist es klar, dass der Abgleich speziell für URIs erfolgreich mit unerwünschten Werten übereinstimmt. Zum Beispiel URNs :

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

Soweit ich weiß, hat Ruby jedoch keine Standardmethode zum Parsen von URLs. Daher benötigen Sie höchstwahrscheinlich ein Juwel, um dies zu tun. Wenn Sie URLs speziell im HTTP- oder HTTPS-Format abgleichen müssen, können Sie Folgendes tun:

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

@Philip war sowohl hilfreich als auch angemessen. Vielen Dank!
Fotanus

2
uri.kind_of?(URI::HTTP)scheint für beide Fälle (http und https) ausreichend zu sein, zumindest in Ruby 1.9.3.
Andrea Salicetti

leidet immer noch unter den Problemen, die @skalee unter der Antwort der Jonuts beschrieben hat
akostadinov

1
Zusammenfassung, URI.parse(string_to_be_checked).kind_of?(URI::HTTP)macht den Job gut.
Ben

19

Ich bevorzuge das adressierbare Juwel . Ich habe festgestellt, dass es URLs intelligenter behandelt.

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
Ich habe gerade Addressable :: URI.parse () mit den seltsamsten Zeichenfolgen gefüttert, um zu sehen, was es ablehnt. Es akzeptierte verrücktes Zeug. Die erste Zeichenfolge, die nicht akzeptiert wurde, war ":-)". Hmm.
MVW

1
Wie kommt das zu so vielen Upvotes? Addressable::URI.parsegibt bei ungültiger Eingabe nicht nil zurück.
Müllsammler

11

Dies ist ein ziemlich alter Eintrag, aber ich dachte, ich würde weitermachen und dazu beitragen:

String.class_eval do
    def is_valid_url?
        uri = URI.parse self
        uri.kind_of? URI::HTTP
    rescue URI::InvalidURIError
        false
    end
end

Jetzt können Sie so etwas tun wie:

if "http://www.omg.wtf".is_valid_url?
    p "huzzah!"
end

2
Dies funktioniert viel besser als die oben genannten Lösungen. Es hat nicht die oben aufgeführten Einschränkungen und akzeptiert auch keine Uris wie Javascript: alert ('Spam').
Bchurchill

2
aber es passt auch zusammen http:/, was möglicherweise nicht das ist, was Sie wollen.
Bo Jeanes

10

Für mich verwende ich diesen regulären Ausdruck:

/^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix

Möglichkeit:

  • i - Groß- und Kleinschreibung wird nicht berücksichtigt
  • x - Leerzeichen in Regex ignorieren

Sie können diese Methode festlegen, um die URL-Validierung zu überprüfen:

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

Um es zu benutzen:

valid_url?("http://stackoverflow.com/questions/1805761/check-if-url-is-valid-ruby")

Testen mit falschen URLs:

  • http://ruby3arabi - Ergebnis ist ungültig
  • http://http://ruby3arabi.com - Ergebnis ist ungültig
  • http:// - Ergebnis ist ungültig

Test mit korrekten URLs:

  • http://ruby3arabi.com - Ergebnis ist gültig
  • http://www.ruby3arabi.com - Ergebnis ist gültig
  • https://www.ruby3arabi.com - Ergebnis ist gültig
  • https://www.ruby3arabi.com/article/1 - Ergebnis ist gültig
  • https://www.ruby3arabi.com/websites/58e212ff6d275e4bf9000000?locale=en - Ergebnis ist gültig

Folgendes wird als gültig markiert: "http://test.com\n<script src=\"nasty.js\">"und jede Domäne, die eine der 683 TLDs verwendet , die länger als 5 Zeichen sind oder zwei oder mehr aufeinanderfolgende Bindestriche haben, wird als ungültig markiert. Portnummern außerhalb des Bereichs 0-65535 sind zulässig. FTP- und IP-Adressen sind offensichtlich nicht zulässig, aber erwähnenswert.
Aidan

1
Hier ist die beste Lösung für die schnelle URL-Überprüfung. danke
Somedirection

4

Das ist ein bisschen alt, aber so mache ich es. Verwenden Sie Rubys URI-Modul, um die URL zu analysieren. Wenn es analysiert werden kann, ist es eine gültige URL. (Das heißt aber nicht zugänglich.)

URI unterstützt viele Schemata, und Sie können selbst benutzerdefinierte Schemata hinzufügen:

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}

Weitere Informationen zum URI-Modul finden Sie in der Dokumentation .


Ich bin darauf gestoßen und habe versucht, einen Segfault zu beheben. Die Verwendung URI.parsewar tatsächlich die Ursache dafür in Ruby 2.5.5 - Ich habe unten zu @jonuts Antwort gewechselt, wenn es Ihnen nichts ausmacht, dass einige seltsame Fälle durchfallen. Für meine Zwecke war es mir egal, das war ideal.
el n00b

3

Allgemein,

/^#{URI::regexp}$/

funktioniert gut, aber wenn Sie nur übereinstimmen möchten httpoder https, können Sie diese als Optionen an die Methode übergeben:

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

Das funktioniert etwas besser, wenn Sie Protokolle wie ablehnen möchten ftp://.


-2

Sie können auch einen regulären Ausdruck verwenden, z. B. http://www.geekzilla.co.uk/View2D3B0109-C1B2-4B4E-BFFD-E8088CBC85FD.htm, sofern dieser reguläre Ausdruck korrekt ist (ich habe ihn nicht vollständig überprüft) Zeige die Gültigkeit der 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
}

Das obige Beispiel gibt aus:

http://hello.it is valid
http:||bra.ziz not valid

5
Was ist mit dem Mailto-Schema? Oder Telnet, Gopher, Nntp, Rsync, SSH oder eines der anderen Schemata? URLs sind etwas komplizierter als nur HTTP und FTP.
Mu ist zu kurz

Das Schreiben von Regex zum Überprüfen von URLs ist schwierig. Warum die Mühe?
Rimian

@Rimian, du musst dich darum kümmern, weil alles, was du URItun kannst, tatsächlich kaputt ist. Siehe Kommentare unter den oben genannten Antworten. Ich bin mir nicht sicher, ob Janies Antwort richtig ist, aber ich stimme zu, dass die Leute es hoffentlich ernsthafter betrachten. TBH mache ich am Ende, url.start_with?("http://") || url.start_with?("https://")weil ich nur HTTP benötige und die Benutzer dafür verantwortlich sein sollten, die richtigen URLs zu verwenden.
Akostadinov
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.