Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.68/100: Рейтинг темы: голосов - 100, средняя оценка - 4.68
 Аватар для Krasiosoft
52 / 52 / 23
Регистрация: 01.06.2015
Сообщений: 189

Правильный парсинг html в Qt

01.06.2015, 18:12. Показов 21800. Ответов 54
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.

Необходимо парсить html средствами Qt.

Я это делаю следующим образом:

C++ (Qt)
1
2
3
    QWebPage WebPage;
    WebPage.mainFrame()->setHtml(HtmlText);
    QWebElement WebElement =  WebPage.mainFrame()->documentElement();
Далее уже с помощью QWebElement можно парсить html.

Правильный ли это подход для решение такой задачи?

То при закрытии приложения выдает ошибки в окно дебага:

LEAK: 5 CachedResource
LEAK: 4258 WebCoreNode

Которые говорят об утечке памяти.

Заранее благодарен.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
01.06.2015, 18:12
Ответы с готовыми решениями:

Qt парсинг html. Вытащить html код тэга?
QWebElementCollection collection = frame->findAllElements("div"); foreach (QWebElement element, collection) { ...

Html парсинг на примере
Есть обычный html файл в котором несколько таблиц, мне надо каждую таблицу в свой html поместить. Сейчас я просто запихиваю всю страницу в...

Создание\парсинг html файла
Доброго времени суток всем. Есть задача, организовать отчет в виде html. В отчете есть таблица такого вида: Сам html-код страницы под...

54
 Аватар для Krasiosoft
52 / 52 / 23
Регистрация: 01.06.2015
Сообщений: 189
24.06.2015, 17:52  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Avazart Посмотреть сообщение
Т.е можно так делать:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
    QTextCodec *codec = QTextCodec::codecForName("Windows-1251");
    //QTextCodec *localCodec = QTextCodec::codecForLocale(); // save local codec
    //QTextCodec::setCodecForLocale(codec);
 
    QXmlInputSource src;
    //src.setData(content);
    src.setData(codec->toUnicode(content)); // QByteArray content
 
    QDomDocument doc;
    LibXml2Reader reader;
 
    doc.setContent(&src, &reader);
Так скорей всего и нужно делать, но так можно делать зная кодировку html страницы, а иначе как быть?
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
24.06.2015, 17:54
Цитата Сообщение от Krasiosoft Посмотреть сообщение
Так скорей всего и нужно делать, но так можно делать зная кодировку html страницы, а иначе как быть?
А иначе никак, нужнать что там за страница.
Но у меня указанный мною способ не работает(по крайней мере под Debian), сразу пишет в дебаг что:
Code
1
2
encoding error : input conversion failed due to input error, bytes 0x98 0xD1 0x81 0xD0
encoding error : input conversion failed due to input error, bytes 0x98 0xD1 0x81 0xD0
0
 Аватар для Krasiosoft
52 / 52 / 23
Регистрация: 01.06.2015
Сообщений: 189
24.06.2015, 18:00  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
А иначе никак, нужнать что там за страница.
Но у меня указанный мною способ не работает(по крайней мере под Debian), сразу пишет в дебаг что:
Скорей всего Вы забыли проделать обратные действия передавая данные в сам парсер (функция LibXml2ReaderPrivate:: parse):
C++ (Qt)
1
2
3
    QString decodedHtmlText;
    QTextCodec *codec = QTextCodec::codecForName("windows-1251");
    QByteArray htmlText = codec->fromUnicode(decodedHtmlText);
1
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
24.06.2015, 18:01
Сейчас проверю.
0
267 / 189 / 33
Регистрация: 15.01.2011
Сообщений: 681
24.06.2015, 18:05
Krasiosoft,
Цитата Сообщение от Krasiosoft Посмотреть сообщение
Нельзя использовать fromLocal8Bit, откуда мы знаем какая у нас будет кодировка на входе?
если парсится нормально оформленная html страничка то узнать ее кодировку можно , примеру эта страничка :
HTML5
1
2
3
4
5
6
7
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="ru">
<head>
<base href="https://www.cyberforum.ru/" /><!--[if IE]></base><![endif]-->
    <link rel="canonical" href="https://www.cyberforum.ru/qt/thread1465127-page2.html" />
<base href="https://www.cyberforum.ru/" />
<meta http-equiv="Content-Type" content="text/html;charset=windows-1251" />
charset=windows-1251 то что нужно, если этого нет то на страничке может быть вообще все что угодно
1
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
24.06.2015, 18:08
Цитата Сообщение от Krasiosoft Посмотреть сообщение
Скорей всего Вы забыли проделать обратные действия передавая данные в сам парсер (функция LibXml2ReaderPrivate:: parse):
Да действительно так работает, только я не совсем понимаю почему так.

Добавлено через 54 секунды
Цитата Сообщение от ssXXss Посмотреть сообщение
charset=windows-1251 то что нужно, если этого нет то на страничке может быть вообще все что угодно
Этого может и не быть указано.

Вероятно стоит как-то применять такой метод QTextCodec

QTextCodec * codecForHtml(const QByteArray & ba, QTextCodec * defaultCodec)
0
267 / 189 / 33
Регистрация: 15.01.2011
Сообщений: 681
24.06.2015, 18:16
неплохой парсер от google
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
24.06.2015, 18:17
ssXXss, И че? сам то им пользовался? Он сишный. Тогда чем хуже "чистый" libxml2 ?
0
267 / 189 / 33
Регистрация: 15.01.2011
Сообщений: 681
24.06.2015, 18:19
да его использую, пока нравится ), "Тогда чем хуже "чистый" libxml2 ?" - не знаю, это дело вкуса
0
 Аватар для Krasiosoft
