Здравствуйте.
После посещения одной конференции у меня появилась идея, воплощение которой я и представляю.
Данный пост предоставляет пример работы с библиотеками grab и rdflib, а также готовый класс для выполнения SPARQL запросов к содержимому web-страниц.
Использовать данный инструмент предполагается для превращения информации с сайтов, которые не предоставляют её в структурированном виде (rdf-тройки, xml, json), в понятный «машинам» вид.
С целью выполнения SPARQL запросов к html содержимому необходимо создать локальное rdf хранилище, и наполнить его информацией, полученной из html страницы посредством grab.
Для начала импортируем все необходимые библиотеки, а также зарегистрируем использование SPARQL плагина.
Определим наш класс, и построим конструктор для него.
Конструктор может принимать url страницы, которую необходимо раcпарсить и поместить в хранилище, а также может определять нестандартное расположение определения пространства имён.
Далее необходимо определить служебную функцию для наполнения хранилища содержимым страницы.
В локальное хранилище помещается следующая информация о элементах:
Следующая служебная функция рекурсивно проходит по дереву элементов собирая необходимую информацию и добавляя её в хранилище.
Данная функция выполняет SPARQL запрос к локальному хранилищу.
Данная функция наполняет хранилище содержимым указанной страницы.
И напоследок, несколько простых примеров запросов.
Результат исполнения запроса на вывод всех ссылок на скрипты:
Таким образом, существует 3 способа наполнить хранилище:
GIST проекта, содержит также определение пространства имен посредством xml. Пространство имен определяет, что является тегом, закладывает необходимые свойства и отношения а также определяет тэги html 4.
Рекомендуемая литература:
«Programming the Semantic Web» By Toby Segaran, Colin Evans, Jamie Taylor
После посещения одной конференции у меня появилась идея, воплощение которой я и представляю.
Данный пост предоставляет пример работы с библиотеками grab и rdflib, а также готовый класс для выполнения SPARQL запросов к содержимому web-страниц.
Использовать данный инструмент предполагается для превращения информации с сайтов, которые не предоставляют её в структурированном виде (rdf-тройки, xml, json), в понятный «машинам» вид.
С целью выполнения SPARQL запросов к html содержимому необходимо создать локальное rdf хранилище, и наполнить его информацией, полученной из html страницы посредством grab.
Для начала импортируем все необходимые библиотеки, а также зарегистрируем использование SPARQL плагина.
# -*- coding: utf-8 -*- import grab import rdflib from rdflib import * from rdflib import plugin plugin.register( 'sparql', rdflib.query.Processor, 'rdfextras.sparql.processor', 'Processor') plugin.register( 'sparql', rdflib.query.Result, 'rdfextras.sparql.query', 'SPARQLQueryResult')
Определим наш класс, и построим конструктор для него.
Конструктор может принимать url страницы, которую необходимо раcпарсить и поместить в хранилище, а также может определять нестандартное расположение определения пространства имён.
class SQtHD(): ''' sparql query to html documents ''' def __init__(self,url=None,htmlNamespace='http://localhost/rdf/html#'): ''' Constructor ''' self.__grab__=grab.Grab()#Наш парсер self.__storage__=Graph()#Наше хранилище self.__namespace__=Namespace(htmlNamespace)#Создаем пространство имен self.__storage__.bind('html', URIRef(htmlNamespace))#Задаем пространству имен короткое имя self.__initnamespace__=dict(self.__storage__.namespace_manager.namespaces()) if url:#Если необходимо, то загружаем содержимое указанной страницы в хранилище. self.__store__(url)
Далее необходимо определить служебную функцию для наполнения хранилища содержимым страницы.
def __store__(self,url): self.__storage__.remove((None,None,None))#Очищаем хранилище self.__grab__.go(url)#Выполняем переход по указанному адресу средствами grab root=self.__grab__.tree.getroottree().getroot() self.__parse__(root)#Парсим содрежимое страницы.
В локальное хранилище помещается следующая информация о элементах:
- Информация о типе элемента (какой html тэг)
- Информация о родительском элементе
- Информация о позиции элемента по отношению к братьям
- Информация о уровне вложенности элемента
- Тест содержащийся в элементе
- Информация о количестве дочерних элементов
- Ссылки на дочерние элементы
- Значение атрибутов для элемента
Следующая служебная функция рекурсивно проходит по дереву элементов собирая необходимую информацию и добавляя её в хранилище.
def __parse__(self,element,parent=None,children_position=None,children_level=0): current_element=BNode() children_elements=element.getchildren() if str(element.tag)=='<built-in function Comment>': self.__storage__.add((current_element, RDF.type, self.__namespace__['comment'])) else: self.__storage__.add((current_element, RDF.type, self.__namespace__[element.tag])) if not parent==None: self.__storage__.add((current_element,self.__namespace__['parent'],parent)) self.__storage__.add((parent,self.__namespace__['children'], current_element)) self.__storage__.add((current_element,self.__namespace__['children_position'], Literal(children_position))) self.__storage__.add((current_element,self.__namespace__['children_level'], Literal(children_level))) if element.text and len(element.text.strip())>0: self.__storage__.add((current_element,self.__namespace__['text'], Literal(element.text.strip()))) if element.text_content() and len(element.text_content().strip())>0: self.__storage__.add((current_element,self.__namespace__['text_content'], Literal(element.text_content().strip()))) self.__storage__.add((current_element,self.__namespace__['children_count'], Literal(len(children_elements)))) for i in element.attrib: self.__storage__.add((current_element,self.__namespace__[i], Literal(element.attrib[i]))) for i in range(len(children_elements)): self.__parse__(children_elements[i],current_element,i,children_level+1)
Данная функция выполняет SPARQL запрос к локальному хранилищу.
def executeQuery(self,query,url=None): ''' execute query on storadge ''' if url:#Если необходимо, то загружаем содержимое указанной страницы в хранилище. self.__store__(url) return self.__storage__.query(query, initNs=self.__initnamespace__)#Возвращаем результат выполнения запроса.
Данная функция наполняет хранилище содержимым указанной страницы.
def loadStoradge(self,url): ''' load and parse html page to local rdf storadge ''' self.__store__(url)
И напоследок, несколько простых примеров запросов.
if __name__ == "__main__": endPoint = SQtHD()#Создаем экземпляр класса SQtHD endPoint.loadStoradge('http://habrahabr.ru')#Загружаем страницу в хранилище print "All sources for images given by tag <img>:"#Вывести все уникальные адреса картинок q=endPoint.executeQuery('SELECT DISTINCT ?src { ?a rdf:type html:img. ?a html:src ?src. }') for row in q.result: print row print print "All link urls:"#Вывести все уникальные адреса ссылок q=endPoint.executeQuery('SELECT DISTINCT ?href { ?a rdf:type html:a. ?a html:href ?href. }') for row in q.result: print row print print "All class names for elements:"#Вывести все уникальные имена классов q=endPoint.executeQuery('SELECT DISTINCT ?class { ?a html:class ?class. }') for row in q.result: print row print ''' print "All scripts (without loaded by src):"#Тест всех внутристраничных скриптов. q=endPoint.executeQuery('SELECT ?text { ?a rdf:type html:script. ?a html:text ?text. }') for row in q.result: print row print''' print "All script srcs:"#Все ссылки на скрипты. q=endPoint.executeQuery('SELECT ?src { ?a rdf:type html:script. ?a html:src ?src. }') for row in q.result: print row print
Результат исполнения запроса на вывод всех ссылок на скрипты:
All script srcs: /javascripts/1341931979/all.js /javascripts/1341931979/_parts/posts.js /javascripts/1341931979/_parts/to_top.js /javascripts/1341931979/_parts/shortcuts.js /javascripts/1341931979/libs/jquery.form.js /javascripts/1341931979/facebook_reader.js /js/1341931979/adriver.core.2.js /javascripts/1341931979/libs/highlight.js /javascripts/1341931979/hubs/all.js /javascripts/1341931979/posts/all.js
Таким образом, существует 3 способа наполнить хранилище:
- При инициализации класса
- Посредством функции loadStoradge
- При каждом запросе к хранилищу
GIST проекта, содержит также определение пространства имен посредством xml. Пространство имен определяет, что является тегом, закладывает необходимые свойства и отношения а также определяет тэги html 4.
Рекомендуемая литература:
«Programming the Semantic Web» By Toby Segaran, Colin Evans, Jamie Taylor
