1. 程式人生 > >使用xpath實現document.querySelector樣式選擇器進行html解析(四):將選擇結果封裝進行輸出

使用xpath實現document.querySelector樣式選擇器進行html解析(四):將選擇結果封裝進行輸出

-----------------------------------------------------------------

恩,其實到目前為止,關於xpath解析html的樣式選擇器其實已經完工了,而且,應該說比預期的目的還多出了一丟丟的效果

例如:QuerySelector("*[style*='(?<!\w)font-weight\s*:\s*bold(?!\w)']"),可以選中所有style屬性中包含粗體定義的節點

例如:QuerySelector("*:contains(abc.*?xyz)"),可以選中所有正文中包含abc和xyz,且abc在xyz之前的節點

注意到沒有,我們可以直接使用正則,當然了,第三章我貼的偽類contains處理之前的那個正則不支援圓括號輸入,關於指定屬性的正則不支援方括號輸入,自己魔改一下就可以完整的支援正則了,或者比較麻煩,需要層深計算,但還是可以實現的,可以參考文盲老顧之前關於正則的博文,但是個人感覺沒什麼必要了

本章為選擇器的最後一章,關於結果輸出方式的,有自己程式碼風格的可以不看,畢竟文盲老顧也是半路出家的c#工作者,沒有考慮到的,沒有學習到的東西都還很多,有更好的結果輸出方案的也請告知文盲,讓文盲繼續進步哦

-----------------------------------------------------------------