52 / 52 / 23
Регистрация: 01.06.2015
Сообщений: 189
24.06.2015, 18:55  [ТС]
Цитата Сообщение от ssXXss Посмотреть сообщение
если парсится нормально оформленная html страничка то узнать ее кодировку можно
Верно, но это же должен делать за нас парсер.

Цитата Сообщение от Avazart Посмотреть сообщение
Да действительно так работает, только я не совсем понимаю почему так.
Парсер libxml2 сам определяет кодировку и уже ей декодирует, поэтому ему нужно давать исходные данные html страницы.

Цитата Сообщение от ssXXss Посмотреть сообщение
да его использую, пока нравится ), "Тогда чем хуже "чистый" libxml2 ?" - не знаю, это дело вкуса
Для любого парсера можно сделать свою обвертку для удобной работы, в данном случае я хочу преобразовать результат парсинга в QDomDocument, чтоб не нужно было делать обвертку.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
24.06.2015, 19:13
Цитата Сообщение от Krasiosoft Посмотреть сообщение
Парсер libxml2 сам определяет кодировку и уже ей декодирует, поэтому ему нужно давать исходные данные html страницы.
C++
1
2
3
4
5
6
this->context =
    htmlCreatePushParserCtxt(&handler, 
        this,
        data, xmlStrlen(reinterpret_cast<const xmlChar*>(data)), 
        "",
        XML_CHAR_ENCODING_NONE);
хм что тогда означает XML_CHAR_ENCODING_NONE

http://www.xmlsoft.org/html/li... arEncoding

Добавлено через 15 минут
Т.е к примеру для
C++
1
htmlDocPtr htmlParseFile(const char * filename,  const char * encoding)
http://www.xmlsoft.org/html/li... lParseFile

Есть возможность явно задать кодировку.
0
 Аватар для Krasiosoft
52 / 52 / 23
Регистрация: 01.06.2015
Сообщений: 189
25.06.2015, 22:04  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
XML_CHAR_ENCODING_NONE
Тоже не могу понять что этот параметр означает, т.к. парсер все равно определяет кодировку сам по тегу meta.

Еще для правильной работы с парсером нужно понять в какой кодировке поступают данные в функцию:
C++
1
void LibXml2ReaderPrivate::characters(void* c, const xmlChar* ch, int len)
Как я уже проверил, они туда поступают не в текущей кодировке html страницы, а могут и в другой.

Сейчас по исходникам libxml2 пытаюсь разобраться как он определяет кодировку.

Добавлено через 5 часов 1 минуту
Функция htmlCurrentChar берет один символ следующим образом:

1) Проверяет если мы установили в xmlParserCtxt *context значение XML_CHAR_ENCODING_UTF8, тогда пробует брать символ как UTF-8, если удалось, возвращает этот символ.
2) Пробует брать символ как байт и проверяет его, чтоб он был меньше 128, если это так, возвращает это значение как символ.
3) Пробует определить кодировку автоматически с помощью функции htmlFindEncoding и на основе найденной кодировки уже возвращает символ.

