Приветствуем тебя читатель. Не так давно на нашем сервисе GrabDuck появился новый парсер/экстрактор статей. Между собой мы называем его GrabDuck Article Extractor 2.0 или сокращенно GAE 2.0. Почему так громко? Дело в том, изменений и усовершенствований накопилось столько, что нам пришлось полностью выкинуть старый, с которым мы жили последние полтора года и создать новый парсер статей “с нуля”. И да, для нас это большое и важное изменение. Что нам не нравилось и что мы сделали в результате описано под катом.
![](https://habrastorage.org/files/230/62f/38b/23062f38bf3e4e6e8e405d7e14b6fddb.jpeg)
Итак, мы долго жили со старым парсером, взятым со стороны в виде форка от какого-то open source проекта. Да, он был хорошим и старался выполнять свою работу на все 100 (где-то в одной из первых статей мы давали ссылку на него — если интересно, посмотрите). И для тех, чьи требования не превышают среднестатистических, мы по прежнему его рекомендуем к использованию — он точно справиться.
![](https://habrastorage.org/files/ad2/1f6/1a3/ad21f61a3a8840dc948d431b8c65c62a.jpg)
Но со временем все чаще стали натыкаться на различные ограничения. Сайты у нас, как известно, сохраняют всякие, до сих пор попадается ужасное наследие 2000х, когда и стандартов-то особых не было. Вообщем, тут наша библиотека давала сбой и приходилось все больше лезть в чужой код и править «под себя». Со временем, пожалуй основной претензией стало то, что библиотека была как швейцарский нож, хороша, но все делала сама: загружала документ по url, отслеживала редиректы, умела расшифровывать различные сокращатели ссылок, пыталась определить кодировку, даже если она не была явно задана, парсила документ, определяла изображения и даже пыталась понять дату, когда статья опубликована. Вообщем не библиотека, а сказка… Правда до тех пор, пока не требовалось что-то исправить или немного поменять. И мы часто стояли перед выбором: или править код напрямую, или, после обработки документа, проводить еще одну, свою собственную, естественно дублируя местами какую-то логику от нашего оригинального парсера. И решение это было непростым — создатель этой самой open source библиотеки явно не был фанатом тестирования и поэтому все работало ровно до момента пока не трогали и не вносили существенных изменений в код.
А учитывая, что сам процесс парсинга и извлечения статей, для тех, кто никогда с этим не сталкивался, полагается целиком на статистику, а не на четкие критерии, достаточно было чуть-чуть изменить веса применяемой статистической модели, и мы сразу рисковали, что однажды, какие-то классы сайтов просто перестанут обрабатываться корректно. Ведь общего формата-то нет — вся статья, это просто большой кусок html, в котором где-то внутри есть несколько параграфов так необходимого нам текста. Так что со временем у нас появился наш параллельный мир, когда уже обработанная и, казалось бы, уже подготовленная статья еще раз прогонялась, но уже через наш собственный недо-парсер.
Как эта open source библиотека работала в многопотоковом режиме была отдельная и очень грустная песня. И первоначально на больших импортах, когда счет шел на десятки тысяч закладок стоящих одновременно в очереди на обработку, все в нашем королевстве просто замирало.
И это был для нас урок номер 1: когда строите свою систему, используйте независимые компоненты — кирпичики. И именно из них собирайте то, что нужно вам. Если что-то пойдет не так, или появиться новый интересный проект, который выполняет работу лучше, всегда можно отключить старое и попробовать новое, не ломая систему и не рискуя, что все рассыпиться на каком-то этапе. А тут, уж поверьте нашему опыту, если что-то в мире чисел может пойти не так, оно обязательно пойдет не так и почти сразу.
Так что в конце мы решили — все, хватит, пора брать контроль в свои руки и писать что-то наше, под наши требования и с удовлетворяющем нас качеством. Так и появился на нашей архитектурной диаграмме новый компонент — GAE 2.0.
Прежде всего хотелось построить его в виде сборища независимых компонентов. Для каких-то шагов нам была нужна параллельная обработка по принципу, чем больше, тем лучше, где-то можно было обойтись и одним потоком, а где-то мы хотели ускориться распараллелив работу, но были серьезные ограничения на количество одновременно обрабатываемых элементов.
В результате вырисовывался этакий конвейер или pipeline, где каждая закладка превращается в полноценную статью, с каждым шагом наполняясь значимыми для пользователя данными.
![](https://habrastorage.org/files/bf5/028/96b/bf502896b73241ec9876c6420aae50d1.jpg)
Итак, какие же шаги нам необходимо предпринять, чтобы из ссылки сделать полноценную статью, которую уже можно показать пользователю?
После раздумий, зоны ответственности получились такие: Собственно сам Url Fetcher. Отвечает за непосредственную загрузку статьи по предоставленному Url. Должен понимать всевозможные редиректы, уметь работать через SSL и с сокращателями ссылок. И еще его нужно параллелить, ведь само ожидание ответа от сервера занимает годы компьютерного времени и с этим нужно что-то делать. Но и стратегия чем больше, тем лучше, тут тоже не подходит: будем бомбардировать один и тот же сайт запросами и нас попросту банально забанят. Значит нужен какой-то оптимум, что называется и нашим и вашим.
Полученный результат необходимо проверить на ошибки, а еще он может быть дубликатом уже существующей на GrabDuck статьи, и тогда достаточно всего лишь привязать к этой существующей статье нового пользователя.
И только после этого наступает время для извлечения данных и подготовки финальной статьи, которую и будем показывать нашим пользователям. Что сюда входит? Получение мета-информации, а это заголовки, изображения, расчет тегов и языка документа. Конечно же нам необходим сам контент для полнотекстового поиска, также необходимо сгенерировать текстовый сниппет, кратко представляющий сам документ.
После этого документ готов к использованию и доступен для поиска на GrabDuck.
Итак новый парсер готов и ура все новые закладки уже пойдут через него и мы наконец-то получим, что хотели! Но большой вопрос, который может возникнуть у читателя: а что будет с существующими закладками? Ведь они были УЖЕ обработаны и УЖЕ сохранены в системе! Неужели они так и останутся нетронутыми? И наш ответ — нет! Прежде всего, у пользователя всегда есть возможность выбрать закладку и принудительно обновить ее. Для этого достаточно выбрать соответствующий пункт из контекстного меню. Выглядит это как то так.
![](https://habrastorage.org/files/6a0/919/931/6a0919931c3f4a94a13bd957cb652373.png)
Ну или просто подождать немного. Одна из замечательных особенностей GrabDuck состоит в том, что мы проводим периодическую проверку всех закладок: а все ли в порядке, живы ли до сих пор сайты, не появилось ли на странице новых комментариев и т.п. Так что рано или поздно, ваши закладки попадут на обновление и пройдут через GAE 2.0.
На сегодня это все, что мы хотели вам рассказать. Оставляйте свои комментарии и до встречи.
![](https://habrastorage.org/files/230/62f/38b/23062f38bf3e4e6e8e405d7e14b6fddb.jpeg)
Итак, мы долго жили со старым парсером, взятым со стороны в виде форка от какого-то open source проекта. Да, он был хорошим и старался выполнять свою работу на все 100 (где-то в одной из первых статей мы давали ссылку на него — если интересно, посмотрите). И для тех, чьи требования не превышают среднестатистических, мы по прежнему его рекомендуем к использованию — он точно справиться.
![](https://habrastorage.org/files/ad2/1f6/1a3/ad21f61a3a8840dc948d431b8c65c62a.jpg)
Но со временем все чаще стали натыкаться на различные ограничения. Сайты у нас, как известно, сохраняют всякие, до сих пор попадается ужасное наследие 2000х, когда и стандартов-то особых не было. Вообщем, тут наша библиотека давала сбой и приходилось все больше лезть в чужой код и править «под себя». Со временем, пожалуй основной претензией стало то, что библиотека была как швейцарский нож, хороша, но все делала сама: загружала документ по url, отслеживала редиректы, умела расшифровывать различные сокращатели ссылок, пыталась определить кодировку, даже если она не была явно задана, парсила документ, определяла изображения и даже пыталась понять дату, когда статья опубликована. Вообщем не библиотека, а сказка… Правда до тех пор, пока не требовалось что-то исправить или немного поменять. И мы часто стояли перед выбором: или править код напрямую, или, после обработки документа, проводить еще одну, свою собственную, естественно дублируя местами какую-то логику от нашего оригинального парсера. И решение это было непростым — создатель этой самой open source библиотеки явно не был фанатом тестирования и поэтому все работало ровно до момента пока не трогали и не вносили существенных изменений в код.
А учитывая, что сам процесс парсинга и извлечения статей, для тех, кто никогда с этим не сталкивался, полагается целиком на статистику, а не на четкие критерии, достаточно было чуть-чуть изменить веса применяемой статистической модели, и мы сразу рисковали, что однажды, какие-то классы сайтов просто перестанут обрабатываться корректно. Ведь общего формата-то нет — вся статья, это просто большой кусок html, в котором где-то внутри есть несколько параграфов так необходимого нам текста. Так что со временем у нас появился наш параллельный мир, когда уже обработанная и, казалось бы, уже подготовленная статья еще раз прогонялась, но уже через наш собственный недо-парсер.
Как эта open source библиотека работала в многопотоковом режиме была отдельная и очень грустная песня. И первоначально на больших импортах, когда счет шел на десятки тысяч закладок стоящих одновременно в очереди на обработку, все в нашем королевстве просто замирало.
И это был для нас урок номер 1: когда строите свою систему, используйте независимые компоненты — кирпичики. И именно из них собирайте то, что нужно вам. Если что-то пойдет не так, или появиться новый интересный проект, который выполняет работу лучше, всегда можно отключить старое и попробовать новое, не ломая систему и не рискуя, что все рассыпиться на каком-то этапе. А тут, уж поверьте нашему опыту, если что-то в мире чисел может пойти не так, оно обязательно пойдет не так и почти сразу.
Так что в конце мы решили — все, хватит, пора брать контроль в свои руки и писать что-то наше, под наши требования и с удовлетворяющем нас качеством. Так и появился на нашей архитектурной диаграмме новый компонент — GAE 2.0.
Прежде всего хотелось построить его в виде сборища независимых компонентов. Для каких-то шагов нам была нужна параллельная обработка по принципу, чем больше, тем лучше, где-то можно было обойтись и одним потоком, а где-то мы хотели ускориться распараллелив работу, но были серьезные ограничения на количество одновременно обрабатываемых элементов.
В результате вырисовывался этакий конвейер или pipeline, где каждая закладка превращается в полноценную статью, с каждым шагом наполняясь значимыми для пользователя данными.
![](https://habrastorage.org/files/bf5/028/96b/bf502896b73241ec9876c6420aae50d1.jpg)
Итак, какие же шаги нам необходимо предпринять, чтобы из ссылки сделать полноценную статью, которую уже можно показать пользователю?
После раздумий, зоны ответственности получились такие: Собственно сам Url Fetcher. Отвечает за непосредственную загрузку статьи по предоставленному Url. Должен понимать всевозможные редиректы, уметь работать через SSL и с сокращателями ссылок. И еще его нужно параллелить, ведь само ожидание ответа от сервера занимает годы компьютерного времени и с этим нужно что-то делать. Но и стратегия чем больше, тем лучше, тут тоже не подходит: будем бомбардировать один и тот же сайт запросами и нас попросту банально забанят. Значит нужен какой-то оптимум, что называется и нашим и вашим.
Полученный результат необходимо проверить на ошибки, а еще он может быть дубликатом уже существующей на GrabDuck статьи, и тогда достаточно всего лишь привязать к этой существующей статье нового пользователя.
И только после этого наступает время для извлечения данных и подготовки финальной статьи, которую и будем показывать нашим пользователям. Что сюда входит? Получение мета-информации, а это заголовки, изображения, расчет тегов и языка документа. Конечно же нам необходим сам контент для полнотекстового поиска, также необходимо сгенерировать текстовый сниппет, кратко представляющий сам документ.
После этого документ готов к использованию и доступен для поиска на GrabDuck.
Итак новый парсер готов и ура все новые закладки уже пойдут через него и мы наконец-то получим, что хотели! Но большой вопрос, который может возникнуть у читателя: а что будет с существующими закладками? Ведь они были УЖЕ обработаны и УЖЕ сохранены в системе! Неужели они так и останутся нетронутыми? И наш ответ — нет! Прежде всего, у пользователя всегда есть возможность выбрать закладку и принудительно обновить ее. Для этого достаточно выбрать соответствующий пункт из контекстного меню. Выглядит это как то так.
![](https://habrastorage.org/files/6a0/919/931/6a0919931c3f4a94a13bd957cb652373.png)
Ну или просто подождать немного. Одна из замечательных особенностей GrabDuck состоит в том, что мы проводим периодическую проверку всех закладок: а все ли в порядке, живы ли до сих пор сайты, не появилось ли на странице новых комментариев и т.п. Так что рано или поздно, ваши закладки попадут на обновление и пройдут через GAE 2.0.
На сегодня это все, что мы хотели вам рассказать. Оставляйте свои комментарии и до встречи.
Поделиться с друзьями