Frontera: архитектура фреймворка для обхода веба и текущие проблемы +13


Всем привет, я занимаюсь разработкой Frontera, первым в истории фреймворком для масштабного обхода интернета сделанным на Python-е, с открытым исходным кодом. С помощью Фронтеры можно легко сделать робота который сможет выкачивать контент со скоростью тысяч страниц в секунду, при этом следуя вашей стратегии обхода и используя обычную реляционную БД или KV-хранилище для хранения базы ссылок и очереди.

Разработка Фронтеры финансируется компанией Scrapinghub Ltd., имеет полностью открытый исходный код (находится на GitHub, BSD 3-clause лицензия) и модульную архитектуру. Мы стараемся чтобы и процесс разработки тоже был максимально прозрачным и открытым.

В этой статье я собираюсь рассказать о проблемах с которыми мы столкнулись при разработке Фронтеры и эксплуатации роботов на ее основе.

Устройство распределенного робота на базе Фронтеры выглядит так:
image

На картинке изображена конфигурация с хранилищем Apache HBase и шиной данных Apache Kafka. Процесс запускается из воркера стратегии обхода (SW), который планирует URL-ы, с которых нужно начать обход. Эти URL-ы попадают «scoring log», топик кафки (выделенный канал сообщений), потребляются воркером БД и им же планируются в топик «new batches», откуда поступают в пауки на основе Scrapy. Паук Scrapy разрешает DNS имя, поддерживает пул открытых соединений, получает контент и посылает его в топик «spider log». Откуда контент потребляется снова воркером стратегии и в зависимости от логики закодированной в стратегии обхода он планирует новые URL-ы.

Если кому-то интересно, то вот видео моего доклада о том, как мы обходили испанский интернет с помощью Фронтеры.



На текущий момент мы столкнулись с тем, что людям которые пытаются развернуть робота у себя очень тяжело дается конфигурирование распределенных компонент. К сожалению, развертывание Фронтеры на кластере предполагает понимание ее архитектуры, чтение документации, правильную настройку шины данных (message bus) и хранилища под нее. Все это очень затратно по времени и отнюдь не для начинающих. Поэтому мы хотим автоматизировать развертывание на кластере. Мы выбрали Kubernetes и Docker для достижения этих целей. Большой плюс Kubernetes в том, что он поддерживается многими облачными провайдерами (AWS, Rackspace, GCE и др.) Т.е. с помощью него можно будет развернуть Фронтеру даже не имея настроенного Kubernetes кластера.

Другая проблема в том, что Фронтера она как система водоснабжения ядерной электростанции. В ней есть потребители и производители для них очень важно контролировать такие характеристики, как скорость потока и производительность, в разных местах системы. Здесь следует напомнить, что Frontera это онлайн система. Классические роботы (Apache Nutch), напротив, работают в пакетном режиме: сначала порция планируется, затем скачивается, затем парсится и снова планируется. Одновременный парсинг и планирование не предусмотрены в таких системах. Таким образом, у нас встает проблема синхронизации скорости работы разных компонент. Довольно тяжело спроектировать робота, который обходит страницы с постоянной производительностью с большим количеством потоков, при этом сохраняет их в хранилище и планирует новые. Разнится скорость ответа веб-серверов, размер и количество страниц на сайте, количество ссылок, все это делает невозможным точную подгонку компонент по производительности. В качестве решения этой проблемы мы хотим сделать веб-интерфейс на базе Django. Он будет отображать основные параметры и если получится подсказывать какие нужно принять меры оператору робота.

Я уже упоминал о модульной архитектуре. Как и любой проект с открытым кодом мы стремимся к разнообразию технологий, которые мы поддерживаем. Поэтому сейчас у нас в Pull Request’ах готовится поддержка распределенного Redis, было уже две попытки сделать поддержку Apache Cassandra, ну и мы бы хотели поддержку RabbitMQ в качестве шины данных.

Все эти проблемы мы рассчитываем хотя бы частично решить в рамках Google Summer Of Code 2017. Если Вам что-то кажется интересным, и Вы студент, то дайте нам знать на frontera@scrapinghub.com и подайте заявку через форму GSoC. Подача заявок начинается с 20 марта и продлится до 3 апреля. Полное расписание GSoC 2017 здесь.