Функция htmlFindEncoding ищет HTTP-EQUIV, за ним CONTENT и за ним CHARSET=, далее переписывает название кодировки пока:
((*cur >= 'A') && (*cur <= 'Z')) || ((*cur >= 'a') && (*cur <= 'z')) || ((*cur >= '0') && (*cur <= '9')) || (*cur == '-') || (*cur == '_') || (*cur == ':') || (*cur == '/'))

Но что самое главное, ищет он проходясь по байтам пока не встретит 0. Выходит не существует кодировки в которой могут быть нулевые байты? Или тег meta с кодировкой должен быть выше нежели текстовая информация? Я видел уже несколько сайтов где тег title идет выше чем указание кодировки.

Вот только в каком виде мы получаем символы в LibXml2ReaderPrivate::characters(...), я так и не понял пока.
1
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
25.06.2015, 22:07
Нулевой байт обычно - конец файла или чего либо, по этому да он не может быть внутри страницы.
0
 Аватар для Krasiosoft
52 / 52 / 23
Регистрация: 01.06.2015
Сообщений: 189
26.06.2015, 18:41  [ТС]
Вроде разобрался, задать кодировку парсеру можно следующим образом:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    xmlParserCtxt* context;
 
    // ...
    // Создаем context и т.п. (НО НЕ ЗАПУСКАЕМ ПАРСЕР)
    // ...
 
    QByteArray codecName("windows-1251");
 
    //  Создаем xmlChar строку на основе codecName
    xmlChar *codec;
    codec = xmlStrndup((xmlChar*)codecName.constData(),codecName.size());
 
    //  Устанавливаем название кодировки для входящих данных в контекст
    if (context->input->encoding != 0){
        xmlFree((xmlChar *) context->input->encoding);
    }
    context->input->encoding = codec;
 
    //  Проверяем знает ли libxml2 данную кодировку
    xmlCharEncodingHandlerPtr EncodingHandler;
    EncodingHandler= xmlFindCharEncodingHandler((const char *) codec);
    if (EncodingHandler != 0) {
        // Переключаемся на эту кодировку
        xmlSwitchToEncoding(context, EncodingHandler);
    }else{
        // Ошибка
        return false;
    }
 
    context->charset = XML_CHAR_ENCODING_UTF8;
При таком переключении кодировки все данные полученные от парсера приходят в UTF-8 и парсер не обращает внимание на кодировку в тегах meta.

Но вот саму обвертку LibXml2Reader нужно будет переписать, как минимум чтоб не нужно было перегонять данные html страницы с QByteArray в QString и потом обратно.
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
26.06.2015, 21:27
Цитата Сообщение от Krasiosoft Посмотреть сообщение
Если я не прав, поправьте меня, но насколько мне известно, то в QString'е данные хранятся в utf-8 и все приведенные ниже операции делают одно и тоже:
Не в UTF-8, а Unicode
, при этом использует 16 бит на символ.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.06.2015, 21:27

Правильный парсинг Period
Доброго времени суток. Ребят подскажите как правильно парсить Period. Вылетает ошика: java.time.format.DateTimeParseException: Text cannot...

Правильный парсинг на php
Пример разбираем чисто теоретический, для понимания как правильно поступать в той или иной ситуации. Какой вариант вы посоветуете? Или...

Правильный парсинг файла
Здравствуйте! Искал по форуму решение проблемы, так и не нашел. В общем проблема такая: Циклом foreach парсится файл. ...

Правильный запрос и парсинг даннх
Здравствуйте. Столкнулся с проблемой на этапе запуска программы. В eclipce в логе выводит такой результат: 10-20 05:52:27.700:...

JSON.net, правильный парсинг структуры
Здравствуйте. API сервер выдает примерно такую структуру { &quot;mashine&quot; : { &quot;&lt;Тут ид машинки&gt;&quot; : { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
55
Ответ Создать тему
Новые блоги и статьи
Nekobox - outbounds[0].transport: unknown transport type: raw
damix 01.10.2026
Фикс ошибки Правым кликом по серверу -> отладочная информация -> edit Заменить "net": "raw", на "net": "tcp", Нажать кнопку reload.
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru