LINUX.ORG.RU

[Qt] Распарсить html

 


0

2

В приложении имеется встроенный браузер на вебките, который загружает нужную страницу. Далее нужно взять исходный текст загруженной в текущий момент страницы, распарсить его на предмет пары ссылок и текстов и сунуть полученные данные в таблицу sqlite.

Чем это лучше сделать? Желательно средствами самого Qt. Или все-же писать свой велосипед?

Пример:

В исходном тексте страницы есть несколько таких моментов:

<div class="audioRow fl_l" id="audio84522151_33" onmouseover="addClass(this, 'over')" onmouseout="removeClass(this, 'over')">
<div class="repeat_wrap"><div onmouseover="showTooltip(this, window.lang_repeat_audio)" onmouseout="hideTooltip()" id="repeat84522151_33" class="fl_r repeat" onclick="AudioObject.toggleRepeat()"></div></div>
<div class="fl_l">
<a name="84522151_33"></a>
 <table cellpadding="0" cellspacing="0"><tbody>
 <tr><td class="play_btn">
 <img class="playimg" onclick="return operate('84522151_33','http://cs5024.vkontakte.ru/u46191745/audio/0df7aabdd412.mp3',239);" id="imgbutton84522151_33" nosorthandle="true" src="images/play.gif"/>
 </td>

 <td class="play_title"><div class="audioTitle">
  <b id="performer84522151_33"><a href='gsearch.php?section=audio&c[q]=Jean Michel Jarre'>Jean Michel Jarre</a></b><span> - </span><span id="title84522151_33">Magnetic Fields Part 2</span> </div>
  <div class="duration">3:59</div>
 </td>
 </tr>
 </tbody></table>

Расположены они по порядку сверху вниз. Из каждого нужно выдернуть два пункта, они подсвечены жирным.

<div class=«audioRow fl_l» id=«audio84522151_33» onmouseover=«addClass(this, 'over')» onmouseout=«removeClass(this, 'over')»> <div class=«repeat_wrap»><div onmouseover=«showTooltip(this, window.lang_repeat_audio)» onmouseout=«hideTooltip()» id=«repeat84522151_33» class=«fl_r repeat» onclick=«AudioObject.toggleRepeat()»></div></div> <div class=«fl_l»> <a name=«84522151_33»></a> <table cellpadding=«0» cellspacing=«0»><tbody> <tr><td class=«play_btn»> <img class=«playimg» onclick=«return operate('84522151_33','http://cs5024.vkontakte.ru/u46191745/audio/0df7aabdd412.mp3',239);» id=«imgbutton84522151_33» nosorthandle=«true» src=«images/play.gif»/> </td>

<td class=«play_title»><div class=«audioTitle»> <b id=«performer84522151_33»><a href='gsearch.php?section=audio&c[q]=Jean Michel Jarre'>Jean Michel Jarre</a></b><span> - </span><span id=«title84522151_33»>Magnetic Fields Part 2</span> </div> <div class=«duration»>3:59</div> </td> </tr> </tbody></table>

</td>

Да, контактик не нужен, но все же =)

★★★★★

QWebElement Class Reference The QWebElement class provides convenient access to DOM elements in a QWebFrame

Gorthauer ★★★★★
()
// Returns a new list of elements matching the given CSS selector selectorQuery. 
// If there are no matching elements, an empty list is returned.
// Standard CSS2 selector syntax is used for the query.

QWebElement QWebFrame::findFirstElement ( const QString & selectorQuery ) const

Ищи img.playimg и div.audioTitle.

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

Залажал с копипастой доки, но и так понятно, что не список, а первый элемент возращает.

rival ★★
()

дык!

Как уже умные люди сказали - WebKit уже сам в себе всё содержит. Доступ к каждому элементу через поиск. А вообще-то в примерах всё есть. И вывод DOM-дерева и поиск..хм

QRegExp - если не используешь WebKit, а грузишь с помощью QNetworkAccessManager + QNetworkRequest + QNetworkReply и т.п.

m4n71k0r
()

Регулярные выражения в руки, нечего там html парсить.

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

>QRegExp, возможно?

Есть одна проблема: он очень тормозной по сравнению с не-Qt реализациями. Т.е. его как минимум не стоит натравливать на весь файл - стоит как-то выделить его части (строки, которые содержат .mp3, к примеру) и только на них искать.

Ну и при этом, как уже сказали, вместо QWebKit юзай QNetworkAccessManager + QNetworkRequest + QNetworkReply.

Pavval ★★★★★
()

