LINUX.ORG.RU

Подскажите по парсингу HTML

 , , ,


0

1

С наступающим, ЛОР!

Встала тут передо мной задача — надо переводить дофига HTML-файлов в текстовый вид. Проблема в том, что нужная информация хранится во вложенных «дивах». То есть, мне по сути из этого:

<div id="Ненужный_ИД" class="MessageItem">
    <div class="ненужные_аттрибуты">
        <div class="ненужные_аттрибуты $ИСТОЧНИК ненужные_аттрибуты">
            <div class="MessageItemText"> $ТЕКСТ_СООБЩЕНИЯ </div>
        </div>
        <div class="ненужные_аттрибуты">
	    <span class="ненужные_аттрибуты">
		<span class="ненужные_аттрибуты">ненужный_текст</span>
            </span>
            <span class="ненужные_аттрибуты">
                <span class="TimeHandler">$ВРЕМЯ_СООБЩЕНИЯ</span>
            </span>
        </div>
    </div>
</div>
Нужно сделать вот это:
 $ВРЕМЯ_СООБЩЕНИЯ $ИСТОЧНИК $ТЕКСТ_СООБЩЕНИЯ 

Как я понял, sed тут не справится. Пока безуспешно пытаюсь вкурить перловский HTML::TokeParser, но может быть есть более простой инструмент? Если да, то ткните носом в мануал...

самый простой способ - запустить headless браузер (либо взять любой shadow dom), и сделать

var parser = document.createElement("div")
parser.innerHTML = "контент html"
var plainText = parser.textContent


как вариант можно просто вычленять текст между тегами, удалять лишние пробелы и добавлять отступ по глубине вложенности тега (так работает просмотрщик html, кажется, в total commander, так же и отображают сайты консольные браузеры, где-то была статья о простом таком парсере)

trashymichael ★★★
()

Я бы xmlstarlet взял, он практически на это и заточен (хотя я бы взял python, но судя по тегам вам не подойдет).

micronekodesu ★★★
()
Ответ на: комментарий от trashymichael

скорее всего, трюк с innerHTML = ""; ... = ...textContent сработает в любом парсере, но как в случайном DOM назовут эти методы - зависит от реализации

trashymichael ★★★
()

если отдельные файлы, присоединяюсь совету про xmlstarlet, как-то пользовался им.

xmlstarlet sel -t -v 'твой/xpath/тут' 1.xml
правда не знаю, съест ли он невалидный html.

ну и да - в перле должен уж быть какой-нибудь инструмент c xpath

neschastnyjj86
()

Я сейчас занимаюсь тем же самым.

Читаю посимвольно, ищу начало несовпадения потом ищу ближайший «<» и читаю данные. Всё это в цикле, коорый ещё в рекурсивном цикле.

sniper21 ★★★★★
()
Последнее исправление: sniper21 (всего исправлений: 1)

На python есть хороший парсер lxml.html

ism ★★★
()
Ответ на: комментарий от voidmaster

В перле наверняка полно подходящих инструментов, но я с ним пока на «Вы»

а, ну тогда попрубуй питон + lxml.etree (там есть метод .xpath('тратата'))

neschastnyjj86
()

Не понятен принцип отделения $ИСТОЧНИК от ненужных атрибутов. Поэтому для начала можно перейти к обычному тексту чем-то вроде следующего, а там уже awk или к чему ещё душа лежит. Чтобы понять что тут происходит, нужно читать про XSLT и XPath.

$ cat src.html 
<?xml version="1.0"?>
<div id="Ненужный_ИД" class="MessageItem">
    <div class="ненужные_аттрибуты">
        <div class="ненужные_аттрибуты $ИСТОЧНИК ненужные_аттрибуты">
            <div class="MessageItemText"> $ТЕКСТ_СООБЩЕНИЯ </div>
        </div>
        <div class="ненужные_аттрибуты">
            <span class="ненужные_аттрибуты">
            <span class="ненужные_аттрибуты">ненужный_текст</span>
            </span>
            <span class="ненужные_аттрибуты">
                <span class="TimeHandler">$ВРЕМЯ_СООБЩЕНИЯ</span>
            </span>
        </div>
    </div>
</div>
$ cat template.xsl 
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:template match="div[@class='MessageItem']/div">
<xsl:value-of select="div/span/span[@class='TimeHandler']"/>
<xsl:apply-templates/>
<xsl:text>
</xsl:text>
</xsl:template>

<xsl:template match="div[div/@class='MessageItemText']">
<xsl:text>|</xsl:text>
<xsl:value-of select="@class"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="div[@class='MessageItemText']"/>
</xsl:template>

<xsl:template match="text()"/>

</xsl:stylesheet>
$ xsltproc template.xsl src.html 
$ВРЕМЯ_СООБЩЕНИЯ|ненужные_аттрибуты $ИСТОЧНИК ненужные_аттрибуты| $ТЕКСТ_СООБЩЕНИЯ 

unterwulf
()

php / phpQuery

\phpQuery::newDocument(file_get_contents('/path/to/html/file.html'));
echo pq(".TimeHandler")->html().' '.pq(".MessageItemText")->html()

Ford_Focus ★★★★★
()

Mojo::DOM. Это составная часть большого проекта, но внешних зависимостей у него нет, только то что входит в core-packages perl'а.

Думаю тебе оттуда пригодится ещё как минимум Mojo::UserAgent.

anonymous
()

Если исходные файлы на XHTML (т.е. well-formed XML), то можно на xquery написать

annulen ★★★★★
()

Не слушай их. Бери html-xml-utils. Он может частично пережевывать кривой html, но лучше его править перед скармливанием, конечно.
Там sed может быть и не нужен, надо смотреть на твои не нужные атрибуты. Ид для дива поставил div_id.

$ cat test.html | hxnormalize -x | tee >(hxselect -c ".MessageItemText" >> test.txt) >(hxselect "#div_id div div" | head -n1 | sed "s/.*\\$/\\$/;s/\s.*//;s/\\$/ \\$/" | tr --delete '\n' >> test.txt) >(hxselect -c ".TimeHandler" >> test.txt) >(echo >> test.txt) > /dev/null
$ cat test.txt
$ВРЕМЯ_СООБЩЕНИЯ $ИСТОЧНИК $ТЕКСТ_СООБЩЕНИЯ

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 2)
Ответ на: комментарий от sniper21

Всё это в цикле, коорый ещё в рекурсивном цикле.

Извращенец.

crutch_master ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.