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

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 916
Благодарностей
3 867
Баллы
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
 
Категория
Парсинг
Номер конкурса шаблонов
Пятый конкурс шаблонов
Уровень сложности
Продвинутый

Вложения

Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...

Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.

Последнее редактирование:

Valandersi

Client
Регистрация
19.01.2015
Сообщения
1 923
Благодарностей
1 123
Баллы
113
Техничка подъехала. Возможно это мне не пригодиться сейчас, но пригодиться в дальнейшем. Спс
 

Supergrok

Client
Регистрация
05.03.2019
Сообщения
171
Благодарностей
156
Баллы
43
Это матрица, детка. Какой же я тупой, чтобы понять все это, все эти термины, алгоритмы,да и вобще ход этих мыслей
 

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 916
Благодарностей
3 867
Баллы
113
Это матрица, детка. Какой же я тупой, чтобы понять все это, все эти термины, алгоритмы,да и вобще ход этих мыслей
Чем больше информации ты впитываешь и пропускаешь через себя (не обязательно даже полностью воспроизводя её и понимая) - тем умнее ты становишься ;-)

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

goldenbux

Client
Регистрация
06.09.2018
Сообщения
84
Благодарностей
45
Баллы
18

Danny

Client
Регистрация
29.09.2014
Сообщения
711
Благодарностей
154
Баллы
43
Вау!
Спасибо большое за труды и классный шаблон! )
 
  • Спасибо
Реакции: Lord_Alfred

goldenbux

Client
Регистрация
06.09.2018
Сообщения
84
Благодарностей
45
Баллы
18

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

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

Может быть можно где то прочитать поподробнее об этом крутом алгоритме?
 
  • Спасибо
Реакции: Lord_Alfred

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 916
Благодарностей
3 867
Баллы
113
Может быть можно где то прочитать поподробнее об этом крутом алгоритме?
Там несколько киллер-регулярок, которые в том числе умеют корректно определять доменную зону (за счет использования их в виде списка внутри). Шаблон открытый если что - там это в последнем кубике "fix content" )
 
  • Спасибо
Реакции: Alexmd и goldenbux

Astraport

Client
Регистрация
01.05.2015
Сообщения
4 983
Благодарностей
4 433
Баллы
113
Это удивительно, но вчера как раз с @specialist копали в том же направлении, но на чистом C#.
И ты забыл добавить пункт о наличии Git в системе.
А почему Универсальный экстрактор™ <=?
 
Последнее редактирование:
  • Спасибо
Реакции: Andrew Shell и Lord_Alfred

Astraport

Client
Регистрация
01.05.2015
Сообщения
4 983
Благодарностей
4 433
Баллы
113
Немного потестил. Пара вопросов.
1. На некоторых сайтах в результатах - Пожалуйста, обновите свой браузер. Мы рекомендуем Google Chromeпоследней версии.
2. Как парсить оставляя нужные теги? Например списки, таблицы, картинки?
 

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 916
Благодарностей
3 867
Баллы
113
И ты забыл добавить пункт о наличии 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

Astraport

Client
Регистрация
01.05.2015
Сообщения
4 983
Благодарностей
4 433
Баллы
113
 

inilim

Client
Регистрация
16.09.2017
Сообщения
446
Благодарностей
170
Баллы
43
Примеров не хватает.
 

Asmus003

Client
Регистрация
25.03.2018
Сообщения
259
Благодарностей
66
Баллы
28
Чуть сложнее уже будет через gRPC обмениваться данными, но может и что-то такое я когда-нибудь расковыряю для себя и выложу для всех ;-)
А в чем преимущество такой связки зенки и голанга?
 

Lord_Alfred

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

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

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

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

MasterX

Client
Регистрация
11.12.2015
Сообщения
89
Благодарностей
19
Баллы
8
У Алфреда как всегда годнота, которую понимают и применяют еденицы. НО ты крут.
 

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 916
Благодарностей
3 867
Баллы
113
  • Спасибо
Реакции: Sergey и Alexmd

Max