Конечно же, есть еще и проблемы производительности. На данный момент в Scrapinghub в пилотном режиме работает сервис по массивному скачиванию страниц на основе Фронтеры. Клиент нам предоставляет набор доменов, к которым он бы хотел получить контент, а мы их скачиваем и помещаем в S3 хранилище. Оплата за скачанный объем. В таких условиях мы стараемся качать как можно больше страниц в единицу времени. При попытке масштабировать Фронтеру до 60 спайдеров мы с толкнулись с тем, что HBase (через Thrift интерфейс) деградирует при записи в него всех найденных ссылок. Эти данные мы называем ссылочной базой, а нужна она для того, чтобы знать когда и что мы скачали, какой ответ получили и т.п. На кластере из 7 регион серверов у нас кол-во запросов доходит до 40-50K в секунду и при таких объемах время ответа сильно увеличивается. Производительность записи сильно падает. Решать такую проблему можно разными способами: например сохранять в отдельный быстрый лог, а позже его пакетными методами записывать в HBase, или же обращаться в HBase напрямую минуя Thrift, через собственный Java клиент.

Также мы постоянно работаем над улучшением надежности. Слишком большой скачанный документ или внезапные сетевые проблемы не должны приводить к остановке компонент. Тем не менее это иногда случается. Для диагностики таких случаев мы сделали обработчик сигнала ОС SIGUSR1, который сохраняет в лог текущий стек процесса. Несколько раз нам это очень сильно помогло разобраться в чем была проблема.

Мы планируем и дальше улучшать Фронтеру, и надеемся что сообщество активных разработчиков будет расти.



