Всем привет, я занимаюсь разработкой 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
    29.03.2017 15:58

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


    1. square
      29.03.2017 16:19

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


      1. gearbox
        29.03.2017 22:53

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


        1. roller
          30.03.2017 01:21

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


          1. gearbox
            30.03.2017 10:57

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


            1. roller
              30.03.2017 13:14

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


              1. kirill3333
                30.03.2017 14:53

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


                1. gearbox
                  30.03.2017 17:27

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


              1. gearbox
                30.03.2017 17:25

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


    1. asibiryakov
      29.03.2017 16:31

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


  1. square
    29.03.2017 16:10

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


    1. asibiryakov
      29.03.2017 16:24

      В HBase он уже есть встроенный.


  1. slavenski
    29.03.2017 16:28
    -1

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


    1. asibiryakov
      29.03.2017 16:29

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


      1. mizhgun
        29.03.2017 17:20

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


        1. asibiryakov
          29.03.2017 17:55

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


          1. mizhgun
            29.03.2017 18:14

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


            1. asibiryakov
              30.03.2017 12:21

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


    1. Carburn
      30.03.2017 00:42

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


  1. mizhgun
    29.03.2017 17:52

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


    1. asibiryakov
      29.03.2017 17:56

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


      1. mizhgun
        29.03.2017 18:06

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


  1. mizhgun
    29.03.2017 18:06

    del


  1. gearbox
    29.03.2017 23:00

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

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

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


    1. asibiryakov
      30.03.2017 12:12

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


      1. gearbox
        30.03.2017 17:21

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


  1. roller
    30.03.2017 01:15

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


    1. ShamanR
      30.03.2017 11:46

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


      1. roller
        30.03.2017 13:53

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


  1. fediq
    30.03.2017 10:36

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


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


    1. kmike
      30.03.2017 12:15

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


    1. asibiryakov
      30.03.2017 14:51

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