Пока семантическая паутина только-только набирает обороты и захолустные веб-студии не взвинчивают цены за слова семантическая и семантический давайте посмотрим на инструменты для работы с этим зверем в 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-источника решается в несколько приемов:
- найти источник с данными
- сграбить данные (с помощью регулярных выражений, запросами к дереву) или получить их от владельца сайта (RSS,API)
- сохранить в удобном хранилище
- использовать данные — получение и обработка
Это решение имеет один большой недостаток — для каждого источника приходится реализовывать получение данных.
Как следствие количество реализаций (граберов, хранилищ, запросов) может быть очень велико.
Наличие 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