Парсинг результатов 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 ответа

Решение

Используйте REPLACE с REGEX:

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 могут быть довольно сложными.

Другие вопросы по тегам