Как избежать утечки места при чтении HTML-документа с помощью HXT

Ссылка на усеченную версию образца документа

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

concatMap (unwords . take 62 . drop 11) . lines

к тексту и выведите его.

Когда я это делаю, это занимает более 400 МБ места в HTML-документе размером 4 МБ.

Код, который у меня есть, довольно прост, поэтому я не включаю его, опасаясь искажения ответов.
Вот одна итерация кода:

file = readDocument [(a_validate, v_0), (a_parse_html, v_1)] "Cache entry information.xhtml"
text = fmap last $ runX $
  file >>>
  deep (hasName "pre") />
  isText >>>
--  changeText (unwords . take 62 . drop 11 . lines) >>>
  getText

Я думаю, проблема в том, что я делаю это так: HXT пытается сохранить весь текст в памяти по мере его чтения.

Согласно this, похоже, что HXT необходимо на минимум читать весь документ, хотя и не хранить его в памяти.

Я собираюсь попробовать другие парсеры, HaXmL, в качестве следующего.
N.B. Я решил исходную проблему, обработав входной файл как простой текст, а желаемую часть - разделенную "<pre>00000000:" и "</pre></body>\n</html>"


person Alex R    schedule 04.09.2010    source источник


Ответы (2)


Является ли парсер HXT "онлайн" парсером?

Пример, который у вас есть, отлично подходит для String, при условии, что каждая строка не является патологически длинной:

unwords . take 62 . drop 11 . lines

Здесь вы будете использовать только 73 строки ввода, 11, которые вы отбрасываете, и 62, с которыми вы работаете. Однако этот пример в основном не имеет отношения к обработке XML. Если синтаксический анализатор HXT не является онлайн-анализатором, вам придется прочитать весь файл в памяти, прежде чем вы сможете работать с любыми встроенными строковыми данными.

Боюсь, я не знаю, является ли HXT онлайн-парсером, но, похоже, это суть вашей проблемы.

person Stephen Tetley    schedule 05.09.2010
comment
К сожалению, я не уверен, является ли HXT онлайн-парсером или нет; Сначала я попробовал TagSoup, и у него была аналогичная проблема. Я видел людей, утверждающих, что используют HXT для файлов размером в ГБ, поэтому я подозреваю, что это онлайн-парсер. - person Alex R; 06.09.2010
comment
Я подозреваю, что HXT - это не онлайн-анализатор (он же потоковый). Вообще говоря, разработать онлайн-анализатор требует больше усилий, чем обычный, поэтому, если не указано иное, я бы предположил, что данный парсер не будет потоковым. Быстрый поиск настроил эту тему: stackoverflow.com/questions/2292729/ Безусловно, hexpat будет хорошим кандидатом, поскольку он построен на синтаксическом анализаторе SAX, а HaXML поддерживает онлайн-анализ (потоковый) - vis импорт нужного модуля. - person Stephen Tetley; 06.09.2010

Попробуйте использовать ByteString модуля Data.Bytestring.Lazy. Обычная строка оптимизирована для рекурсии и плохо себя ведет в случае больших объемов данных. Также вы можете попытаться сделать свои функции более строгими (например, используя seq), чтобы избежать больших накладных расходов из-за неоцененных преобразователей. Но будьте осторожны, так как это может ухудшить ситуацию, если будет применено неправильно.

PS: Всегда полезно привести краткий пример.

person fuz    schedule 05.09.2010
comment
Вы имеете в виду ByteString? Я не слышал о BitString, пока вы не упомянули об этом, и, похоже, он специализируется на тех случаях, когда я забочусь об отдельных битах. - person Alex R; 06.09.2010
comment
Это было первое, что я попробовал, еще до того, как перешел на HXT. Это совсем не помогло; проблема была в самом разборе. - person Alex R; 06.09.2010
comment
Вы использовали Data.Bytestring или Data.Bytestring.Lazy? Только второй является ленивым, в то время как первый, как в вашем примере, сначала скопирует все это в вашу драгоценную оперативную память. - person fuz; 07.09.2010
comment
Я использовал Data.ByteString.Lazy. При профилировании кода стало ясно, что проблема String vs. ByteString не была главной. - person Alex R; 08.09.2010