Client
Регистрация
17.06.2012
Сообщения
168
Благодарностей
44
Баллы
28
а где экстрактор то взяв либу и скомпилив тупо ее...эх...плюс либа на момент когда последний раз тестил была сыровата и не очень хорошо выделяла статью...
при твои знаниях мен - мог бы что нить поинтересней придумать... у нас же конкурс шаблонов где должна быть интересная реализация или сложная.
короче я просто плачу от конкурса...даже отцы не порадовали...
 
  • Спасибо
Реакции: Andrew Shell

TwistDanceR

Client
Регистрация
30.05.2019
Сообщения
479
Благодарностей
200
Баллы
43
Неплохо) Надо будет затестить. В мире SEO оч пригодится) Учитывая, что есть синонимайзер под статьи - для доров и сателлитов прям хорошая. Нраица)
 
  • Спасибо
Реакции: Lord_Alfred

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 916
Благодарностей
3 867
Баллы
113
а где экстрактор то взяв либу и скомпилив тупо ее.
А зачем писать ещё один велосипед, который будет с квадратными колёсами, если есть уже готовые с овальными? :bn:

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

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

К слову, ты посмотрел внутрь шаба? Там есть несколько любопытных мест (предварительная валидация и пост обработка).
 
Последнее редактирование:
  • Спасибо
Реакции: DRAMER77 и Alexmd

Nike59

Client
Регистрация
05.08.2011
Сообщения
122
Благодарностей
122
Баллы
43
Попробовал демо. Быстро. Даже очень быстро парсит. Посмотрел основной шаблон. Влет мне не разобраться, но очень интересно. @Lord_Alfred в очередной раз впечатлил меня своей программистской и исследовательской дотошностью и полетом мысли. Буду голосовать за этот конкурсный проект.
 
  • Спасибо
Реакции: Lord_Alfred

udder

Client
Регистрация
28.03.2017
Сообщения
618
Благодарностей
128
Баллы
43
Великолепный шаблон.
Текст на выходе чистый. Теперь нужно научиться добывать ссылки на статьи для парсинга :D

P.S Шаблон запускать можно в многопоток?
 
Последнее редактирование:
  • Спасибо
Реакции: Lord_Alfred

Max

Client
Регистрация
17.06.2012
Сообщения
168
Благодарностей
44
Баллы
28
1. статью можно писать в системный аут а не файлы
2. я не увидел скрещивания го и шарпа. скрещивание было бы если написал мост с помощью которого из зенки можно было вызывать модули голанга и функции напрямую.
3. лучшим решением было бы создать экзешник с асинхронным хттп-сервером. на вход данные на выход результат. тот же микросервис.

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

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

intagens

Client
Регистрация
28.09.2015
Сообщения
209
Благодарностей
31
Баллы
28
супер инструмент! вот, прям, то что искал!)

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

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

и еще подскажи, можно ли настроить шаблон, чтобы он не парсил подписи к картинкам и названия разделов статьи?
 
  • Спасибо
Реакции: Lord_Alfred

radv

Client
Регистрация
11.05.2015
Сообщения
3 788
Благодарностей
1 952
Баллы
113
Полезная штука :ay:
 
  • Спасибо
Реакции: Lord_Alfred

Lord_Alfred

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

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

и еще подскажи, можно ли настроить шаблон, чтобы он не парсил подписи к картинкам и названия разделов статьи?
Нельзя, только если хакать саму либу
 
  • Спасибо
Реакции: sw_sw, intagens и slcor

intagens

Client
Регистрация
28.09.2015
Сообщения
209
Благодарностей
31
Баллы
28
Для парсинга контента с тегами нужно найти в файле readability_cli.go строку article.TextContent и заменить её на article.Content
мне не нужны теги) мне нужно получать из статьи article.TextContent, article.Title и article.Image ... так получиться?

article.Image // какое-то изображение из статьи из метаданных
а что значит "какое-то"? рандомное? а если изображений несколько - можно получить все?
 

slcor

Client
Регистрация
08.03.2010
Сообщения
25
Благодарностей
13
Баллы
3
Просто шикарный шаблон, спасибо!
мне не нужны теги) мне нужно получать из статьи 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)
 

intagens

Client
Регистрация
28.09.2015
Сообщения
209
Благодарностей
31
Баллы
28

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