Семантическая сеть, ARC2 и PHP

в 8:18, , рубрики: php, semantic web, web 3.0, Семантическая Сеть, метки: , ,

Пока семантическая паутина только-только набирает обороты и захолустные веб-студии не взвинчивают цены за слова семантическая и семантический давайте посмотрим на инструменты для работы с этим зверем в php.

Стоит заметить, что в не-англоязычной сфере большинство терминов не устоялось, так же как не устоялось понимание концепции и технологии в целом. Для кого-то семантическая сеть это синоним html5 с вкусными плюшками, для кого-то это повсеместное применение RDF, развитие хранилищ и устройств, а для кого-то гарантированное получение пристойных фотографий по запросу мокрая киска ночью (не безопасно для работы).

О поддержке семантики в своих продуктах заявляют и реализуют drupal.org, ontowiki.net, semantic-mediawiki.org, talis.com и даже есть специальный WYSIWYG редактор loomp.org.

На данный момент (весна 2012ого) существуют два решения, претендующих на звание публичной библиотеки — это RDF API for PHP и ARC2.
RAP отложим до лучших времен, последняя версия датируется 2008 годом. Есть поддержка php 4 версии — это весьма сомнительное преимущество, но возможно кому-то потребуется. А вот после этой странички интерес к RAP пропал совсем.

Теория

Небольшой теоретический курс-введение, который можно смело пропустить и перейти к песочнице.

Словарь терминов:

  • triple, триплет — значения в форме субъект-предикат-объект
  • triplestore — хранилища триплетов
  • RDF — модель описания метаданных, основная идея которого базируется на использование триплетов хранения отношений, свойств и состояний информационного ресурса
  • RDF/XML, RDF/JSON, RDFa — описание модели в формате xml, json и в атрибутах элементов разметки
  • SPARQL — язык запросов к данным, описанными с помощью RDF

В качестве примера можно рассмотреть фразу «у Маши красная машина» и набор триплетов:

  • Маша владеет машиной
  • Маша есть человек
  • машина имеет цвет
  • цвет есть красный

С одной стороны из одной фразы получили четыре, а можно и больше, если продолжить описания человека, машины и цвета. C другой эти утверждения в разы проще для компьютерной обработки.
RDF применяется для унифицированного описания ресурса информации, т.е. в основе сколь угодно сложной модели выступает один концепт. Это позволяет сильно упростить реализацию хранилищ и стандартизировать язык запросов к нему (например, показать владельцев «машин красного цвета»).

Собираем песочницу

В качестве ящика будет библиотека ARC2, песком послужит стартовый пакет.
Конфигурация сервера не требует ничего экстра-ординарного, песочнице вполне хватает стандартного LAMP сервера из убунту.
Как минимум потребуются модули libxml, sockets для PHP 5.3.* и MySql в качестве хранилища, если у вас своя сборка сервера.
Установка проста до неприличия, нужно развернуть оба пакета и в файле tuukka-arc2-starter-pack/config.php прописать путь до библиотеки arc2:

include_once(dirname(__FILE__).'/../arc2/ARC2.php');

Папка с библиотекой переименована из semsol-arc2-xxxxxxx в простое arc2, а tuukka-arc2-starter-pack-xxxxxxx в tuukka-arc2-starter-pack.
Помимо пути в config.php нужно прописать настройки базы данных, за это отвечает секция ниже:

