1 место Универсальный экстрактор™ контента (основной статьи страницы)

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 916
Реакции
3 883
Баллы
113
51509
Пару месяцев назад я публиковал в своём блоге видео с конференции, где рассказывалось какие есть сложности в реализации универсального парсера контента (основной статьи страницы без мусора: без меню, футера и тд) из html-кода. В комментариях к той записи мы обсудили, что хотелось бы использовать готовую библиотеку, дабы не писать свои велосипеды из регулярок, и именно тогда мой взор пал на пакет для Golang, который базируется на Readability.js (самом актуальном решении этой задачи от разработчиков Mozilla). Go'шная реализация переписана практически строчка-в-строчку, а что самое важное - её можно скомпилировать в исполняемый файл, чтобы получить максимальную производительность от языка, который сделали инженеры Google. Я взял этот go'шный пакет, скрестил его с другим (для работы из CLI) и сделал шаблон поверх этого добра, чтоб выполнять предварительную валидацию и постобработку.

Для чего нужен такой парсер контента? Чтобы грабить корованы конечно же! наполнять этим контентом доры/копипастные сайты, использовать его для переводов или исследований (составление датасетов).

Инструкция по компиляции парсера:
  1. Скачайте архив из аттача, распакуйте его
  2. Установите git: https://git-scm.com/download/win (необходим для установки зависимостей)
  3. Установите go: https://golang.org/dl/ (я использовал версию 1.14, инсталлятор "go1.14.windows-amd64.msi")
  4. После установки откройте cmd.exe и перейдите в папку с распакованным шаблоном и файлами:
    51501
  5. Установите зависимости:
    Код:
    Развернуть Свернуть Копировать
    go get github.com/urfave/cli
    go get github.com/go-shiori/go-readability
    Снимок экрана 2020-03-06 в 16.39.12.png

  6. Скомпилируйте парсер:
    Код:
    Развернуть Свернуть Копировать
    go build readability_cli.go
    51504
  7. Протестируйте его работоспособность (данный текст означает что всё хорошо, просто мы не передали обязательный параметр --url):
    51505

После этих простых манипуляций вы можете парсить контент без мусора просто в гигантских масштабах с ⚡молниеносной скоростью. А чтобы понять как это всё работает - я добавил тестовый шаблон readability_example.xmlz, который уже и запускает вложенный шаблон-парсер со следующим функционалом:
  • Парсинг на запросах, без браузера.
  • Очень точное получение основного контента за счёт использования актуальной библиотеки (а не старых решений на php/python/.net 2000-2010 годов, которые мало того что грузят CPU, так ещё и парсят мусор).
  • Мультиязычная обработка (нет привязки к языкам, парсер должен переварить хоть тайский, хоть китайский).
  • Встроенное кеширование через md5-хэш URL (в случае если вы парсите контент в реалтайме под каждую страницу как я, то вам нет смысла гонять парсер по одним и тем же ссылкам несколько раз).
  • Использование рандомного прокси из проксичекера (можно отключить для ускорения).
  • Валидация HTTP-статус кода (проверка, что страница отдала 200 код).
  • Пропуск всех результатов, где контент закодирован Brotli (в данный момент ZP не поддерживает декодирование).
  • Проверка типа данных (поддерживается парсинг только html, чтоб не попадались pdf/docx или другие документы).
  • Очистка результата от любых ссылок (очень крутой алгоритм, который я уже давно использую, но если нужно - это можно отключить).
  • Исправление пробелов/табов/переводов строк (дублей и некорректных завершений).
  • Исправление пробелов перед важными пунктуационными символами.
  • Два метода для удаления дубликатов (среди строк и предложений).
  • Эвристический метод для определения бинарных данных (может иногда быть слишком агрессивным, но на больших объемах лучше так).
  • Эвристический метод для удаления результатов, состоящих практически из одних цифр.
  • Сохранение метаданных рядом в кэше (добавлено сохранение только URL в xml-подобной структуре, но с легкостью можно добавить свои данные: нишу, запрос и тд).

Те, кто протестируют шаблон - будут приятно удивлены скоростью парсинга и минимальной нагрузкой на CPU, которая достигается как раз за счёт использования golang 8-)

51506
 
Номер конкурса шаблонов
  1. Пятый конкурс шаблонов
Уровень сложности
Продвинутый
Категория
  1. Парсинг

Вложения

Последнее редактирование:
Техничка подъехала. Возможно это мне не пригодиться сейчас, но пригодиться в дальнейшем. Спс
 
Это матрица, детка. Какой же я тупой, чтобы понять все это, все эти термины, алгоритмы,да и вобще ход этих мыслей
Чем больше информации ты впитываешь и пропускаешь через себя (не обязательно даже полностью воспроизводя её и понимая) - тем умнее ты становишься ;)

