「Qtの基礎 - HTML」の版間の差分
提供: MochiuWiki : SUSE, EC, PCB
📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
ページの作成:「== 概要 == <br><br> == XPath == 以下の例では、WebページのHTMLをダウンロードして、<head>タグ内の<title>タグの値を抽出している。<br> <br> 具体的には、まず、<code>QNetworkAccessManager</code>クラスを使用してHTTPリクエストを送信して、<code>QNetworkReply</code>クラスを使用してレスポンスを受信する。<br> 次に、libxml2ライブラリを使用して、受信したレスポンスから<h…」 |
|||
| 1行目: | 1行目: | ||
== 概要 == | == 概要 == | ||
Qtでは、HTMLを詳細にパースするライブラリが存在しないため、外部ライブラリを使用する必要がある。<br> | |||
<br> | |||
HTMLがパースできるライブラリを、以下に示す。<br> | |||
* libxml2 | |||
*: 概要 | |||
*: libxml2は、XML文書を解析し、XPathクエリを実行するための非常に人気があるC言語ライブラリである。 | |||
*: C++からも使用可能である。 | |||
*: <br> | |||
*: XPathサポート | |||
*: XPath 1.0をサポートしている。 | |||
*: <br> | |||
* TinyXML-2 | |||
*: 概要 | |||
*: 軽量で簡単に使用できるC++のXML解析ライブラリである。 | |||
*: XPathの直接的なサポートは無いが、XMLノードを簡単に走査して目的のデータを見つけるための機能がある。 | |||
*: <br> | |||
*: XPathサポート | |||
*: 直接的なXPathサポートは無いが、独自の検索関数を記述することで類似の機能を実現できる。 | |||
*: <br> | |||
* PugiXML | |||
*: 概要 | |||
*: 軽量かつ高速なXML解析ライブラリで、C++で開発されている。 | |||
*: <br> | |||
*: XPathサポート | |||
*: XPath 1.0をフルサポートしており、HTMLやXMLファイルからのデータ抽出に適している。 | |||
*: <br> | |||
* Xerces-C++ | |||
*: 概要 | |||
*: Apache Software Foundationにより開発された高性能なXML解析ライブラリである。 | |||
*: DOM、SAX、XPath 1.0をサポートしている。 | |||
*: <br> | |||
*: XPathサポート | |||
*: XPath 1.0をサポートしている。 | |||
<br><br> | <br><br> | ||
2024年3月22日 (金) 18:54時点における版
概要
Qtでは、HTMLを詳細にパースするライブラリが存在しないため、外部ライブラリを使用する必要がある。
HTMLがパースできるライブラリを、以下に示す。
- libxml2
- 概要
- libxml2は、XML文書を解析し、XPathクエリを実行するための非常に人気があるC言語ライブラリである。
- C++からも使用可能である。
- XPathサポート
- XPath 1.0をサポートしている。
- TinyXML-2
- 概要
- 軽量で簡単に使用できるC++のXML解析ライブラリである。
- XPathの直接的なサポートは無いが、XMLノードを簡単に走査して目的のデータを見つけるための機能がある。
- XPathサポート
- 直接的なXPathサポートは無いが、独自の検索関数を記述することで類似の機能を実現できる。
- PugiXML
- 概要
- 軽量かつ高速なXML解析ライブラリで、C++で開発されている。
- XPathサポート
- XPath 1.0をフルサポートしており、HTMLやXMLファイルからのデータ抽出に適している。
- Xerces-C++
- 概要
- Apache Software Foundationにより開発された高性能なXML解析ライブラリである。
- DOM、SAX、XPath 1.0をサポートしている。
- XPathサポート
- XPath 1.0をサポートしている。
XPath
以下の例では、WebページのHTMLをダウンロードして、<head>タグ内の<title>タグの値を抽出している。
具体的には、まず、QNetworkAccessManagerクラスを使用してHTTPリクエストを送信して、QNetworkReplyクラスを使用してレスポンスを受信する。
次に、libxml2ライブラリを使用して、受信したレスポンスから<head>タグ内の<title>タグの値を抽出する。
libxml2ライブラリは、C言語で記述されたライブラリであるため、メモリ管理には特に注意が必要である。
例えば、xmlFreeDoc関数、xmlXPathFreeContext関数、xmlFree関数等を適切に使用すること。
# QMakeを使用する場合
LIBS += -lxml2
INCLUDEPATH += /<libxml2のインストールディレクトリ>/include/libxml2
# CMakeを使用する場合
# pkg-configを使用してlibxml2ライブラリを検索
pkg_search_module(LIBXML2 REQUIRED libxml-2.0)
# ライブラリのインクルードディレクトリをターゲットに追加
include_directories(${LIBXML2_INCLUDE_DIRS})
# ライブラリのリンクディレクトリをターゲットに追加
link_directories(${LIBXML2_LIBRARY_DIRS})
target_include_directories(<プロジェクト名> PRIVATE
# ...略
${LIBXML2_INCLUDE_DIRS}
)
target_link_libraries(<プロジェクト名>
# ...略
${LIBXML2_LIBRARIES}
)
# libxml2のコンパイルオプション
add_definitions(
# ...略
${LIBXML2_CFLAGS_OTHER}
)
// main.h
#ifndef MAIN_H
#define MAIN_H
#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkReply>
class HtmlTitleFetcher : public QObject {
Q_OBJECT
private:
QNetworkAccessManager *m_pManager;
QNetworkReply *m_pReply;
QUrl url;
private:
void parseHtml(const QByteArray &htmlData);
public:
HtmlTitleFetcher(const QUrl &url, QObject *parent = nullptr);
private slots:
void onFinished();
};
#endif // MAIN_H
// main.cpp
#include <libxml/HTMLparser.h>
#include <libxml/xpath.h>
#include "main.h"
HtmlTitleFetcher::HtmlTitleFetcher(const QUrl &url, QObject *parent) : QObject(parent), url(url)
{
m_pManager = new QNetworkAccessManager(this);
QNetworkRequest request(url);
m_pReply = manager->get(request);
connect(m_pReply, SIGNAL(finished()), this, SLOT(onFinished()));
}
void HtmlTitleFetcher::onFinished()
{
if (m_pReply->error() == QNetworkReply::NoError) {
QByteArray htmlData = m_pReply->readAll();
parseHtml(htmlData);
}
else {
std::cerr << QString("エラー : %1").arg(m_pReply->errorString()).toStdString() << std::endl;
}
reply->deleteLater();
}
void HtmlTitleFetcher::parseHtml(const QByteArray &htmlData)
{
htmlDocPtr doc = htmlReadMemory(htmlData.data(), htmlData.size(), nullptr, "UTF-8", HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING);
if (doc == nullptr) {
std::cerr << QString("HTMLデータのパースに失敗").toStdString() << std::endl;
return;
}
xmlXPathContextPtr context = xmlXPathNewContext(doc);
if (context == nullptr) {
xmlFreeDoc(doc);
std::cerr << QString("XPathの生成に失敗").toStdString() << std::endl;
return;
}
xmlXPathObjectPtr result = xmlXPathEvalExpression((const xmlChar*)"//title", context);
if (result == nullptr) {
xmlXPathFreeContext(context);
xmlFreeDoc(doc);
std::cerr << QString("XPath式の評価に失敗").toStdString() << std::endl;
return;
}
xmlNodeSetPtr nodeset = result->nodesetval;
if (xmlXPathNodeSetIsEmpty(nodeset)) {
std::cerr << QString("<title>タグが存在しません").toStdString() << std::endl;
}
else {
xmlNodePtr cur = nodeset->nodeTab[0];
if (cur != nullptr && cur->children != nullptr) {
xmlChar *content = xmlNodeGetContent(cur);
std::cerr << QString("<title>タグの値 : %1").arg(QString((char *)content)).toStdString() << std::endl;
xmlFree(content);
}
}
xmlXPathFreeObject(result);
xmlXPathFreeContext(context);
xmlFreeDoc(doc);
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QUrl url("https://www.example.com");
HtmlTitleFetcher fetcher(url);
return app.exec();
}