$arc_config = array(
  /* MySQL database settings */
  'db_host' => 'localhost', //имя сервера
  'db_user' => 'root', // имя пользователя
  'db_pwd' => '', // пароль, у меня он пустой
  'db_name' => 'arc2test', // название базы данных
//...

Если стартовый пакет установлен в директории веб-сервера, то запросив localhost/tuukka-arc2-starter-pack/endpoint.php появится форма для отправки запросов.
Запросы можно отправлять через консоль, для этого нужно разрешить исполнение файла tuukka-arc2-starter-pack/cli.php (chmod +x cli.php)
Большой разницы между запуском из под консоли или веб нету, кроме формата результа.
Веб песочница возвращает XML.

Лабораторной крысой будет страничка Эрика Миллера
В исходном коде странички интересует ссылка на данные для загрузки:

 <link rel="meta" type="application/rdf+xml" title="Contact" href="contact" />

Первое, с чего нужно начать — это добавить данные в наше хранилище с помощью запроса:

LOAD <http://www.w3.org/People/EM/contact#me>

Для запуска из-под консоли в папке tuukka-arc2-starter-pack запустите команду:

./cli.php "LOAD <http://www.w3.org/People/EM/contact#me>"

Ответ должен быть такой:

Loaded 32 triples

Через веб интерфейс такой:

<?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
  <head>
    <!-- query time: 0.3139 sec -->
  </head>
  <inserted>32</inserted>
</sparql>

Мы успешно загрузили данные, теперь запросим все имена в нашем хранилище:

PREFIX foaf: <http://xmlns.com/foaf/0.1/> 
SELECT ?name WHERE { ?x foaf:name ?name }

Ответ:

name 
Eric Miller

Технически язык запросов несколько напоминает SQL, но есть одно важно отличие:
SQL — язык запросов к таблице с данными, SPARQL — язык запросов к графу.

Запросим все ники и почтовые ящики контактов, которые есть в нашем хранилище:

PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?name ?nick ?mbox 
WHERE { 
?x foaf:name ?name . 
?x foaf:nick ?nick .  
x foaf:mbox ?mbox
}

Ответ:

name         nick  mbox 
Eric Miller  em    mailto:em@w3.org

Получить список все знакомых контактов:

PREFIX foaf: <http://xmlns.com/foaf/0.1/> 
SELECT ?name ?knows 
WHERE {
?x foaf:name ?name . 
?x foaf:knows ?knows 
}

Ответ:

name        knows 
Eric Miller http://www.w3.org/People/Berners-Lee/card#i 
Eric Miller http://www.w3.org/People/Connolly/#me 
Eric Miller http://www.w3.org/People/djweitzner/public/foaf.rdf#DJW 

Загрузим данные последнего контакта — Daniel Weitzner:

LOAD <http://www.w3.org/People/djweitzner/public/foaf.rdf#DJW>

Ответ:

Loaded 113 triples

Проверим еще раз всех знакомых контактов:

PREFIX foaf: <http://xmlns.com/foaf/0.1/> 
SELECT ?name ?knows 
WHERE {
?x foaf:name ?name . 
?x foaf:knows ?knows 
}

Ответ:

name             knows
Eric Miller      http://www.w3.org/People/Berners-Lee/card#i 
Eric Miller      http://www.w3.org/People/Connolly/#me 
Eric Miller      http://www.w3.org/People/djweitzner/public/foaf.rdf#DJW 
Daniel Weitzner  _:b279264211_arc8d9fb5 
Daniel Weitzner  _:b2309778025_arc8d9fb6 
Daniel Weitzner  _:b420706296_arc8d9fb9 
Daniel Weitzner  _:b2549551164_Tim 
Daniel Weitzner  _:b2407349360_arc8d9fb10 
Daniel Weitzner  _:b1728586196_DanC 
Daniel Weitzner  _:b4168748262_arc8d9fb11 
Daniel Weitzner  _:b1634950492_arc8d9fb12

Странных личностей знает Даниил.

Узнаем ник Даниила:

PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT  ?nick   
WHERE {
?x foaf:name 'Daniel Weitzner' . 
?x foaf:nick ?nick 
}

Ответ

nick 
Danny 

Обычно задача собрать информацию с web-источника решается в несколько приемов:

  1. найти источник с данными
  2. сграбить данные (с помощью регулярных выражений, запросами к дереву) или получить их от владельца сайта (RSS,API)
  3. сохранить в удобном хранилище
  4. использовать данные — получение и обработка

Это решение имеет один большой недостаток — для каждого источника приходится реализовывать получение данных.
Как следствие количество реализаций (граберов, хранилищ, запросов) может быть очень велико.
Наличие API существенно упрощает процесс, но о унификации и стандартизации думать не приходится (к тому же API не всегда данные).

Концепция семантический сети предполагает наличие источников, как страничка контактов Эрика Миллера, которые удобные для работы с контентом на ней.
В этом отличие от сегодняшнего и вчерашнего дня.

В бой

Посмотрим более детально на библиотеку ARC2.
Код, который получает данные со страницы Эрика и выводит их в «сыром» виде:

include_once("arc2/ARC2.php");
$parser = ARC2::getRDFParser(); 
$parser->parse('http://www.w3.org/People/EM/contact#me');
print_r($parser->getTriples());
//print_r($parser->getSimpleIndex()); # применена пост-фильтрация

Вывод:

Array
(
    [0] => Array
        (
            [s] => http://www.w3.org/People/EM/contact#me
            [p] => http://www.w3.org/1999/02/22-rdf-syntax-ns#type
            [o] => http://xmlns.com/foaf/0.1/Person
            [s_type] => uri
            [o_type] => uri
            [o_datatype] => 
            [o_lang] => 
        )

    [1] => Array
        (
            [s] => http://www.w3.org/People/EM/contact#me
            [p] => http://www.w3.org/1999/02/22-rdf-syntax-ns#value
            [o] => Eric Miller, em@w3.org
            [s_type] => uri
            [o_type] => literal
            [o_datatype] => 
            [o_lang] => 
        )
    //....
)

Структура массива триплетов оговорена:

  • s значение субъекта (URI, Bnode ID, или переменная)
  • p URI свойства или переменной
  • o значение объекта ( URI, Bnode ID, литерал или переменная)
  • s_type «uri», «bnode» или «var»
  • o_type «uri», «bnode», «literal» или «var»
  • o_datatype URI типа
  • o_lang индентификатор языка, например «en-us»

Вместо getTriples() можно использовать getSimpleIndex(), тогда вывод станет более содержательным:

Array
(
    [http://www.w3.org/People/EM/contact#me] => Array
        (
            [http://www.w3.org/1999/02/22-rdf-syntax-ns#type] => Array
                (
                    [0] => http://xmlns.com/foaf/0.1/Person
                )

            [http://www.w3.org/1999/02/22-rdf-syntax-ns#value] => Array
                (
                    [0] => Eric Miller, em@w3.org
                )

            [http://xmlns.com/foaf/0.1/name] => Array
                (
                    [0] => Eric Miller
                )
         //...
      )
   )

Используем хранилище песочницы для примера с запросами (копируем из config.php):

$config = array(
  /* db */
  'db_host' => 'localhost',
  'db_user' => 'root',
  'db_pwd' => '',
  'db_name' => 'arc2test1',


  /* store name (= table prefix) */
  'store_name' => 'sandbox',
);

/* instantiation */
$store = ARC2::getStore($config);

$q = ' 
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?nick 
 WHERE   { ?x foaf:nick ?nick .}
';

$rows = $store->query($q);
print_r($rows);
print_r($store->getErrors());

Результат:

Array 
 (
  [query_type] => select
  [result] =>  Array 
    (
    [variables] =>  Array (
      [0] => nick
    )
    [rows] => Array (
      [0]=> Array (
        [nick] => em
        [nick type] => literal
      )
      [1]=> Array (
        [nick] => Danny
        [nick type]=> literal
      )
    )
  )
  [query_time] => 0.060401201248169
)

Далее работаем с массивом как нам нужно.

Интересное на этом не заканчивается, библиотека ARC2 имеет много интересных функций, а про семантику можно еще лет десять писать диссертации, но все это выходит за рамки статьи.
Однако, надеюсь, знакомство состоялось.
Спасибо за внимание!

Автор: Exbe

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js