Парсинг результатов SPARQL для получения имени хоста
У меня есть огромный список таких троек:
?s ex:url ?url
куда ?url
может быть:
www.ex.com/data/1.html
www.ex.com/data/2.html
www.google.com/search
...
Можно ли с помощью запроса SPARQL каким-то образом отфильтровать запрос и получить отдельный список доменов? В примере www.ex.com
а также www.google.com
,
Что-то вроде этого:
SELECT distinct ?url
WHERE { ?s ex:url ?url }
Но лечение каждого URL привязки. Конечно, я мог бы получить их все и обработать каждый URL один за другим в моей программе, но я полагаю, что запрос sparql будет более эффективным с точки зрения памяти. Я использую Stardog - в случае, если у него есть некоторые пользовательские функции.
2 ответа
BIND(REPLACE(STR(?url), "^(.*?)/.*", "$1") AS ?domain)
Редактировать: как @JoshuaTailor отметил в комментариях, STRBEFORE лучше, если в? Url нет схемы:
BIND(STRBEFORE(?url, "/") AS ?domain)
Если вам нужно беспокоиться о схеме URL (это исключает схему):
BIND(REPLACE(STR(?url), "^(https?://)?(.*?)/.*", "$2") AS ?domain)
Конечно, вышесказанное работает только для основных http(s) URL, и регулярное выражение становится несколько более сложным, если необходимо обрабатывать произвольные URL.
Вот тот, который обрабатывает любую или отсутствующую схему, номер порта, информацию об аутентификации и отсутствующую косую черту:
BIND(REPLACE(?url, "^(?:.*?://)?(?:.*?@)?([^:]+?)(:\\d+)?((/.*)|$)", "$1") AS ?domain)
Обратите внимание, что запросы с регулярными выражениями могут быть довольно медленными.
Вы можете сделать что-то подобное, используя манипуляции со строками, которые не требуют регулярных выражений. Например, вы можете взять часть строковой формы URL после "//" и перед "/":
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" |
---------------------------------------------------
Это не использует регулярные выражения, и может быть быстрее, чем решение, использующее функцию регулярного выражения.
Тем не менее, это все равно может дать вам больше, чем имя хоста, например, если URL-адрес примерно такой : http: // username: password@example.org: 8080, где вы получите имя пользователя: password@example.org: 8080, которое это больше, чем просто имя хоста.
Чтобы сделать это более тщательно, вы должны выбрать одну из спецификаций URI/URL и т. Д., Например RFC 3986, и взглянуть на раздел о компонентах синтаксиса. Несколько соответствующих произведений из этой грамматики:
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] hier-part = "//" authority path-abempty / path-absolute / path-rootless / path-empty
Компонент полномочий должен начинаться с двойной косой черты ("//") и завершаться следующей косой чертой ("/"), знаком вопроса ("?") Или знаком знака ("#") или концом URI.
authority = [ userinfo "@" ] host [ ":" port ]
Я не буду работать через все это (и, возможно, было бы более целесообразно использовать регулярное выражение для обработки сложных случаев), но может быть проще всего просто взять URI из результата SPARQL и затем использовать реальную библиотеку анализа URI чтобы получить имя хоста. Это самое надежное решение, поскольку URI могут быть довольно сложными.