zlukfo@gmail.com
  • Публикации
  • Темы
  • Ключевые слова
  • Архив

Две техники парсинга источников в Интернет

Под источником данных в данной статье подразумевается статический объект (файл) или динамический (генерируемый скриптом), который содержит данные в формате xml(html) и доступный для чтения по протоколу http(s). Источниками, попадающими под наше определение являются:

  • статические html станицы сайтов
  • динамические страницы, генерирующие контент в формате xml(html)
  • ленты rss новостей
  • ...

Для извлечения данных из источников данных существует 2 техники

  1. двухпроходный парсинг. Его работа выполняется в два этапа. На первом из источника извлекаются и сохраняются в файл все ссылки, содержащие необходимые данные. На втором этапе парсер переходит по каждой ссылке, извлекает необходимые данные и сохраняет их в базу.
  2. циклический парсинг. Парсер через определенные промежутки времени обращается к источнику данных по одному адресу, извлекает данные и сохраняет их в базу. Особенность данного типа в том, что данные по одному адресу являются динамическими, изменяющимися с течением времени.

Отличия, особенности, алгоритмы

Двухпроходный парсинг

Главная его особенность состоит в типе ссылки на источник данных:

  • каждый объект информации (в терминологии бд - запись таблицы) расположен по статическому уникальному адресу
  • зачастую (не всегда) адрес на объект информации формируется по некоторому шаблону

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

Исходя из сказанного, данная техника парсинга имеет следующий алгоритм

  1. Генерируется файл со списком ссылок на объекты информации. Здесь есть два пути.

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

1.2. Шаблона не сущесвует. В этом случае создается скрипт, который, начиная с корневого источника данных собирает все ссылки на другие источники, содержащиеся по текущей ссылке, сохраняет их в файл, затем переходит по каждой из этих ссылок и повторяет дейсвие. Вот пример скрипта, соверщающего такой рекурсивный обход.

  1. Выполняется обращение к каждой собранной ссылке по которой извлекается объект информации
  2. Извлеченный объект сохраняется в БД

Циклический парсинг

Как было сказано выше, источник данных для такого вида парсинга имеет динамический контент и единственный адрес, по которому данный контент находится. Подавляющую долю источников данных такого типа составляют ленты новостей с форматом данных rss (формат описан в нотации xml). Rss формат имеет, как правило стандартный набор узлов, хранящих данные, поэтому написанный парсер подойдет для различных источников данных. Обший алгоритм парсинга такой.

  1. Парсер с заданной периодичностью обращается по указанному источнику, извлекает данные и сохраняет их во временный файл, в нашем случае это будет csv-файл.
  2. При следующем обращении парсера к источнику, перед тем, как очередная порция информации (запись бд) будет добавлена в csv-файл, может проверяться ее уникальность. Не уникальные записи игнорируются.
  3. Через определенный промежуток времени парсер сохраняет данные в бд и очищает csv-файл.
  4. Цикл повторяется.

Подробнее реализация циклического парсера описана в статье

Промежуточные задачи техник парсинга

Обе описанные техники парсинга имеют несколько общих задач, которые нехобходимо решать в процессе их реализации.

Задача исключения дубликатов объектов информации

Данная задача может быть решена и на уровне бд. Но с целью обобшения использования парсера и во избежание дополнительной нагрузки на бд проверка уникальности записи будет выполняться на уровне парсера.

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

  1. Проверка уникальности может выполняться по одному или нескольким полям записи. Список полей определяется в настройках запуска парсера.
  2. Порядок проверки выполняется начиная от последних добавленных записей. Аргументом для данного требования является следующая эмпирическая аксиома - вероятность того, что текущая запись является дубликатом ранее сохраненной уменьшается с увеличением интервала времени между получением первой записи и ее текущего дубликата (в частности, это правило действует для rss лент новостей). В том случае, если наше утверждение верно, это позволит сократить время, затрачиваемое на проверку уникальности записи.
  3. Проверку уникальности можно открючить в настройках запуска парсера.

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

# функция обращается к файлу хешей и возвращает генератор на хеши, начиная с конца файла
def _getStringFromEndFile(filename, string_len, delimiter_line_len=1, emty_line_in_end=True):
        if not os.path.exists(filename):
                return
        with codecs.open(filename, 'r', 'utf-8') as hk:
                if emty_line_in_end:
                        hk.seek(0,2)
                else:
                        hk.seek(1,2)
                while hk.tell()>string_len:
                        hk.seek(-(string_len+delimiter_line_len),1)
                        yield hk.read(string_len)
                        hk.seek(-string_len,1)
        yield None

# функция по хешу проверяет уникальность ОДНОЙ записи
def getDataFromSource(filename ,h):
        hk=codecs.open(filename, 'a', 'utf-8')
        for line in _getStringFromEndFile(filename, 56):
                if line==h:
                        return 0
        hk.write(h+'\n')
        hk.close()
        return 1

Подробнее о функции _getStringFromEndFile() можно прочитать в этой статье

При вызове _getStringFromEndFile() предполагается, что длина хена равна 56 (sha224). Если для расчета используется другой алгоритм хеша - подставить необходимую длину.

Запуск парсера в режиме демона

Восстановление структуры источника данных

В ходе работы парсер выполняет следующие действия

  1. подключается к указанной базе (единожды, при запуске парсера)
  2. извлекает данные из источника и сохраняет их в csv файл
  3. При следующем обращении парсер, прежде чем добавить извлеченные данные в csv файл, проверяет существование каждой записи в нем. Существующие данные повторно не добавляются
  4. При наступлении времени созранить извлеченные данные в базу, парсер выполняет эту операцию и затем очищает csv файл.
  5. цикл повторяется

В ходе работы парсер создает четыре влеменных файла

  • файл логов - в нем созхраняется время обращения к источнику и количество новых записей, добавленных в csv файл
  • сам csv файл
  • файл ошибок - хранит время ошибки и ее описание
  • файл критических ошибок. в него записываются ошибки прерывающие работу скрипта.

Настройки парсера для конкретного проета хранятся в отдельном файле params.py


Опубликовано

авг. 22, 2016

Тема

Анализ текста

Ключевые слова

  • парсинг 2
  • zlukfo@gmail.com - Публикации на тему разработки web-приложений
  • Все авторские права защищены
  • Автор и разработчик блога zlukfo. Theme: Elegant by Talha Mansoor