0,0
рейтинг
16 сентября 2009 в 01:18

Теория лоадеров

За последние 5 лет я написал множество лоадеров. Это так называемые программки, которые парсят инфу на сайтах-источниках и сохраняют ее себе в базу. Зачастую они представляют из себя последовательность регулярных выражений, с помощью которых находятся значения в нужных клеточках. Лоадеры могут авторизоваться, могут коннектиться через прокси, а иногда даже распознавать защитные картинки. Суть не в этом.

Теоретическая проблема в том, что невозможно написать абсолютно автоматический лоадер. Мы можем затырить любую инфу, но база превращается в свалку, если лоадер теряет классификацию сайта-источника. А когда начинаем сохранять классификацию, возникает проблема.



Рассмотрим пример. Пусть есть автосайт, на который грузятся объявления о продаже авто с сотни других ресурсов. Лоадер парсит объяву, выдает массив:

{марка:"ford", модель:"focus", модификация:"1.6 Ti-VCT 5d", описание: итд...}.

Автоматический лоадер часто работает так: смотрит в таблице марок по названию, если есть ford — берет id марки, если нет — добавляет «ford» в марки, и берет его id. То же делает с моделью и модификацией. Потом добавляет объявление с полученными id-шниками. Такая система плоха тем, что обязательно найдется объява, в которой на месте марки будет «ФОРД» или не «ВАЗ», а «VAZ», или «автоВаз», или не «Санкт-Петербург», а «С-Петербург»,«СПб»,«Cп-б». Умный гугл поймет, что это синонимы, а наш глупенький лоадер, сверяющий названия посимвольно, нет. В результате получается бардак в таблицах с классификациями.

Пытаясь минимизировать ручной труд монгола/модератора, я придумал такой алгоритм.

Прежде всего, лоадер состоит из двух частей.

Первая — loader_pages.
Скрипт просматривает страницы со списками объявлений типа вот таких http://cars.auto.ru/cars/used/ford/focus/ и тупо собирает ссылки на отдельные объявы. + находит ссылки на переходы по страницам и идет по ним рекурсией. Нашел ссылку на объяву — добавил ее в базу или, если она уже добавлена, обновил «дату последнего нахождения» на текущую. Это нужно для того, чтобы (лоадер работает ежечасно) удалять объекты, у которых дата нахождения ссылки достаточно старая (это значит, что ссылка уже не найдена, а значит объект с источника был удален).

Вторая — loader_offer.
Берет из базы еще не обработанные ссылки, грузит html, парсит. Получает массив типа

{марка:"ford", модель:"focus", модификация:"1.6 Ti-VCT 5d", описание: итд...}

Грузит табличку compares. В ней находятся сопоставления, которые будут вручную обрабатываться модератором. Табличка состоит из полей:

{лоадер,тип,найденное значение,id в соответствующей таблице классификации}.

В нашем случае,

{лоадер:"auto.ru",тип:"марка",значение:"ford",сопоставление:"..."}.

Если соответствующее сравнение уже проставлено, ура победа, берем id-шник. Если нет — добавляем в compares новое сравнение, а объект не добавляем.

Модератор просматривает не проставленные сравнения и сопоставляет им значения из соответствующих «хороших» наших таблиц с марками автомобилей, моделями, городами итд.

Паренты.
Все хорошо работает пока таблицы маленькие. К примеру, марки авто — их всего 100. Сопоставить раз плюнуть. Моделей в моей базе 7000, а модификаций — 20.000. Представляете, из 20 тысяч выбрать сопоставление модификации «1.6 Ti-VCT 5d», которая у меня называется «1.6 Ti-VCT»? Модератор умирает. Или нужен хороший поиск.

Но можно сделать проще. При загрузке объявы мы будем обрабатывать сравнения по-порядку, сначала марка, затем модель, после модификация. Берем сравнение для марки,

{лоадер:"auto.ru",тип:"марка",значение:"ford",сопоставление:"..."},

находим его или добавляем — не суть. Берем id-шник этого сравнения и записываем его в дополнительное поле parent для сравнения модели:

{лоадер:"auto.ru",тип:"модель",значение:"focus",сопоставление:"...",parent:"id сравнения марки"}.

То же самое делаем в модификации, в парент которой пишем id сравнения модели.