Техничка подъехала. Возможно это мне не пригодиться сейчас, но пригодиться в дальнейшем. Спс
Да, забыл написать в посте - это будет полезно для тех кто в будущем захочет скрестить зенку и golang. Чуть сложнее уже будет через gRPC обмениваться данными, но может и что-то такое я когда-нибудь расковыряю для себя и выложу для всех ;-)
 
Вау!
Спасибо большое за труды и классный шаблон! )
 
  • Спасибо
Реакции: Lord_Alfred

  • Очистка результата от любых ссылок (очень крутой алгоритм, который я уже давно использую, но если нужно - это можно отключить).

Посмотреть вложение 51506
Привет, спасибо за материал, реально интересная тема. Можно отдельно поподробнее про алгоритм очистки, по какому принципу он работает? Есть шаблон, в который что то подобное очень бы пригодилось, нужна идея по какому принципу работать))

Может быть можно где то прочитать поподробнее об этом крутом алгоритме?
 
  • Спасибо
Реакции: Lord_Alfred
Может быть можно где то прочитать поподробнее об этом крутом алгоритме?
Там несколько киллер-регулярок, которые в том числе умеют корректно определять доменную зону (за счет использования их в виде списка внутри). Шаблон открытый если что - там это в последнем кубике "fix content" )
 
  • Спасибо
Реакции: Alexmd и goldenbux
Это удивительно, но вчера как раз с @specialist копали в том же направлении, но на чистом C#.
И ты забыл добавить пункт о наличии Git в системе.
А почему Универсальный экстрактор™ <=?
 
Последнее редактирование:
  • Спасибо
Реакции: Andrew Shell и Lord_Alfred
Немного потестил. Пара вопросов.
1. На некоторых сайтах в результатах - Пожалуйста, обновите свой браузер. Мы рекомендуем Google Chromeпоследней версии.
2. Как парсить оставляя нужные теги? Например списки, таблицы, картинки?
 
И ты забыл добавить пункт о наличии Git в системе.
Ого! Большое спасибо за это замечание, у меня он стоял по дефолту и я даже не подозревал, что он необходим! :-)

А почему Универсальный экстрактор
Что бы у кого-нибудь триггернуло и кто-нибудь спросил...))

1. На некоторых сайтах в результатах - Пожалуйста, обновите свой браузер. Мы рекомендуем Google Chromeпоследней версии.
Можно пример? Вряд ли я смогу что-то поправить, но любопытно посмотреть что там за верстка если такое выдаётся.

2. Как парсить оставляя нужные теги? Например списки, таблицы, картинки?
Определённые теги никак не оставить, максиму что - это можно поправить мой исходник "readability_cli.go" и за место сохранения тела статьи article.TextContent - можно подтянуть из оригинального пакета следующие данные:

Код:
Развернуть Свернуть Копировать
article.Title // тайтл
article.TextContent // текстовый контент без тегов
article.Content // контент с html-тегами
article.Byline // автор из метаданных
article.Excerpt // короткое содержание статьи (саммари)
article.SiteName // название сайта
article.Image // какое-то изображение из статьи из метаданных
article.Favicon // фавикон
 
Последнее редактирование:
  • Спасибо
Реакции: Alexmd
 
Примеров не хватает.
 
Чуть сложнее уже будет через gRPC обмениваться данными, но может и что-то такое я когда-нибудь расковыряю для себя и выложу для всех ;-)

А в чем преимущество такой связки зенки и голанга?
 
@Astraport, там нет контента в исходном коде ) А данный пакет не строит DOM-дерево (точнее не обрабатывает javascript), поэтому такой результат - вполне логичный. Я даже вот lynx поставил потестить ради интереса, чтоб узнать что он выдаст на ту страницу:
51530

правда, кириллический шрифт почему-то не подтянулся, ну да ладно.

Примеров не хватает.
Каких именно примеров? В архиве лежит шаблон readability_example.xmlz, который и подраузмевался как пример :-)

А в чем преимущество такой связки зенки и голанга?
Если через gRPC гонять запросы, то можно было бы исполняемый файл golang сделать в виде демона, который постоянно висел и ожидал бы данных - это ещё бы сократило время на обработку. Но и в текущей реализации я не успеваю заметить как запускается и умирает процесс в диспетчере задач, потому что они очень быстро обрабатывают данные.
 
  • Спасибо
Реакции: Andrew Shell и Alexmd
У Алфреда как всегда годнота, которую понимают и применяют еденицы. НО ты крут.
 
а где экстрактор то взяв либу и скомпилив тупо ее...эх...плюс либа на момент когда последний раз тестил была сыровата и не очень хорошо выделяла статью...
при твои знаниях мен - мог бы что нить поинтересней придумать... у нас же конкурс шаблонов где должна быть интересная реализация или сложная.
короче я просто плачу от конкурса...даже отцы не порадовали...
 
  • Спасибо
