2016-10-21 4 views
0

ich eine riesige Liste von Tripeln wie diese:Parsing-Ergebnisse SPARQL Hostnamen erhalten

?s ex:url ?url 

Wo ?url sein:

www.ex.com/data/1.html 
www.ex.com/data/2.html 
www.google.com/search 
... 

Ist es möglich, mit einer SPARQL Query, zu filtern, die Fragen Sie irgendwie und erhalten Sie die eindeutige Liste von Domains? In dem Beispiel www.ex.com und www.google.com.

Somthing wie folgt aus:

SELECT distinct ?url 
WHERE { ?s ex:url ?url } 

Aber jede URL binden zu behandeln. Natürlich könnte ich sie alle bekommen, und jede URL einzeln in meinem Programm behandeln, aber ich nehme an, eine Sparql-Abfrage wäre mehr Speicher effizient. Ich benutze Stardog - falls es eine benutzerdefinierte Funktion hat.

+0

Sie könnten die Domäne einer URL an eine neue Variable BIND und dann diese Variable SELECT. Weitere Informationen finden Sie in den SPARQL-Spezifikationen für String-Operationen und REGEX. So etwas wie die Teilzeichenfolge bis zum ersten Auftreten von '/' sollte funktionieren. – AKSW

+0

Kannst du bitte erläutern, wie ich die Domain der URLs an eine neue Variable binden könnte? Ich kenne die REGEX-Operationen, aber sie scheinen Ergebnisse über FILTER – user1156544

Antwort

2

Verwendung REPLACE mit REGEX:

BIND(REPLACE(STR(?url), "^(.*?)/.*", "$1") AS ?domain) 

Example in Yasgui

Edit: Wie @JoshuaTailor in den Kommentaren erwähnt, STRBEFORE ist besser, wenn es keine Regelung ist url:

BIND(STRBEFORE(?url, "/") AS ?domain) 

Wenn Sie sich um das URL-Schema kümmern müssen (dies verwirft das Schema):

BIND(REPLACE(STR(?url), "^(https?://)?(.*?)/.*", "$2") AS ?domain) 

Natürlich funktioniert das obige nur für grundlegende http (s) URLs, und die Regex wird etwas komplexer, wenn beliebige URLs behandelt werden müssen.

Hier ist eine, die jeden oder fehlende Regelung, die Portnummer Griffe, Auth-Info, und fehlende Schrägstrich:

BIND(REPLACE(?url, "^(?:.*?://)?(?:.*[email protected])?([^:]+?)(:\\d+)?((/.*)|$)", "$1") AS ?domain) 

Hinweis, die mit regulären Ausdrücken Abfragen kann sehr langsam sein.

+0

zu verwerfen. Ihr 2. Regex funktioniert großartig! Vielen Dank! Der erste gibt nur http: // zurück, also vermute ich, dass er für meinen Fall weiter tunen muss, aber der zweite ist gut. Ich werde einen Leistungstest machen, weil, wie Sie sagten, es sehr teuer sein könnte – user1156544

+0

Es gibt keine Notwendigkeit für Regex hier. Sie können STRBEFORE einfach verwenden und die Zeichenfolge vor '/' abrufen. Und der zweite REGEX funktioniert nicht für Nicht-HTTP (S) -URLs wie "ftp", usw. Dies würde auch Probleme mit URLs haben, die Authentifizierungsinformationen und Portinformationen enthalten (z. B. "http: // user: password" @ example.org: 8080/index.html ', wo du' user: [email protected]: 8080' bekommen würdest –

+0

Übrigens sollte auch der erste für meine Frage funktionieren - mein Fehler, das habe ich vergessen die realen Daten haben das Schema (http: // ...) – user1156544

5

Sie können so etwas mit einer Zeichenfolgenmanipulation durchführen, für die keine regulären Ausdrücke erforderlich sind. Zum Beispiel können Sie den Teil der Zeichenfolge Form der URL nach einem „//“ und vor einem „/“ nehmen:

select ?url ?hostname { 
    values ?url { <http://example.org/index.html> } 
    bind(strbefore(strafter(str(?url),"//"),"/") as ?hostname) 
} 
--------------------------------------------------- 
| url        | hostname  | 
=================================================== 
| <http://example.org/index.html> | "example.org" | 
--------------------------------------------------- 

, die nicht reguläre Ausdrücke nicht verwendet, und können schneller sein als eine Lösung mit der Regex Funktion.

Allerdings könnte dies noch erhalten Sie mehr als einen Hostnamen, zum Beispiel, wenn die URL so etwas wie http: // username: [email protected]: 8080, wo Sie Benutzernamen bekommen würde: Passwort @ example.org:8080, das ist mehr als nur Hostname.

Um dies genauer zu machen, sollten Sie eine der URI/URL-Spezifikationen wie RFC 3986 auswählen und einen Blick auf den Abschnitt über Syntaxkomponenten werfen.Einige relevanten Produktionen von dieser Grammatik sind:

URI   = scheme ":" hier-part [ "?" query ] [ "#" fragment ] 

     hier-part = "//" authority path-abempty 
       /path-absolute 
       /path-rootless 
       /path-empty 

Die Autorität Komponente durch einen Doppelstrich („//“) vorgeschaltet ist und durch den nächsten Schrägstrich beendet („/“), Fragezeichen ("?") oder Nummer Zeichen ("#") Zeichen, oder am Ende der URI.

authority = [ userinfo "@" ] host [ ":" port ] 

Ich werde nicht durch alles, was Arbeit (und vielleicht wäre es sinnvoll, einen regulären Ausdruck zu verwenden, um die komplexen Fälle zu behandeln), aber es könnte sein, am einfachsten, nur die URI nehmen von der SPARQL Ergebnis und verwenden Sie dann eine tatsächliche URI-Parsing-Bibliothek, um den Hostnamen zu erhalten. Das ist die zuverlässigste Lösung, da URIs sehr komplex sein können.

+0

STRBEFORE + STRAFTER funktioniert nicht, wenn die URL nicht vollständig ist (fehlendes Schema), wie in den Beispielen in der Frage.Obwohl das offenbar nicht der Fall war aktuelle Daten – evsheino

+0

Ich stimme mit Ihrem letzten Absatz überein.Mit einer URI-Parsing-Bibliothek klingt wie die robusteste Weise, dies zu programmieren.Ich werde auch Ihre Lösung überprüfen und alle Zeiten messen, um zu sehen, welche der 3 Optionen besser funktionieren – user1156544