Комментарии (32):

  1. yusman
    /#10142906

    Интересный продукт, спасибо!
    Подскажите, а Scrapinghub умеет работать с «динамическими» страницами с большим количеством JS? Например, ждать появления какого либо элемента страницы, прежде чем начать парсить страницу.

    • square
      /#10142964

      Это крайне нетривиальная задача, а тут обычный паук, вам нужен куда более «сообразительный» парсер.

      • gearbox
        /#10143806

        Тривиальная но крайне требовательная к ресурсам — так имхо правильнее. На фантоме пишется за вечер. Я писал.

        • roller
          /#10143952

          Для одного сайта. После того как вы посмотрели его глазами и нашли к чему привязаться в xpath (теги, id, вложенность). И написали скрипты именно для этого сайта. А сайтов тысячи.

          • gearbox
            /#10144446

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

            • roller
              /#10144862

              Ок. Отрендерили вы DOM, а если на живом сайте скролить вниз происходит подгрузка данных. То есть на первом шаге вы не получает все данные. Если это не критично, то конечно так можно поступить.

              • kirill3333
                /#10145108

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

                • gearbox
                  /#10145472

                  а это уже селениум c драйвером фантома. Но тут да — под каждый сайт (движок) свои хаки. Ну или подождать сильный ИИ )

              • gearbox
                /#10145464

                Да, в таком юзкейсе Вы правы и это очевидно. Я говорил именно об индексации страниц, генерируемых js без действий пользователя. Их тоже немало, других простых способов решить вопрос — нет, гугль, насколько мне известно поступает также.

    • asibiryakov
      /#10142996

      Пока что только применительно к конкретному веб-сайту. У нас есть своя разработка https://github.com/scrapinghub/splash

  2. square
    /#10142930

    Возможно перед HBase поставить фильтр Блума, чтобы поменьше его кантовать? Или там иного рода проблемы?

  3. slavenski
    /#10142986 / -1

    Я далек от Web'а, и сейчас, наверное, моя карма уйдет в небытие =), но подскажите, правильно ли я понял, разрабатывается фреймворк, который исполняет роль поисковика?

    • asibiryakov
      /#10142990

      Этот фреймворк скачивает документы из сети. Скачанный контент может использоваться для построения поисковика.

      • mizhgun
        /#10143138

        А мне всегда виделось, что Frontera это фреймворк не для скачивания, а для построения стратегии обхода URLов, в которую при желании можно впилить любую скачивающую часть, не только Scrapy.

        • asibiryakov
          /#10143234

          Это тоже верно. Просто по мере разработки мы поняли, что стратегия обхода отдельно от хранилища и от других компонент, отвечающих за обмен данными не представляет большой пользы. В результате мы разработали эти компоненты и приняли решение, что Фронтера будет навязывать архитектуру всего робота. При этом мы старались сделать её максимально расширяемой.

          • mizhgun
            /#10143306

            Не следил за Фронтерой уж год наверное. То есть архитектурно вы как-то жестко сейчас завязаны именно на Скрапи?

            • asibiryakov
              /#10144684

              Использование Scrapy не является обязательным при построении роботов на Fronter'е. Но если Вы берете воркер стратегии, разрабатываете под него стратегию обхода, то должны будете считаться с тем, как во Fronter'е реализован менеджмент состояний, очередь и обмен данными между компонентами.

    • Carburn
      /#10143924

      Он роль поискового робота выполняет.

  4. mizhgun
    /#10143222

    Имхо, если у людей есть четкое понимание, что такое Frontera, зачем она им надо и как ее готовить, то вряд ли подъем и настройка HBase и Kafka вызовет у них какие-то прямо проблемы. Другой вопрос, что тюнить их под задачу уже нетривиально, но это в любом случае, независимо от навыков.

    • asibiryakov
      /#10143238

      Скорее наоборот, это понимание у них не появится пока они не возьмут и не попробуют. А вот с этим у нас не все хорошо.

      • mizhgun
        /#10143284

        Так речь как раз о том, что для того, чтобы возникло само желание взять и пробовать Фронтеру, нужно иметь определенный порог знаний и опыта и соответствующий круг задач, это же не Скрапи с его массовой индийско-апворковской аудиторией.

  5. mizhgun
    /#10143280

    del

  6. gearbox
    /#10143814

    >Разнится скорость ответа веб-серверов, размер и количество страниц на сайте

    Учитываете ли при работе данные с robots.txt (второй версии желательно) Если от ваших запросов сервер начинает тупить — мониторите/замеряете/корректируете частоту запросов?

    Писал паука для одного из проектов, имхо — если не самая сложная то одна из по головоломности частей получилась как раз работа с robots.txt Но у меня там еще загон был — разные политики по юзер-агенту (статичный, round-robin, кастом) и юзерагент мог как учитываться так и нет при обработке robots (в зависимости от настроек)

    • asibiryakov
      /#10144644

      Статья про фреймворк, а не про конкретный робот. Есть два способа обрабатывать robots.txt в рамках Fronter'ы и Scrapy. Самое простое, это использовать RobotsTxtMiddleware в Scrapy. Перед обработкой URL запрашивается robots.txt с домена, кешируется, и все запросы к домену проверяются если допустимы в рамках robots.txt домена.
      Второй способ, это интегрировать обработку robots.txt в стратегию обхода, и попросту не планировать URL, которые запрещены в robots.txt.

      • gearbox
        /#10145450

        allow/disallow отрабатываются тривиально, речь шла о нормальной работе с Request-rate и Visit-time. Но ответ Ваш я понял, спасибо!

  7. roller
    /#10143946

    Люди, которые научатся доставать исходные данные из react-кода без выполнения js — озолотяться

    • ShamanR
      /#10144588

      Что вы под этим подразумеваете? Какой юзкейс?

      • roller
        /#10144960

        Юзкейс прост — экономить деньги/время. Вместо запуска фантомов для выполнения js — простой curl

  8. fediq
    /#10144388

    Я так понимаю, автор имеет отношение к Scrapinghub. Скажите, а ваша Portia — она насколько стабильно работает и насколько сложный парсинг поддерживает?


    Попробовал вчера hosted версию — при работе с переменным числом блоков эвристики постоянно промахиваются, и получается мусор. При попытке выгрузить "накликанный" парсер в формате Scrapy — выгружает что-то похожее на mock'овый код — модельки описаны, а алгоритм парсинга — нет.

    • kmike
      /#10144654

      Насколько знаю, внутри portia — библиотечка https://github.com/scrapy/scrapely. Ну т.е. там еще куча всего есть, но вроде дефолтное извлечение выполняется именно через scrapely. Это и есть алгоритм парсинга.

    • asibiryakov
      /#10145100

      Пришлите конкретные поля/запросы, мы посмотрим со своей стороны.