Главная страница
Навигация по странице:

  • Соединение с базой данных

  • Определение класса Python для отображения в таблицу

  • Настройка отображения Теперь нужно указать SQLAlchemy, что таблица users соответствует классу User.>>> from

  • Одновременное создание таблицы, класса и отображения

  • Создание сессии

  • Добавление объектов в БД

  • Для Герасимова 2. Разработка модели потребительских предпочтений на основе данных рекомендательной сети epinions com


    Скачать 2.87 Mb.
    НазваниеРазработка модели потребительских предпочтений на основе данных рекомендательной сети epinions com
    Дата11.06.2022
    Размер2.87 Mb.
    Формат файлаdocx
    Имя файлаДля Герасимова 2.docx
    ТипДокументы
    #584719
    страница3 из 16
    1   2   3   4   5   6   7   8   9   ...   16

    Технологии


    Сбор и обработка большого объема данных требует активного применения современных информационных технологий. Наша задача требует разработки собственных программ, поскольку стандартные средства не могут предоставить необходимой гибкости. В этом разделе будет рассказано о том, какие технологии и как применялись при выполнении данной работы, будут приведены теоретические сведения о некоторых из них и ссылки на справочные материалы.
        1. Сбор данных


    Процедуры сбора данных с сайта epinions.com были написаны на языке Python. Этот язык хорошо подходит для подобных задач благодаря своей простоте, а также наличию большого количества полезных библиотек с хорошей документацией. Кроме того, автор имел некоторый опыт работы с Python, что в итоге явилось решающим фактором в пользу выбора этого языка в качестве инструмента для автоматизированного сбора данных.

    Для хранения информации, собранной с сайта, использовалась СУБД SQLite [17]. Главными ее преимуществами являются простота использования и настройки.

    Останавливаться на базах данных и языке Python мы не будем. По вопросам проектирования баз данных можно обратиться к книге [2]. Синтаксис и логику программ на Python легко будет понять каждому, кто знаком с каким-нибудь современным языком программирования. Об основных принципах и синтаксисе языка можно прочитать в официальной документации [15].

    В этом разделе лучше уделить внимания технологиям, которые, по мнению автора, больше других помогли пройти самый технически сложный этап работы – реализацию системы сбора данных.
          1. Технология ORM


    ORM (англ. Object-relational mapping, рус. Объектно-реляционное отображение) — технология программирования, которая связывает базы данных с концепциями объектно-ориентированных языков программирования, создавая «виртуальную объектную базу данных».

    Для иллюстрации возможностей технологии рассмотрим какое-нибудь простое приложение, например, коллективный блог. В таком блоге пользователи могут оставлять свои записи (посты) и комментарии к ним. Для реализации приложения могут быть введены объекты: User (пользователь), Post (пост) и Comment (комментарий). Время жизни этих объектов не ограничено временем работы создающей их программы. Объекты предназначены для длительного хранения в базе данных с сохранением всех отношений между ними.

    Реляционные БД – наиболее распространенный тип баз данных в настоящее время, однако объектная модель данных резко отличается от реляционной, что заставляет писать программное обеспечение, которое должно уметь как обрабатывать данные в объектно-ориентированном виде, так и сохранять эти данные в реляционной форме. Постоянная необходимость в преобразовании между двумя разными формами данных не только сильно снижает производительность, но и создает трудности для программистов, так как обе формы данных накладывают ограничения друг на друга. Реляционные базы данных используют набор таблиц, представляющих простые данные. Дополнительная или связанная информация хранится в других таблицах. Часто для хранения одного объекта в реляционной базе данных используется несколько таблиц. Это требует применения операции JOIN для получения всей информации, относящейся к объекту. Например, в рассмотренном примере с коллективным блогом для хранения пользователя может использоваться дополнительная таблица со странами, в которых проживают пользователи.

    Технология ORM направлена на решение указанной проблемы и обеспечивает автоматическое преобразование объектных структур в памяти приложения в форму, удобную для хранения в реляционных базах данных, а также для решения обратной задачи — развертывания реляционной модели в объектную, с сохранением свойств объектов и отношений между ними. На сегодняшний день для большинства языков программирования существуют как коммерческие, так и бесплатные реализации технологии ORM. В этой работе использовалась одна из систем ORM для языка PythonSQLAlchemy [17].

    Покажем на примере SQLAlchemy основные принципы работы с ORM.

    Соединение с базой данных

    Создадим БД SQLite в оперативной памяти. Чтобы соединиться с базой, мы используем функцию create_engine():

    >>> from sqlalchemy import create_engine

    >>> engine = create_engine('sqlite:///:memory:', echo=True)
    Флаг echo включает ведение лога через стандартный модуль logging Питона. Когда он включен, мы увидим все созданные нами SQL-запросы.
    Создание таблицы

    Далее нужно задать структуру наших таблиц. Вернемся к примеру с блогом и создадим таблицу users. В ней мы будем хранить записи о зарегистрированных пользователях. Мы определим нашу таблицу внутри каталога MetaData, используя конструктор Table(), который по принципу действия аналогичен SQL-команде CREATE TABLE:

    >>> from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey

    >>> metadata = MetaData()

    >>> users_table = Table('users', metadata,

    ... Column('id', Integer, primary_key=True),

    ... Column('name', String),

    ... Column('fullname', String),

    ... Column('password', String)

    ... )
    Далее мы пошлем базе команду CREATE TABLE, параметры которой будут взяты из метаданных нашей таблицы. Вызовем метод create_all() и передадим ему наш объект engine, который и указывает на базу.

    >>> metadata.create_all(engine)
    Заметим, что колонки VARCHAR создаются без указания их длины. В SQLite это вполне допустимый тип данных, но во многих других СУБД так делать нельзя. Для того чтобы создать таблицу в PostgreSQL или MySQL, нужно задать длину для строк:

    >>> Column('name', String(50))
    Поле «длина» в строках String, как и простая разрядность/точность в Integer, Numeric и т. п. не используются более нигде, кроме как при создании таблиц.
    Определение класса Python для отображения в таблицу

    В то время как класс Table хранит информацию о таблицах БД, он ничего не говорит о логике объектов, что используются нашим приложением. Создадим класс User, соответствующий таблице users.

    >>> class User(object):

    ... def __init__(self, name, fullname, password):

    ... self.name = name

    ... self.fullname = fullname

    ... self.password = password

    ...

    ... def __repr__(self):

    ... return "" % (self.name, self.fullname, self.password)
    __init__ — это конструктор, __repr__ - строковое представление класса, которое возвращается, например, при вызове оператора print.
    Настройка отображения

    Теперь нужно указать SQLAlchemy, что таблица users соответствует классу User.

    >>> from sqlalchemy.orm import mapper

    >>> mapper(User, users_table)


    Функция mapper() создаст новый объект класса Mapper и сохранит его для дальнейшего применения. Теперь создадим и проверим объект типа User:

    >>> user = User("Василий", "Василий Петров", "qweasdzxc")

    >>> print user #Напечатает

    >>> print user.id #Напечатает None

    Атрибут id, который не определен в __init__, все равно существует по той причине, что колонка id существует в объекте таблицы users_table. По умолчанию mapper() создает атрибуты класса для всех колонок, что есть в Table. Так как SQLAlchemy не было дано команды сохранить пользователя в базу, его id имеет значение None. Когда позже мы сохраним пользователя, в этом атрибуте будет храниться автоматически сформированное значение.
    Одновременное создание таблицы, класса и отображения

    Предыдущий пример, включающий таблицу Table, пользовательский класс и вызов mapper(), иллюстрирует классический вариант использования SQLAlchemy, в котором подчеркивается разделение задач. Большое число приложений, однако, не требуют такого разделения, и для них SQLAlchemy предоставляет более лаконичный стиль – декларативный.

    >>>from sqlalchemy.ext.declarative import declarative_base

    >>>Base = declarative_base()

    >>>class User(Base):

    ... __tablename__ = 'users'

    ... id = Column(Integer, primary_key=True)

    ... name = Column(String)

    ... fullname = Column(String)

    ... password = Column(String)

    ... def __init__(self, name, fullname, password):

    ... self.name = name

    ... self.fullname = fullname

    ... self.password = password

    ... def __repr__(self):

    ... return "" % (self.name, self.fullname, self.password)
    Функция declarative_base() определяет новый класс, который мы назвали Base. От него будут унаследованы все наши ORM-классы. Отметим, что объекты Column определены без указания имен соответствующих полей таблицы, так как они будут выведены из имен своих атрибутов. Объект Table, соответствующий классу User, доступен через атрибут __table__
    >>> users_table = User.__table__
    Создание сессии

    Чтобы осуществлять взаимодействие с базой данных, нужно создать сессию (объект класса Session). Для этого после подключения к базе данных, то есть на уровне вызова функции create_session(), можно определить класс Session, который будет служить фабрикой объектов Session.

    >>> from sqlalchemy.orm import sessionmaker

    >>> Session = sessionmaker(bind=engine)
    Теперь, чтобы начать взаимодействие с БД, нужно создать сессию. С помощью созданной фабрики объектов, это делается так:
    >>> session = Session()
    Добавление объектов в БД

    Чтобы добавить в БД объект, его нужно добавить в сессию.

    >>> vasyaUser = User("Василий", "Василий Петров", "qweasdzxc")

    >>> session.add(vasyaUser)
    Этот объект будет находиться в ожидании сохранения, SQL-запроса на сохранение объекта в БД пока послано не будет. Сессия пошлет SQL-запрос, чтобы сохранить пользователя, как только это понадобится, используя процесс сохранения на диск(flush). Если мы запросим пользователя из базы, то сначала вся информация о нем будет сохранена в базу, а запрос последует потом. Для примера, ниже мы создадим новый объект запроса (Query), который загружает объекты User. Мы отбираем записи по атрибуту name и говорим, что нам нужен только первый результат из всего списка строк. Возвращается объект, совпадающий с только что добавленным:
    >>> ourUser = session.query(User).filter_by(name="vasya").first()



    >>> vasyaUser == ourUser

    Cессия определяет, что возвращаемая запись совпадает с записью, которая уже была представлена во внутренней хэш-таблице объектов. Поэтому мы просто получили тот же самый объект, который только что добавили. Принцип технологии ORM, известный как карта идентичности, гарантирует, что все операции над конкретной записью внутри сессии оперируют одним и тем же набором данных. Как только объект с неким первичным ключом появится в сессии, все SQL-запросы в рамках этой сессии вернут тот же самый объект Python для этого первичного ключа. При попытке поместить в эту сессию другой объект с тем же первичным ключом будет выдана ошибка.

    Предположим, что Василий решил сменить пароль на более сложный. В нашем приложении это будет реализовано так:

    >>> vasyaUser.password = "prtpsnb!-4346"
    Сессия отслеживает изменения объектов, которые с ней ассоциированы.

    >>> session.dirty

    IdentitySet([])
    Теперь сообщим сессии, что мы хотим отправить все оставшиеся изменения в базу и применить все изменения, зафиксировав транзакцию. Это делается с помощью commit():

    >>> session.commit()

    Функция commit() сохраняет все изменения в базу и фиксирует транзакцию. Ресурсы подключений, что использовались в сессии, освобождаются. Дальнейшие операции с сессией произойдут в новой транзакции, которая снова запросит необходимые ресурсы по необходимости. Если посмотреть на атрибут id сохраненного пользователя, который ранее имел значение None, то можно убедиться, что ему присвоено новое значение.
    >>> vasyaUser.id

    1

          1. Язык запросов XPath


    XPath (XML Path Language) — язык запросов к элементам XML-документа, реализующий навигацию по документу XML. Язык был использован в этой работе при извлечении информации с веб-страниц парсером lxml [13]. Это оказалось возможным, поскольку навигация по HTML осуществляется так же, как и по XML. Расскажем кратко, как работает XPath.

    XML имеет древовидную структуру. В документе всегда имеется корневой элемент. У всех элементов дерева существуют потомки и предки, кроме корневого элемента, у которого предков нет, а также тупиковых элементов (листьев дерева), у которых нет потомков. Каждый элемент дерева находится на определенном уровне вложенности (далее — «уровень»). У элементов на одном уровне бывают предыдущие и следующие элементы.

    Это очень похоже на организацию каталогов в файловой системе, и строки XPath строятся аналогично путям к файлам.

    Рассмотрим, например, HTML документ:

    <html>

    <body>

    <div>Первый слой

    <span>блок текста в первом слоеspan>

    div>

    <div>Второй слойdiv>

    <div>Третий слой

    <span class="text">первый блок в третьем слоеspan>

    <span class="text">второй блок в третьем слоеspan>

    <span>третий блок в третьем слоеspan>

    div>

    <img />

    body>

    html>
    XPath-путь /html/body/*/span[@class] (полный синтаксис имеет вид /child::html/child::body/child::*/child::span[attribute::class]) будет соответствовать в нём двум элементам исходного документа — первый блок в третьем слое и второй блок в третьем слое. Рассмотрим на этом примере базовые принципы принципы построения пути XPath.

    Путь делится на шаги адресации, которые разделяются символом «косая черта» / . Каждый шаг адресации состоит из трех частей:

    • ось (в данном примере child::), это обязательная часть;

    • условие проверки узлов (в данном примере это имена элементов документа html, body, span, а символ * означает элемент с любым именем), также обязательная часть;

    • предикат (в данном примере attribute::class), необязательная часть, заключаемая в квадратные скобки, в которой могут содержаться оси, условия проверки, функции, операторы (+, -, <, > и пр.).

    Анализ ведется слева направо. Если первый символ это / , то путь адресации считается абсолютным (то есть от корня документа). При этом за узел контекста на первом шаге берется корневой элемент (html). Контекст — это некая точка отсчета, относительно которой рассчитывается следующий шаг адресации. Поэтому на каждом шаге адресации мы получаем новый набор узлов документа, и этот набор становится контекстом для следующего шага адресации.

    На втором шаге адресации (child::body) контекстом становится html элемент. Ось child:: говорит о том, что необходимо найти все непосредственные потомки элемента html, а условие проверки body говорит о том, что в формируемый набор элементов нужно включить все узлы с именем body. В ходе второго шага адресации получаем набор узлов, состоящий всего из одного элемента body, который и становится элементом контекста для третьего шага.

    Третий шаг адресации: child::* . Ось child:: собирает все непосредственные потомки элемента body, а условие проверки * говорит о том, что в формируемый набор нужно включить элементы основного типа с любым именем. В ходе этого шага получаем набор узлов, состоящий из трех элементов div и одного элемента img.

    Четвёртый шаг адресации: child::span . Теперь контекстом является набор из четырёх элементов. И следующий набор узлов создается в четыре прохода (за четыре итерации). При первой итерации узлом контекста становится первый div. Согласно заданной оси child:: и правилу проверки span, в набор включаются непосредственные потомки div-а, имя которых равно span. При второй итерации в набор ничего добавлено не будет, так как у второго div нет потомков. Третья итерация добавит в набор сразу три элемента span, а четвёртая ничего не добавит, так как у элемента img нет потомков. Итак, в ходе проверки получен набор узлов, состоящий из четырёх элементов span. Это и будет контекстом для последующей обработки.

    Следующего шага нет, поэтому будет производиться фильтрация отобранного набора. В этом и состоит отличие предикатов от шагов адресации. На каждом шаге адресации получаем новый набор, отталкиваясь от контекста, полученного на предыдущем шаге. В ходе же обработки предиката новый набор получается из текущего методом фильтрации, когда из набора исключаются узлы, не прошедшие условие проверки. В данном случае ось attribute:: говорит о необходимости проверить, если ли у узлов контекста атрибуты, а условие class требует оставить лишь те узлы, у которых задан атрибут с именем class. Фильтрация происходит за четыре итерации, но в окончательный набор попадают только два элемента span.

    Все современные браузеры имеют расширения, которые позволяют узнать путь XPath для выделенного элемента. В данной работе использовалось расширение FireBug для Firefox.
        1. Преобразование и анализ данных


    Для преобразования и анализа данных были использованы скрипты на языках R и SQL.

    Язык R специально предназначен для статистического анализа данных и включает в себя гибкие средства для удобной работы с табличными данными, векторами, графиками и т.п. Главное его достоинство – множество библиотек, в которых реализованы, пожалуй, все достаточно широко известные методы анализа данных: как классические, так и современные. Программы на R достаточно сложны для восприятия и требуют хорошего знакомства с языком. Во-первых, R имеет не совсем обычный синтаксис. Во-вторых, программы на R обычно очень абстрактные и краткие. Связано это с тем, что R – язык специализированный и имеет много функций для часто повторяющихся операций с данными, причем эти операции зачастую поддерживаются несколькими альтернативными библиотеками, каждая из которых вводит собственные абстракции. Это делает программы очень краткими и упрощает разработку, однако часто сильно затрудняет их восприятие. В качестве справочных ресурсов по R для начинающих можно назвать [10], [18].

    Язык запросов SQL широко распространен, и говорить мы о нем не будем. Хорошим руководством по SQL может послужить книга [3].
      1. 1   2   3   4   5   6   7   8   9   ...   16


    написать администратору сайта