為了方便得到結果之後直接可以用.連線屬性,用來直接輸出結果,所以QuerySelector方法我們修改一下
        public HtmlObjectResult QuerySelector(string selection)
        {
            string xpath = CssParser.ParseCSS(selection);
            try
            {
                return new HtmlObjectResult(_xml.SelectNodes(xpath, XMLExpand.XPathExpand));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

直接將返回的XmlNodeList封裝到一個類裡,作為結果實現

    public class HtmlObjectResult
    {
        private List<HtmlObjectNode> _result = new List<HtmlObjectNode>();
        private int _curr = 0;
        public int Count
        {
            get
            {
                return _result == null ? 0 : _result.Count;
            }
        }
        public HtmlObjectNode[] NodeCollection
        {
            get
            {
                return _result.ToArray();
            }
        }
        public HtmlObjectNode Node
        {
            get
            {
                return _result == null ? null : _result[_curr];
            }
        }
        public HtmlObjectResult(XmlNodeList xnl)
        {
            for (int i = 0; i < xnl.Count; i++)
            {
                _result.Add(new HtmlObjectNode(xnl[i]));
            }
        }
        public HtmlObjectResult Next
        {
            get
            {
                _curr += _curr < _result.Count - 1 ? 1 : 0;
                return this;
            }
        }
        public HtmlObjectResult Previous
        {
            get
            {
                _curr -= _curr > 0 ? 1 : 0;
                return this;
            }
        }
        public HtmlObjectResult First
        {
            get
            {
                _curr = 0;
                return this;
            }
        }
    }

對於結果來說,它其實是一個節點集合,所以,提供一個Count,來表示到底有多少節點被選中

一般情況下,我們都是直接使用的第一個節點作為我們的結果,所以定義一個First,如果需要其他結果,可以用Next、Previous來選擇不同的結果,恩,反正都是返回這個結果集本身,只是下標定位改變了而已

然後可以返回當前選中的結果作為輸出內容,也就是Node屬性,Node也是一個封裝後的xml節點,稍後再講

當然,如果不喜歡這些,可以直接輸出所有的結果,NodeCollection可以滿足你的需要,當然其中的元素也是被封裝好的結果節點

再然後是正式輸出我們期望的結果值了

    public class HtmlObjectNode
    {
        private XmlNode _node = null;
        public HtmlObjectNode(XmlNode node)
        {
            _node = node;
        }
        public HtmlObjectNode Next
        {
            get
            {
                return _node == null ? null : _node.NextSibling != null ? new HtmlObjectNode(_node.NextSibling) : this;
            }
        }
        public HtmlObjectNode Previous
        {
            get
            {
                return _node == null ? null : _node.PreviousSibling != null ? new HtmlObjectNode(_node.PreviousSibling) : this;
            }
        }
        public HtmlObjectNode Parent
        {
            get
            {
                return _node == null ? null : _node.ParentNode != null ? new HtmlObjectNode(_node.ParentNode) : this;
            }
        }
        public string InnerHtml
        {
            get
            {
                return _node == null ? null : Regex.Replace(_node.InnerXml, @"<!\[CDATA\[|\]\]>", "", RegexOptions.IgnoreCase).Trim();
            }
        }
        public string OuterHtml
        {
            get
            {
                return _node == null ? null : Regex.Replace(_node.OuterXml, @"<!\[CDATA\[|\]\]>", "", RegexOptions.IgnoreCase).Trim();
            }
        }
        public string InnerText
        {
            get
            {
                return _node == null ? null : _node.InnerText;
            }
        }
        public XmlNode Node
        {
            get
            {
                return _node;
            }
        }
    }

作為被選中的節點,有時候我們需要純文字內容,有時候需要html內容,html內容有時候需要包含節點本身,有時候不包含

所以,我們的結果輸出就直接定義成三個,分別是InnerText、InnerHtml、OuterHtml,這個也符合html本身的習慣

由於我在第一章的時候,將html轉成xml的時候還追加了不少的CDataSetion節點,這些節點在作為結果輸出的時候應該被刪除節點宣告,所以我在這裡用正則刪除了一些資訊

當然,有時候某些節點定位非常麻煩,可他相鄰的部分節點非常好定位,那麼我們通常會定位到我們希望選中的節點之前,例如有一個表格,很多行很多列,沒有樣式啦、ID啦,甚至資料的位置也可能改變,但表格的格式不變,比如每一個td宣告資料名稱後,下一個緊跟著的td必定是它對應的值的時候,我們就可以直接定位到這個資料名稱的位置,例如 QuerySelector("td:contains(姓名)"),然後使用Next向後移動一個節點,再輸出就是對應的值了:QuerySelector("td:contains(姓名)").First.Node.Next.InnerText

需要注意的是,Node之前的Next是在結果集中選擇下一個對應的結果,Node之後的Next是在Html中對應的元素的下一個元素

好了,HtmlParser部分基本上講完了,之後文盲老顧會嘗試做一些資料提取方面新的嘗試,在儘量減少指正的情況下,如何從頁面內獲取到我們想要的資料,例如自動解析表格之類的

相關推薦

使用xpath實現document.querySelector樣式選擇進行html解析選擇結果封裝進行輸出

-----------------------------------------------------------------恩,其實到目前為止,關於xpath解析html的樣式選擇器其實已經完工了,而且,應該說比預期的目的還多出了一丟丟的效果例如:QuerySelect

tensorflow利用預訓練模型進行目標檢測檢測結果存入mysql資料庫

mysql版本:5.7 ; 資料庫:rdshare;表captain_america3_sd用來記錄某幀是否被檢測。表captain_america3_d用來記錄檢測到的資料。 python模組,包部分內容參考http://www.runoob.com/python/python-modules.html&

服務編程心得—— 如何socket設置為非阻塞模式

led -h bsp wait per 設置 inux sign 也有 1. windows平臺上無論利用socket()函數還是WSASocket()函數創建的socket都是阻塞模式的: SOCKET WSAAPI socket( _In_ int af,

tensorflow利用預訓練模型進行目標檢測檢測中的精度問題以及evaluation

一、tensorflow提供的evaluation Inference and evaluation on the Open Images dataset:https://github.com/tensorflow/models/blob/master/research/object_detection/g

HTML學習筆記 CSS學習選擇 第五節 原創

ext spa family 如果 styles ctype css gre utf <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <

使用Centos下的iptables實現實驗室按教室、按時間進行上網控制

Linux防火墻 iptables 高校運維 上網控制 1.nat轉發策略nat文件; iptables -t nat -A POSTROUTING -s 10.0.0.0/8 -o eth0 -j MASQUERADE (1)可將源IP寫得更具體一些,如列出使用的C類網段(2)WAN I

HTML+CSS基礎CSS選擇

每一條css樣式宣告(定義)由兩部分組成,形式如下: 選擇器{ 樣式; } 在{}之前的部分就是“選擇器”,“選擇器”指明瞭{}中的“樣式”的作用物件,也就是“樣式”作用於網頁中的哪些元素。 標籤選擇器 標籤選擇器其實就是html程式碼中

jQuery選擇程式碼詳解——tokenize方法

原創文章,轉載請註明出處,多謝! /* * tokenize方法是選擇器解析的核心函式,它將選擇器轉換成兩級陣列groups * 舉例: * 若選擇器為“div.class,span”,則解析後的結果為: * group[0][0] = {type

計算機視覺使用K-NN分類對CIFAR-10進行分類

1 - 引言 之前我們學習了KNN分類器的原理,現在讓我們將KNN分類器應用在計算機視覺中,學習如何使用這個演算法來進行圖片分類。 2 - 準備工作 建立專案結構如圖所示 在datasets檔案中下載資料集Cifar-10 k_nearest_neighbo

Spring原始碼解析Spring AOP中對攔截呼叫的實現

前面我們分析了Spring AOP實現中得到Proxy物件的過程,下面我們看看在Spring AOP中攔截器鏈是怎樣被呼叫的,也就是Proxy模式是怎樣起作用的,或者說Spring是怎樣為我們提供AOP功能的; 在JdkDynamicAopProxy中生成Proxy物件的時

jQuery 之 選擇與事件型別

hover() hover()方法用於模擬游標懸停事件.當滑鼠移動到元素上時,會觸發指定的第一個函式(mouseenter);當滑鼠移出這個元素時,會觸發指定的第二個函式(mouseleave)。 例項 $("#p1").hover(function(){   alert("You entered p1!")

使用bottle進行web開發5Generating Content

方便 () strings 系統 end byte 導致 res 名稱 在純粹的 WSGI中,你的應用能返回的數據類型是十分有限的,你必須返回可叠代的字符串,你能返回字符串是因為字符串是可以叠代的,但是這導致服務器將你的內容按一字符一字符的傳送,這個時候,Unicode 字

使用bottle進行web開發4HTTPError

instead bject hat red uil tle ott class not from bottle import error @error(404) def error404(error): return ‘Nothing here, sorry‘

TWaver可視化編輯的前世今生電力 雲計算 數據中心

變電站 fontsize 復雜 部署 ood 配置信息 來看 tar 右鍵 插播一則廣告(長期有效) TWaver需要在武漢招JavaScript工程師若幹 要求:對前端技術(JavasScript、HTML、CSS),對可視化技術(Canvas、WebGL)有濃厚的興

我的C#跨平臺之旅使用AOP進行系統增強

odata ima ges rest eba 技術分享 啟動 get header 使用OData提速REST API開發 引入NuGet包:Microsoft.AspNet.WebApi.OData 在啟動類中添加如下配置(示例為全局配置,也可基於Contro

tensorflow利用預訓練模型進行目標檢測預訓練模型的使用

err sync numpy sna sta porting trac git int32 一、運行樣例 官網鏈接:https://github.com/tensorflow/models/blob/master/research/object_detection/obje

Java併發volatile的實現原理 Java併發Java記憶體模型乾貨總結

synchronized是一個重量級的鎖,volatile通常被比喻成輕量級的synchronized volatile是一個變數修飾符,只能用來修飾變數。 volatile寫:當寫一個volatile變數時,JMM會把該執行緒對應的本地記憶體中的共享變數重新整理到主記憶體。 volatile讀:當讀一

Java並發volatile的實現原理

ont style tile 讀寫 flush microsoft div 圖片 println synchronized是一個重量級的鎖,volatile通常被比喻成輕量級的synchronized volatile是一個變量修飾符,只能用來修飾變量。 volatile寫

資料結構實現迴圈佇列C++版

資料結構實現(四):迴圈佇列(C++版) 1. 概念及基本框架 2. 基本操作程式實現 2.1 入隊操作 2.2 出隊操作 2.3 查詢操作 2.4 其他操作 3. 演算法複雜度分析 3.1 入

API閘道Kong功能梳理和外掛使用-認證外掛使用

作者: 李佶澳   轉載請保留:原文地址   釋出時間:2018/10/18 11:14:00   說明 部署一個echo應用 Basic Auth Key Auth J