百度搜索結果HTML分析

来源:https://www.cnblogs.com/yang--/archive/2018/03/15/8576778.html
-Advertisement-
Play Games

目的: 為了從搜索結果中提取所有網頁,以備後續處理。 訪問百度鏈接分析 名稱 值 說明 wd 任意文字 關鍵字 rn 可以不指定,預設為10,最大為50,最小為1,可設置為任意值 一頁包含的結果條目數 pn 百度預設顯示760條,所以最後一頁為pn=750 第一條結果的索引位置 示例: https:... ...


目的:

為了從搜索結果中提取所有網頁,以備後續處理。

 

訪問百度鏈接分析

名稱 說明
wd 任意文字 關鍵字
rn 可以不指定,預設為10,最大為50,最小為1,可設置為任意值 一頁包含的結果條目數
pn 百度預設顯示760條,所以最後一頁為pn=750 第一條結果的索引位置

示例:

https://www.baidu.com/s?wd=老虎&pn=10&rn=3

關鍵字:老虎,第10條記錄,每頁顯示3條。所以打開的是以老虎為關鍵字,第四頁的記錄

 

HTML源文件分析

剛下載的html源文件格式非常混亂,可使用線上html格式化工具進行格式化,以便閱讀。

根據我的需求,在HTML文件中,<script>元素與<style>元素可以直接跳過。找到搜索結果所在的位置即可。

image

 

image

 

 

提取搜索結果(Qt實現)

在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.

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庫自帶的解析函數提取想要的元素。

 

#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;
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • java.lang.IllegalArgumentExceptionat org.springframework.asm.ClassReader.<init>(Unknown Source)at org.springframework.asm.ClassReader.<init>(Unknown S ...
  • 練習 ...
  • 1.使用字元串來存儲文本; 2.在程式中顯示字元串; 3.在字元串中包含特殊的字元; 4.拼接字元串; 5.在字元串中包含變數; 6.比較字元串; 7.判斷字元串的長度; 程式Credits:顯示一部電影的導演和演員名單 1 package com.jsample; 2 3 public class ...
  • 網上有太多的VHDL和verilog比較的文章,基本上說的都是VHDL和verilog之間可以實現同一級別的描述,包括模擬級、寄存器傳輸級、電路級,所以可以認為兩者是等同級別的語言。很多時候會了其中一個,當然前提是真的學會,知道rtl(寄存器傳輸級)的意義,知道rtl與電路如何對應,在此基礎上,則很 ...
  • For 迴圈語句 基礎知識 for迴圈可以遍歷任何序列的項目,如一個列表或者一個字元串。 語法: for 迴圈規則: do sth 判斷對象是否可迭代 zip() 函數 函數用於將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,然後返回由這些元組組成的列表。 如果各個迭代器的元素個數不一致 ...
  • 1.一些簡單的dos命令: – d: 回車 盤符切換 – dir(directory):列出當前目錄下的文件以及文件夾 – del:刪除文件 – md:創建文件夾 – rd:刪除文件夾 – cd (change directory)改變指定目錄(進入指定目錄) 進入 cd 目錄;cd 多級目錄 回退 ...
  • 呵呵。大家都知道五服以內不得通婚,即兩個人最近的共同祖先如果在五代以內(即本人、父母、祖父母、曾祖父母、高祖父母)則不可通婚。本題就請你幫助一對有情人判斷一下,他們究竟是否可以成婚? 輸入格式: 輸入第一行給出一個正整數N(2 ≤ N ≤),隨後N行,每行按以下格式給出一個人的信息: 其中ID是5位 ...
  • 內容:顯示工具欄,設置主題、快捷鍵、開頭文字、解釋器 一些可能用到的設置,想起來就發上來。有需要的可以查看 ###############顯示工具欄 ##############設置主題,我用的主題是這種比較暗的,不喜歡太亮的,比如那種基本都是白色的。 ####################### ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...