Ну вот, наконец-то руки дошли. Вчера вечером получил исзодный текст страницы, седня буду про курегексп маны читать, чтоб распарсить.

Zhbert ★★★★★
() автор топика
Ответ на: комментарий от rival

Можешь чуть попродробнее рассказать? Об гугль уже все глаза поломал, но ничего не вышло...

Zhbert ★★★★★
() автор топика
Ответ на: комментарий от Pavval

>вместо QWebKit юзай QNetworkAccessManager + QNetworkRequest + QNetworkReply.

Сделал уже, сохраняю текст страницы во временный файл. Далее по идее надо дергать оттуда построчно код и натравливать на него QRegExp, так? Теперь возникла проблема в том, как это правильно сделать, гугль что-то не особо помог.

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

Где-то так (писал не проверяя):

QByteArray arr = networkReply->readAll();
QTextStream stream(arr);
while (!stream.atEnd)
{
  QString str(stream.realLine());
  QRegExp exp("your_pattern");
  int index = -1;
  while ((index = str.indexOf(exp, index + 1) != -1)
  {
    int end = str.indexOf(".mp3", index);
    QString url = str.mid(index, end - index + 4);
    ...
  }
}
Pavval ★★★★★
()
Ответ на: комментарий от Zhbert
// main.cpp:

#include <QDebug>
#include <QApplication>
#include <QWebView>
#include <QWebFrame>
#include <QWebElement>
#include <QRegExp>
#include <QMainWindow>

class MainWindow : public QMainWindow {
public:
    MainWindow(QWidget *parent = 0)
    : QMainWindow(parent)
    {
        QWebView *view = new QWebView(this);
        setCentralWidget(view);

        view->setHtml(
          "<div class=\"audioRow fl_l\" id=\"audio84522151_33\" onmouseover=\"addClass(this, 'over')\" onmouseout=\"removeClass(this, 'over')\">"
          "<div class=\"repeat_wrap\"><div onmouseover=\"showTooltip(this, window.lang_repeat_audio)\" "
          "onmouseout=\"hideTooltip()\" id=\"repeat84522151_33\" class=\"fl_r repeat\" onclick=\"AudioObject.toggleRepeat()\"></div></div>"
          "<div class=\"fl_l\">"
          "<a name=\"84522151_33\"></a>"
          "<table cellpadding=\"0\" cellspacing=\"0\"><tbody>"
          "<tr><td class=\"play_btn\">"
          "<img class=\"playimg\" onclick=\"return operate('84522151_33','http://cs5024.vkontakte.ru/u46191745/audio/0df7aabdd412.mp3',239);\" "
          "id=\"imgbutton84522151_33\" nosorthandle=\"true\" src=\"images/play.gif\"/>"
          "</td>"

          "<td class=\"play_title\"><div class=\"audioTitle\">"
          "<b id=\"performer84522151_33\"><a href='gsearch.php?section=audio&c[q]=Jean Michel Jarre'>Jean Michel Jarre</a></b><span> - </span>"
          "<span id=\"title84522151_33\">Magnetic Fields Part 2</span> </div>"
          "<div class=\"duration\">3:59</div>"
          "</td>"
          "</tr>"
          "</tbody></table>"
        );


        QWebFrame *frame = view->page()->mainFrame();
        QString attr = frame->findFirstElement("img.playimg").attribute("onclick", "<onclick>");

        qDebug() << attr; // "return operate('84522151_33','http://cs5024.vkontakte.ru/u46191745/audio/0df7aabdd412.mp3',239);"
        qDebug() << frame->findFirstElement("div.audioTitle").toPlainText(); // "Jean Michel Jarre - Magnetic Fields Part 2"

        QRegExp rx("(http.*\\.mp3)");
        if (rx.indexIn(attr, 0) != -1) {
            qDebug() << rx.cap(1); // "http://cs5024.vkontakte.ru/u46191745/audio/0df7aabdd412.mp3"
        }
    }

    ~MainWindow() {}
};


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

CSS2 Selectors

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

Спасибище, буду вечером экспериментировать =)

Zhbert ★★★★★
() автор топика
Ответ на: комментарий от rival

Еще раз спасибо, сделал для первой ссылки. Но на странице же их куча. Я правильно понял, что для того, чтобы вытащить все ссылки, нужно юзать findAllElements?

Zhbert ★★★★★
() автор топика
Ответ на: комментарий от rival

>Быстрее попробовать же, нежели спросить и ждать ответа.

Так я и пробовал =) Просто для уточнения спросил.

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