爲了從搜索結果中提取全部網頁,以備後續處理。html
名稱 | 值 | 說明 |
wd | 任意文字 | 關鍵字 |
rn | 能夠不指定,默認爲10,最大爲50,最小爲1,可設置爲任意值 | 一頁包含的結果條目數 |
pn | 百度默認顯示760條,因此最後一頁爲pn=750 | 第一條結果的索引位置 |
https://www.baidu.com/s?wd=老虎&pn=10&rn=3node
關鍵字:老虎,第10條記錄,每頁顯示3條。因此打開的是以老虎爲關鍵字,第四頁的記錄web
剛下載的html源文件格式很是混亂,可以使用在線html格式化工具進行格式化,以便閱讀。app
根據個人需求,在HTML文件中,<script>元素與<style>元素能夠直接跳過。找到搜索結果所在的位置便可。ide
在Qt中,使用QDomDocument 或 QXmlStreamReader 來解析 HTML 文件都失敗了。經分析,其緣由是:QDomDocument 或 QXmlStreamReader都是針對解析XML文件設計的。HTML與XML的區別函數
通過查找資料,TidyLib 庫正好能夠解決問題。包包工具
Tidy is a console application for Mac OS X, Linux, Windows, UNIX, and more. It corrects and cleans up HTML and XML documents by fixing markup errors and upgrading legacy code to modern standards. spa
libtidy
is a C static and dynamic library that developers can integrate into their applications in order to bring all of Tidy’s power to your favorite tools. libtidy
is used today in desktop applications, web servers, and more.設計
TidyLib將HTML會修復文件可能的格式錯誤,並輸出XHTML。XHTML格式符合XML規範,能夠使用QDomDocument 或 QXmlStreamReader 來解析。也能夠使用TidyLib庫自帶的解析函數提取想要的元素。code
#ifndef HTMLPARSE_H #define HTMLPARSE_H #include <QDomDocument> class HtmlParse { public: HtmlParse(); bool setDatas(const QByteArray& datas); QList<QDomElement> getResults(); private: private: QDomDocument doc; }; #endif // HTMLPARSE_H /*********************************************************************************/ #include "htmlparse.h" #include <QDataStream> #include <QTextStream> #include <QDebug> #include "tidy.h" #include "tidybuffio.h" #include "tidyenum.h" #include "tidyplatform.h" #include "errno.h" #include <QStandardPaths> #include <QDir> #include <QDomDocument> #include <QRegularExpression> #include <QRegularExpressionMatch> HtmlParse::HtmlParse() { } bool HtmlParse::setDatas(const QByteArray &datas) { bool result = false; TidyBuffer output = {0}; TidyBuffer errbuf = {0}; int rc = -1; Bool ok; TidyDoc tdoc = tidyCreate(); // Initialize "document" ok = tidyOptSetBool( tdoc, TidyXhtmlOut, yes ); // Convert to XHTML if ( ok ) rc = tidySetErrorBuffer( tdoc, &errbuf ); // Capture diagnostics if ( rc >= 0 ) rc = tidyParseString( tdoc, datas.data() ); // Parse the input if ( rc >= 0 ) rc = tidyCleanAndRepair( tdoc ); // Tidy it up! if ( rc >= 0 ) rc = tidyRunDiagnostics( tdoc ); // Kvetch if ( rc > 1 ) // If error, force output. rc = ( tidyOptSetBool(tdoc, TidyForceOutput, yes) ? rc : -1 ); if ( rc >= 0 ) rc = tidySaveBuffer(tdoc, &output); // Pretty Print if ( rc >= 0 ) { if (doc.setContent(QByteArray((char *)output.bp))) { result = true; } } tidyBufFree( &output ); tidyBufFree( &errbuf ); tidyRelease( tdoc ); return result; } QList<QDomElement>& findResults(const QDomNode& pnode, const QString& tagName, const QHash<QString, QString>& validators, QList<QDomElement>& results) { QDomNode n = pnode.firstChild(); while (!n.isNull()) { if (n.isElement()) { // 遞歸,當前節點的子節點 findResults(n, tagName, validators, results); QDomElement elm = n.toElement(); // 須要檢測tagName時,若是tagName不符合則跳過 if (!tagName.isEmpty() && elm.tagName() != tagName) { n = n.nextSibling(); continue; } // 取出當前節點的全部鍵值對 QHash<QString, QString> ha; auto attrs = elm.attributes(); for (int i = 0; i < attrs.count(); i++) { QDomAttr attr = attrs.item(i).toAttr(); ha.insert(attr.name(), attr.value()); } bool isValid = true; QHash<QString, QString>::const_iterator it = validators.begin(); while (it != validators.end()) { QHash<QString, QString>::const_iterator fi = ha.find(it.key()); if (fi == ha.end()) { isValid = false; break; } // 若是爲空,則跳過 if (it.value().isEmpty()) { it++; continue; } QRegularExpression exp(it.value()); QRegularExpressionMatch mc = exp.match(fi.value()); if (!mc.hasMatch()) { isValid = false; break; } it++; } if (isValid) results.append(elm); } // 下一個兄弟節點 n = n.nextSibling(); } return results; } QList<QDomElement > HtmlParse::getResults() { QList<QDomElement> elements; QList<QDomElement> hrefElements; QHash<QString, QString> validators; validators.insert("class", "result"); validators.insert("id", "\\d+"); validators.insert("srcid", "\\d+"); findResults(doc, "div", validators, elements); qDebug() << elements.count(); for (auto var : elements) { qDebug() << var.attribute("id"); validators.clear(); validators.insert("href", ""); findResults(var, "a", validators, hrefElements); for (auto href : hrefElements) { qDebug() << href.text() << href.attribute("href"); } } return hrefElements; }