Реакции: Andrew Shell
Неплохо) Надо будет затестить. В мире SEO оч пригодится) Учитывая, что есть синонимайзер под статьи - для доров и сателлитов прям хорошая. Нраица)
 
  • Спасибо
Реакции: Lord_Alfred
а где экстрактор то взяв либу и скомпилив тупо ее.
А зачем писать ещё один велосипед, который будет с квадратными колёсами, если есть уже готовые с овальными? :bn:

плюс либа на момент когда последний раз тестил была сыровата и не очень хорошо выделяла статью...
Примеры? Я её месяц гонял перед конкурсом - результат меня полностью устраивал.

при твои знаниях мен - мог бы что нить поинтересней придумать... у нас же конкурс шаблонов где должна быть интересная реализация или сложная.
Быть первым, кто скрестит супер-мощный и быстрый golang и ZP - разве не интересно? :-) Думаю, те, кто шарят как ты - могут такие вещи взять на заметку и применить их в чём-то другом, более интересном.

К слову, ты посмотрел внутрь шаба? Там есть несколько любопытных мест (предварительная валидация и пост обработка).
 
Последнее редактирование:
  • Спасибо
Реакции: DRAMER77 и Alexmd
Попробовал демо. Быстро. Даже очень быстро парсит. Посмотрел основной шаблон. Влет мне не разобраться, но очень интересно. @Lord_Alfred в очередной раз впечатлил меня своей программистской и исследовательской дотошностью и полетом мысли. Буду голосовать за этот конкурсный проект.
 
  • Спасибо
Реакции: Lord_Alfred
Великолепный шаблон.
Текст на выходе чистый. Теперь нужно научиться добывать ссылки на статьи для парсинга :D

P.S Шаблон запускать можно в многопоток?
 
Последнее редактирование:
  • Спасибо
Реакции: Lord_Alfred
1. статью можно писать в системный аут а не файлы
2. я не увидел скрещивания го и шарпа. скрещивание было бы если написал мост с помощью которого из зенки можно было вызывать модули голанга и функции напрямую.
3. лучшим решением было бы создать экзешник с асинхронным хттп-сервером. на вход данные на выход результат. тот же микросервис.

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

держу пальцы за симпатии разрабов и оригинальность. успехов.
 
  • Спасибо
Реакции: Andrew Shell и Platon
супер инструмент! вот, прям, то что искал!)

можно поправить мой исходник "readability_cli.go"
что именно поправить и как это сделать?

за место сохранения тела статьи article.TextContent - можно подтянуть из оригинального пакета следующие данные
это надо исправить в исходнике или добавить в сниппетах(если в сниппетах, то article.TextContent я не нашел)

и еще подскажи, можно ли настроить шаблон, чтобы он не парсил подписи к картинкам и названия разделов статьи?
 
  • Спасибо
Реакции: Lord_Alfred
Полезная штука :ay:
 
  • Спасибо
Реакции: Lord_Alfred
Текст на выходе чистый. Теперь нужно научиться добывать ссылки на статьи для парсинга :D
Думаю, кто угодно сможет скрестить его с каким-нибудь из бесплатных шаблонов:
P.S Шаблон запускать можно в многопоток?
Конечно! :)

что именно поправить и как это сделать?
Для парсинга контента с тегами нужно найти в файле readability_cli.go строку article.TextContent и заменить её на article.Content.

и еще подскажи, можно ли настроить шаблон, чтобы он не парсил подписи к картинкам и названия разделов статьи?
Нельзя, только если хакать саму либу
 
  • Спасибо
Реакции: sw_sw, intagens и slcor
Для парсинга контента с тегами нужно найти в файле readability_cli.go строку article.TextContent и заменить её на article.Content
мне не нужны теги) мне нужно получать из статьи article.TextContent, article.Title и article.Image ... так получиться?

article.Image // какое-то изображение из статьи из метаданных
а что значит "какое-то"? рандомное? а если изображений несколько - можно получить все?
 
Просто шикарный шаблон, спасибо!
мне не нужны теги) мне нужно получать из статьи article.TextContent, article.Title и article.Image ... так получиться?
Там в самом конце файла, есть dstTxtFile.WriteString(article.TextContent)
Просто дописываешь дальше, что тебе нужно, например так:

Код:
Развернуть Свернуть Копировать
dstTxtFile.WriteString(article.TextContent)
dstTxtFile.WriteString("Title:\n")
dstTxtFile.WriteString(article.Title)
dstTxtFile.WriteString("Image:\n")
dstTxtFile.WriteString(article.Image)
 

Кто просматривает тему: (Всего: 0, Пользователи: 0, Гости: 0)