[recovery mode] Очень простой и быстрый HTML->TEXT

image

Все видели просмотрщик html-файлов в TotalCommander. Загорелся идеей написать простой и очень маленький текстовый браузер для своей операционки. Поначалу, смотрел в сторону asm-xml — отличный парсер, однако ну очень уж большой (мой предел — 64 килобайта, не технический, просто принцип такой). Ниже описан очень простой способ получения текста из html.

Сразу оговорюсь, что код мне нужен именно независимый, (для своей ОС), поэтому все готовые библиотеки отпадают сразу. Почему assembler? — только потому что всё в моей ОС пишется на нем. Но метод можно передвинуть на любой язык…

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

Собственно, процесс состоит из нескольких этапов.
Вначале нужно избавиться от содержимого тегов script — только тех, где код написан напрямую, а не там, где подключаются внешние скрипты. Почему? Просто дошел опытным путем, когда выявил, что некоторые, весьма большие, скрипты ломают логику моего парсера)

Далее идет основной цикл. Мы шаг за шагом (точнее байт за байтом) проходим все теги (ищем открытие и закрытие тега). Т.е. у нас в итоге получается не дерево тегов, а список, состоящий из строк преполненных dword заголовками.
Если текст не подпадает под тег — то и записываем его просто как текст.

Структура временная выглядит так (касным выделены заголовки — обозначение тегов):

image

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

inc esi
cmp byte[esi + 0], '<'

Если это открывающий тег, то 

Это, конечно же, лентяйство, говнокод и т.п., но это быстро, коротко и эффективно!

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

Ожидаю комментариев вида: «говнокод», «учи матчасть» и т.п. Поэтому скажу сразу: код (в конце статьи ссылка) — это просто прототип, написанный «на коленке», а насчет «алгоритма» — согласен, это трудно назвать алгоритмом, но он работает! Всего 4Кб программа!

По ссылке рабочий пример (проверял также на исходнике html главной страницы хабра — скрин внизу) — всё работает. Единственно — ограничение размера файла (просто пока не добавил выделение памяти, использую 3 по 64 Кб неинициализированных буфера). После работы программа выдаст два файла — в одном список временный, во втором — готовый текст. Учтите, что в тексте переносы — это 0×0A, поэтому смотрим TotalCommander’ом в режиме текста.

Тест на документе «W3C Reformulating HTML in XML»:
image

Тест на главной страницу Хабрахабра:
image

Исходник + win32binary

А теперь вопрос: у кого получится меньше, чем 4Кб?

Комментарии (3)

  • 29 июня 2016 в 23:42 (комментарий был изменён)

    0

    Загорелся идеей написать простой и очень маленький текстовый браузер для своей операционки.
    Почему assembler? — только потому что всё в моей ОС пишется на нем.

    Я смотрю, Вы уже листер с гуями на асме запилили! Зачотно, чо!)
    А если по чесноку — вывод в файл в длину засчитывается? Обработка параметров со строки? Можно ли не читать с файла, а читать только с stdin? А к кодировкам как мы относимся?(можно было бы впрячься, я в свое время баловался подобными ужиманиями)

    • 29 июня 2016 в 23:43

      0

      да всё можно, я просто пример самой идеи сделал быстро, если подумать хорошо — можно намного умнее сделать всё)
  • 30 июня 2016 в 02:45

    0

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

© Habrahabr.ru