Модератор работает по-порядку. Сначала берет сравнения марок и все их проставляет. Потом берет сравнение модели. При этом мы видим, что у сравнения есть parent-сравнение марки, которое уже проставлено, поэтому в качестве вариантов для сопоставления нужно выводить не все возможные модели, а только те, у которых марка соответствует значению этого parent-сравнения. Ну то есть «Ford» проставили, а затем «Focus» выбираем не из 7000 моделей, а только из сотни моделей фордов.

Суть этого поста вовсе не в том, что я придумал что-то абсолютно новое. Просто нигде не встречал описания этих программ. А у меня мне нравится именно излишняя практичность, потому что в принципе ясно, что каждый объект — подмножество вершин некоторых деревьев, а парсер — это сопоставление элементов html-кода страницы этим вершинам. Можно бы было навести теорию, что-то вроде языка для описания парсеров итд… С другой стороны, средний код лоадера на php у меня занимает 2 страницы. И не ясно, стоит ли париться с теорией, потому как мне не придумать, как еще уменьшить и упростить этот код, даже применив какой-то абстрактный язык.
Алексей Кузнецов @Kasheftin
карма
37,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое

Комментарии (28)

  • +16
    Я всегда думал, что лоадер — это загрузчик, а то, что вы описали — граббер. о_О
    • +1
      Это для него граббер -)) А для сайтов это — лоадер -))
      • +5
        crawler :)
    • +7
      угу, или граббер или парсер, смотря кому-как нравится. :) О лоадерах тоже первый раз слышу, это типа красивое слово, чтобы не было стыдно, что чужой контент воруется… :)
      • +2
        Ах, да, забыл — информация должна быть свободно… воруемой :)
  • 0
    на хабре если не ошибаюсь проскакивал библиотека, которую автор рекомендовал для граббинга лоадинга :)
    но названия не помню
  • +1
    Граббер (по-вашему лоадер) — это лишь извлечение информации с сайта. И на сколько я понял, с этим у вас ни каких проблем нет. Вопросы у вас возникают с классификацией, упорядочиванием и хранением отпарсенной информации и тут единой методики не существует — все зависит от конкретной задачи.

    Ваш алгоритм, на мой взгяд, не плох, за исключением того, что у него иерархаичная классификация. То есть, если марка «ФОРТ», а не «Ford», то система сразу отбросит эту запись для обработки модератором. А могла бы искать дальше, найти «Focus» и поскольку у других марок такой модели нет, сделать вывод, что это все-таки «Ford». Тоже самое касается и модификаци. Я думаю, что найдя классификацию «1.6 Ti-VCT» тоже вполне можно сделать вывод и том что имеется в виду. Но для этого в классификационной базе должно быть двустороннее сопоставление. Если эту систему грамотно выстроить, то модератор будет круглосуточно пить чай, обрабатывая только совершенные ляпы типа «ВАЗ Focus 600» =)
    • 0
      Спасибо. Конечно, нужно вставить эту проверку. Смотреть, если нет марки, на паренты подходящих моделей, и если найдено только одно значение, подставлять его автоматически. Другое дело, что есть системы похуже марок-моделей. Например, база населенных пунктов. В Финляндии около 20.000, при этом есть две деревни «Хельсинки», а «Лахти» вообще штук 8. Иногда кроме как по тексту объявления и не поймешь, какое же Лахти имеется ввиду на источнике.
      • 0
        И каким именно критерием в тексте выступает четкая локализация конкретного «Лахти»? Я имею в виду, когда человек смотрит за счет какой информации он делает вывод?
        • 0
          Делает вывод за счет своей эрудиции. Обычно если это не основное Лахти, в текстах написано типа «Лахти 10 км от Уусикаупунки». А модератор выводит все Лахти на карту и выбирает нужное.
          • 0
            Нда. Тут модеру ни чем не поможешь =)
          • 0
            Lahti — Залив (с Финского на Русский)
  • 0
    плюс можно добавить авто-проверку транслитерированных значений
    чтобы автоматом сопоставлялось ВАЗ-VAZ, ЛАДА-LADA и пр.
    в некоторых случаях позволяет несколько сэкономить человеко-время.
  • 0
    Интересно почитать как это делается у других=)
    А у нас есть специальные таблицы синонимов, причём (как писали выше) достаточно совпасть только модели, чтобы определить и производителя. Такой подход, конечно, полностью проблему не устраняет, но очень сильно снижает нагрузку на людей. Ну а что не распозналось, то да — отсматривается и, при необходимости, в базу добавляются новые синонимы.
  • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Есть два вопроса:
    1. Насколько сложно пользоваться гуглом для поиска синонимов (допустим, "wikipedia" обычно даёт первую ссылку на вики-страницу подходящего понятия)?

    2. Насколько легально использовать заграбленную информацию для коммерческих целей ()?

    Есть также соображение:
    Эти подходы очень напоминают алгоритмы поисковиков. Для последнего подхода, парентов, очень просится map-reduce. Думается, что грамотный лоадер — маленький гугл.
  • 0
    Лучше бы написал про защиту от грабберов
    • 0
      А такие бывают? Мне кажется в лучшем случае система максимального усложнения им жизни =)
    • 0
      Защиту от грабберов написать не очень сложно. Первое, что приходит на ум — перед выводом менять случайным образом названия стилей css в коде (соответственно, cssник менять тоже). Только кеширование отключить. Менять местами блоки в контенте. Важно помнить, что сколько человекочасов потратишь на защиту, за столько она и ломается.
      • 0
        Ну так это и не защита, а именно усложнение жизни грабберу =) Защита — это когда время взлома намного привышает время потраченное на защиту. А тут ничего подобного не замечается.
        • 0
          Кстати тут подумал, что изменять имена классов — это защита пепец грабберу. Особенно в web2.0, где одни дивы на странице. Придется cssник парсить и в нем понимать, какой класс — название параметра, какой — заголовок. А еще мы вообще к каждому элементу на странице прибавим случайный класс, а в css-нике все перемешаем.

          У меня в Питере был приятель, который занимался шифрованием программ. Вот только те методы не очень подходят к web, поскольку можно зашифровать так, что и поисковики ничего не разберут.
          • 0
            Я наверно слабо представляю как работает парсинг. Во всяком случае, всегда считал что парсинг идет по ДОМ-дереву, а не по css =) Оказывается, все намного сложнее =)
            • 0
              По dom-дереву то само собой. Но возьмите обычный сайт. У него есть меню, что-то сверху, сбоку, и все это в дивах или таблицах. Посередине контент тоже в дивах и таблицах. Вы ж не будете выбирать типа пятый тег и в нем третий тег в качестве, скажем, цены предложения. Иначе на сайт добавят баннер, и ваш парсер тут же накроется. А вот редизайн делают редко, и названия классов обычно не меняются.
              • 0
                Да, действительно… Это меня не радует, потому что мне в скором времени возможно придется писать подобный парсер. Собственно, именно поэтому я начинаю потихоньку интересоваться этим вопросом. Ты парсишь с помощью какой-то библиотеки или используешь самописный конечный автомат?

                И еще есть вопрос по поводу правомерности публикации информации, полученной путем подобного сбора. Знакомые недавно открыли агенство недвижимости и по причине малой раскрученности не имеют своего каталога. Вот и возникла идея собирать инфу с больших городских порталов объявлений и публиковать под девизом «у нас нет своего каталога, наш каталог — весь рынок недвижимости» =) Насколько правомерна такая идея?
                • 0
                  Пишу без библиотек на перле или пхп, стараюсь делать короткие независимые парсеры, больше сплитами чем реплейсами, потому как в случае ошибок на страницах источника последние часто привышают memory_limit, и из-за этого парсер останавливается и не грузит следующие «нормальные» страницы.

                  Правомерность — скользкий вопрос. Мы обычно спрашиваем разрешение на трансляцию. Скажем, если у нас портал по недвижимости, мы списываемся с агентствами, и они обычно рады, что их предложения будут у нас, поскольку все заявки по объектам все равно переадресовываются им обратно.
        • 0
          Главное особо не увлекаться этими защитами, а то получится как с картинками. Знаете, на них раньше то на правую кнопку мыши alert выводили, чтобы не скопировали, то разбивали на много мелких картинок, то во флеш засовывали. А в итоге все равно, если очень хочется — жмакнул принтскрин и вырезал в photoshop. То же и с текстами. Будете наворачивать защиты, а придет школьник Вася и руками скопипастит все по 3 цента за страницу.
  • 0
    Просто нигде не встречал описания этих программ.

    Откройте для себя удивительный мир синтаксического анализа

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.