Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 中文字幕日本一本二本三区,日本免费在线观看,日本国产最新一区二区三区

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Python解析庫lxml與xpath用法總結(jié)

          Python解析庫lxml與xpath用法總結(jié)

          文主要圍繞以xpath和lxml庫進(jìn)行展開:

          一、xpath 概念、xpath節(jié)點(diǎn)、xpath語法、xpath軸、xpath運(yùn)算符

          二、lxml的安裝、lxml的使用、lxml案例


          一、xpath

          1.xpath概念

          XPath 是一門在 XML 文檔中查找信息的語言。XPath 使用路徑表達(dá)式在 XML 文檔中進(jìn)行導(dǎo)航 。XPath 包含一個(gè)標(biāo)準(zhǔn)函數(shù)庫 。XPath 是 XSLT 中的主要元素 。XPath 是一個(gè) W3C 標(biāo)準(zhǔn) 。


          2.xpath節(jié)點(diǎn)

          xpath有七種類型的節(jié)點(diǎn):元素、屬性、文本、命名空間、處理指令、注釋以及文檔(根)節(jié)點(diǎn)。

          節(jié)點(diǎn)關(guān)系:父、子、兄弟、先輩、后輩。


          3.xpath語法

          xpath語法在W3c網(wǎng)站上有詳細(xì)的介紹,這里截取部分知識(shí),供大家學(xué)習(xí)。

          XPath 使用路徑表達(dá)式在 XML 文檔中選取節(jié)點(diǎn)。節(jié)點(diǎn)是通過沿著路徑或者 step 來選取的。下面列出了最有用的路徑表達(dá)式:

          表達(dá)式

          描述

          nodename

          選取此節(jié)點(diǎn)的所有子節(jié)點(diǎn)。

          /

          從根節(jié)點(diǎn)選取。

          //

          從匹配選擇的當(dāng)前節(jié)點(diǎn)選擇文檔中的節(jié)點(diǎn),而不考慮它們的位置。

          .

          選取當(dāng)前節(jié)點(diǎn)。

          ..

          選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)。

          @

          選取屬性。

          在下面的表格中,我們已列出了一些路徑表達(dá)式以及表達(dá)式的結(jié)果:

          路徑表達(dá)式

          結(jié)果

          bookstore

          選取 bookstore 元素的所有子節(jié)點(diǎn)。

          /bookstore

          選取根元素 bookstore。注釋:假如路徑起始于正斜杠( / ),則此路徑始終代表到某元素的絕對(duì)路徑!

          bookstore/book

          選取屬于 bookstore 的子元素的所有 book 元素。

          //book

          選取所有 book 子元素,而不管它們?cè)谖臋n中的位置。

          bookstore//book

          選擇屬于 bookstore 元素的后代的所有 book 元素,而不管它們位于 bookstore 之下的什么位置。

          //@lang

          選取名為 lang 的所有屬性。


          謂語(Predicates)

          謂語用來查找某個(gè)特定的節(jié)點(diǎn)或者包含某個(gè)指定的值的節(jié)點(diǎn)。

          謂語被嵌在方括號(hào)中。

          在下面的表格中,我們列出了帶有謂語的一些路徑表達(dá)式,以及表達(dá)式的結(jié)果:

          路徑表達(dá)式

          結(jié)果

          /bookstore/book[1]

          選取屬于 bookstore 子元素的第一個(gè) book 元素。

          /bookstore/book[last()]

          選取屬于 bookstore 子元素的最后一個(gè) book 元素。

          /bookstore/book[last()-1]

          選取屬于 bookstore 子元素的倒數(shù)第二個(gè) book 元素。

          /bookstore/book[position()<3]

          選取最前面的兩個(gè)屬于 bookstore 元素的子元素的 book 元素。

          //title[@lang]

          選取所有擁有名為 lang 的屬性的 title 元素。

          //title[@lang='eng']

          選取所有 title 元素,且這些元素?fù)碛兄禐?eng 的 lang 屬性。

          /bookstore/book[price>35.00]

          選取 bookstore 元素的所有 book 元素,且其中的 price 元素的值須大于 35.00。

          /bookstore/book[price>35.00]/title

          選取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值須大于 35.00。


          選取未知節(jié)點(diǎn)

          XPath 通配符可用來選取未知的 XML 元素。

          通配符

          描述

          *

          匹配任何元素節(jié)點(diǎn)。

          @*

          匹配任何屬性節(jié)點(diǎn)。

          node()

          匹配任何類型的節(jié)點(diǎn)。

          在下面的表格中,我們列出了一些路徑表達(dá)式,以及這些表達(dá)式的結(jié)果:

          路徑表達(dá)式

          結(jié)果

          /bookstore/*

          選取 bookstore 元素的所有子元素。

          //*

          選取文檔中的所有元素。

          //title[@*]

          選取所有帶有屬性的 title 元素。


          選取若干路徑

          通過在路徑表達(dá)式中使用"|"運(yùn)算符,您可以選取若干個(gè)路徑。

          在下面的表格中,我們列出了一些路徑表達(dá)式,以及這些表達(dá)式的結(jié)果:

          路徑表達(dá)式

          結(jié)果

          //book/title | //book/price

          選取 book 元素的所有 title 和 price 元素。

          //title | //price

          選取文檔中的所有 title 和 price 元素。

          /bookstore/book/title | //price

          選取屬于 bookstore 元素的 book 元素的所有 title 元素,以及文檔中所有的 price 元素。


          4.xpath 軸

          軸可定義相對(duì)于當(dāng)前節(jié)點(diǎn)的節(jié)點(diǎn)集。

          軸名稱

          結(jié)果

          ancestor

          選取當(dāng)前節(jié)點(diǎn)的所有先輩(父、祖父等)。

          ancestor-or-self

          選取當(dāng)前節(jié)點(diǎn)的所有先輩(父、祖父等)以及當(dāng)前節(jié)點(diǎn)本身。

          attribute

          選取當(dāng)前節(jié)點(diǎn)的所有屬性。

          child

          選取當(dāng)前節(jié)點(diǎn)的所有子元素。

          descendant

          選取當(dāng)前節(jié)點(diǎn)的所有后代元素(子、孫等)。

          descendant-or-self

          選取當(dāng)前節(jié)點(diǎn)的所有后代元素(子、孫等)以及當(dāng)前節(jié)點(diǎn)本身。

          following

          選取文檔中當(dāng)前節(jié)點(diǎn)的結(jié)束標(biāo)簽之后的所有節(jié)點(diǎn)。

          namespace

          選取當(dāng)前節(jié)點(diǎn)的所有命名空間節(jié)點(diǎn)。

          parent

          選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)。

          preceding

          選取文檔中當(dāng)前節(jié)點(diǎn)的開始標(biāo)簽之前的所有節(jié)點(diǎn)。

          preceding-sibling

          選取當(dāng)前節(jié)點(diǎn)之前的所有同級(jí)節(jié)點(diǎn)。

          self

          選取當(dāng)前節(jié)點(diǎn)。


          5.xpath運(yùn)算符

          下面列出了可用在 XPath 表達(dá)式中的運(yùn)算符:

          運(yùn)算符

          描述

          實(shí)例

          返回值

          |

          計(jì)算兩個(gè)節(jié)點(diǎn)集

          //book | //cd

          返回所有擁有 book 和 cd 元素的節(jié)點(diǎn)集

          +

          加法

          6 + 4

          10

          -

          減法

          6 - 4

          2

          *

          乘法

          6 * 4

          24

          div

          除法

          8 div 4

          2

          =

          等于

          price=9.80

          如果 price 是 9.80,則返回 true。如果 price 是 9.90,則返回 false。

          !=

          不等于

          price!=9.80

          如果 price 是 9.90,則返回 true。如果 price 是 9.80,則返回 false。

          <

          小于

          price<9.80

          如果 price 是 9.00,則返回 true。如果 price 是 9.90,則返回 false。

          <=

          小于或等于

          price<=9.80

          如果 price 是 9.00,則返回 true。如果 price 是 9.90,則返回 false。

          >

          大于

          price>9.80

          如果 price 是 9.90,則返回 true。如果 price 是 9.80,則返回 false。

          >=

          大于或等于

          price>=9.80

          如果 price 是 9.90,則返回 true。如果 price 是 9.70,則返回 false。

          or

          price=9.80 or price=9.70

          如果 price 是 9.80,則返回 true。如果 price 是 9.50,則返回 false。

          and

          price>9.00 and price<9.90

          如果 price 是 9.80,則返回 true。如果 price 是 8.50,則返回 false。

          mod

          計(jì)算除法的余數(shù)

          5 mod 2

          1

          好了,xpath的內(nèi)容就這么多了。接下來我們要介紹一個(gè)神器lxml,他的速度很快,曾經(jīng)一直是我使用beautifulsoup時(shí)最鐘愛的解析器,沒有之一,因?yàn)樗乃俣鹊拇_比其他的html.parser 和html5lib快了許多。


          二、lxml

          1.lxml安裝

          lxml 是一個(gè)xpath格式解析模塊,安裝很方便,直接pip install lxml 或者easy_install lxml即可。


          2.lxml 使用

          lxml提供了兩種解析網(wǎng)頁的方式,一種是你解析自己寫的離線網(wǎng)頁時(shí),另一種 則是解析線上網(wǎng)頁。

          導(dǎo)入包:

          from lxml import  etree


          1.解析離線網(wǎng)頁:

          html=etree.parse('xx.html',etree.HTMLParser())
          aa=html.xpath('//*[@id="s_xmancard_news"]/div/div[2]/div/div[1]/h2/a[1]/@href')
          print(aa)

          2.解析在線網(wǎng)頁:

          from lxml import etree
          import requests
          rep=requests.get('https://www.baidu.com')
          html=etree.HTML(rep.text)
          aa=html.xpath('//*[@id="s_xmancard_news"]/div/div[2]/div/div[1]/h2/a[1]/@href')
          print(aa)

          那么我們?cè)趺传@取這些標(biāo)簽和標(biāo)簽對(duì)應(yīng)的屬性值了,很簡單,首先獲取標(biāo)簽只需你這樣做:


          然后我們可以,比方說,你要獲取a標(biāo)簽內(nèi)的文本和它的屬性href所對(duì)應(yīng)的值,有兩種方法,

          1.表達(dá)式內(nèi)獲取

          aa=html.xpath('//*[@id="s_xmancard_news"]/div/div[2]/div/div[1]/h2/a[1]/text()')
          
          
          ab=html.xpath('//*[@id="s_xmancard_news"]/div/div[2]/div/div[1]/h2/a[1]/@href')

          2.表達(dá)式外獲取

          aa=html.xpath('//*[@id="s_xmancard_news"]/div/div[2]/div/div[1]/h2/a[1]')
          
          
          aa.text
          
          
          aa.attrib.get('href')

          這樣就完成了獲取,怎么樣,是不是很簡單了,哈哈哈。


          下面再來lxml的解析規(guī)則:

          表達(dá)式

          描述

          nodename

          選取此節(jié)點(diǎn)的所有子節(jié)點(diǎn)

          /

          從當(dāng)前節(jié)點(diǎn)選取直接子節(jié)點(diǎn)

          //

          從當(dāng)前節(jié)點(diǎn)選取子孫節(jié)點(diǎn)

          .

          選取當(dāng)前節(jié)點(diǎn)

          ..

          選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)

          @

          選取屬性


          html=lxml.etree.HTML(text)
          #使用text構(gòu)造一個(gè)XPath解析對(duì)象,etree模塊可以自動(dòng)修正HTML文本
          html=lxml.etree.parse('./ex.html',etree.HTMLParser())
          #直接讀取文本進(jìn)行解析
          from lxml import etree
          result=html.xpath('//*')
          #選取所有節(jié)點(diǎn)
          result=html.xpath('//li')
          #獲取所有l(wèi)i節(jié)點(diǎn)
          result=html.xpath('//li/a')
          #獲取所有l(wèi)i節(jié)點(diǎn)的直接a子節(jié)點(diǎn)
          result=html.xpath('//li//a')
          #獲取所有l(wèi)i節(jié)點(diǎn)的所有a子孫節(jié)點(diǎn)
          result=html.xpath('//a[@href="link.html"]/../@class')
          #獲取所有href屬性為link.html的a節(jié)點(diǎn)的父節(jié)點(diǎn)的class屬性
          result=html.xpath('//li[@class="ni"]')
          #獲取所有class屬性為ni的li節(jié)點(diǎn)
          result=html.xpath('//li/text()')
          #獲取所有l(wèi)i節(jié)點(diǎn)的文本
          result=html.xpath('//li/a/@href')
          #獲取所有l(wèi)i節(jié)點(diǎn)的a節(jié)點(diǎn)的href屬性
          result=html.xpath('//li[contains(@class,"li")]/a/text())
          #當(dāng)li的class屬性有多個(gè)值時(shí),需用contains函數(shù)完成匹配
          result=html.xpath('//li[contains(@class,"li") and @name="item"]/a/text()')
          #多屬性匹配
          result=html.xpath('//li[1]/a/text()')
          result=html.xpath('//li[last()]/a/text()')
          result=html.xpath('//li[position()<3]/a/text()')
          result=html.xpath('//li[last()-2]/a/text()')
          #按序選擇,中括號(hào)內(nèi)為XPath提供的函數(shù)
          result=html.xpath('//li[1]/ancestor::*')
          #獲取祖先節(jié)點(diǎn)
          result=html.xpath('//li[1]/ancestor::div')
          result=html.xpath('//li[1]/attribute::*')
          #獲取屬性值
          result=html.xpath('//li[1]/child::a[@href="link1.html"]')
          #獲取直接子節(jié)點(diǎn)
          result=html.xpath('//li[1]/descendant::span')
          #獲取所有子孫節(jié)點(diǎn)
          result=html.xpath('//li[1]/following::*[2]')
          #獲取當(dāng)前節(jié)點(diǎn)之后的所有節(jié)點(diǎn)的第二個(gè)
          result=html.xpath('//li[1]/following-sibling::*')
          #獲取后續(xù)所有同級(jí)節(jié)點(diǎn)


          3.lxml案例

          為了偷懶,小編決定還是采用urllib那篇文章的代碼,哈哈哈,機(jī)智如我。

          好了,今天就講這么多,大家感興趣的話可以多多關(guān)注哦,精彩不停息!!!!

          本文參考文獻(xiàn):

          https://www.w3school.com.cn/

          想學(xué)習(xí)更多前端、Python爬蟲、大數(shù)據(jù)等計(jì)算機(jī)知識(shí),請(qǐng)前往:http://pdcfighting.com/

          Path 和 lxml

          XPath 全稱為 Xml Path Language,即 Xml 路徑語言,是一種在 Xml 文檔中查找信息的語言。它提供了非常簡潔的路徑選擇表達(dá)式,幾乎所有的節(jié)點(diǎn)定位都可以用它來選擇。

          XPath 可以用于 Xml 和 Html,在爬蟲中經(jīng)常使用 XPath 獲取 Html 文檔內(nèi)容。

          lxml 是 Python 語言用 Xpath 解析 XML、Html文檔功能最豐富的、最容易的功能模塊。

          XPath 術(shù)語

          節(jié)點(diǎn)

          在 XPath 中有七種節(jié)點(diǎn)分別是元素、屬性、文本、文檔、命名空間、處理指令、注釋,前3種節(jié)點(diǎn)為常用節(jié)點(diǎn)

          請(qǐng)看下面的 Html 例子,(注:這個(gè)例子全文都需要使用)

          <!DOCTYPE html>
          <html>
              <body>
                  <div>
                      <!-- 這里是注釋 -->
                      <h4>手機(jī)品牌商<span style="margin-left:10px">4</span></h4>
                      <ul>
                         <li>小米</li>
                         <li>華為</li> 
                         <li class='blank'> OPPO </li>
                         <li>蘋果</li>
                      </ul>
                  </div>
                  <div>
                      <h4>電腦品牌商<span style="margin-left:10px">3</span></h4>
                      <ul class="ul" style="color:red">
                          <li>戴爾</li> 
                          <li>機(jī)械革命</li> 
                          <li>ThinkPad</li>
                      </ul>
                  </div>
              </body>
          </html>
          

          在上面的例子中

          <html> 為文檔節(jié)點(diǎn)
          <li>小米</li> 為元素節(jié)點(diǎn)
          class='blank' 為屬性節(jié)點(diǎn)
          <!-- 這里是注釋 --> 為注釋節(jié)點(diǎn)
          

          節(jié)點(diǎn)關(guān)系

          在 XPath中有多中節(jié)點(diǎn)關(guān)系分別是父節(jié)點(diǎn)、子節(jié)點(diǎn)、同胞節(jié)點(diǎn)、先輩節(jié)點(diǎn)、后代節(jié)點(diǎn)

          在上面的例子中

          1. 父節(jié)點(diǎn):每個(gè)元素以及屬性都有一個(gè)父節(jié)點(diǎn),如:div 節(jié)點(diǎn)的父節(jié)點(diǎn)是 body 節(jié)點(diǎn)
          2. 子節(jié)點(diǎn):元素節(jié)點(diǎn)可有零個(gè)、一個(gè)或多個(gè)子節(jié)點(diǎn),如:第一個(gè) ul 節(jié)點(diǎn)的子節(jié)點(diǎn)是4個(gè) li 節(jié)點(diǎn)
          3. 同胞節(jié)點(diǎn):擁有相同的父節(jié)點(diǎn)的節(jié)點(diǎn),如:兩個(gè) div 節(jié)點(diǎn)是同胞節(jié)點(diǎn)
          4. 先輩節(jié)點(diǎn):某節(jié)點(diǎn)的父節(jié)點(diǎn)、父節(jié)點(diǎn)的父節(jié)點(diǎn)…,如:ul 節(jié)點(diǎn)的先輩節(jié)點(diǎn)有 div 節(jié)點(diǎn)、body 節(jié)點(diǎn)
          5. 后代節(jié)點(diǎn):某個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn),子節(jié)點(diǎn)的子節(jié)點(diǎn)…,如:body 節(jié)點(diǎn)的后代節(jié)點(diǎn)有div 節(jié)點(diǎn)、ul 節(jié)點(diǎn)、li 節(jié)點(diǎn)
            更多精彩可以點(diǎn)贊+關(guān)注私信我

          XPath 語法

          基本語法

          表達(dá)式描述nodeName選擇nodeName節(jié)點(diǎn)的所有子節(jié)點(diǎn)/從根節(jié)點(diǎn)開始//從匹配的節(jié)點(diǎn)開始選擇節(jié)點(diǎn).選擇當(dāng)前節(jié)點(diǎn)..選擇當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)@選擇元素*匹配任意元素節(jié)點(diǎn)@*匹配任意屬性節(jié)點(diǎn)

          用上面的 Html 文檔舉個(gè)例子

          路徑表達(dá)式描述body選取 body 的所有子節(jié)點(diǎn)/html選取 html 節(jié)點(diǎn)//div選取所有 div 節(jié)點(diǎn)//div/./h4div 節(jié)點(diǎn)下的 h4 節(jié)點(diǎn)../div選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)下的所有 div 節(jié)點(diǎn)//@class所有帶有 class 元素的節(jié)點(diǎn)//*選擇所有節(jié)點(diǎn)//@*選擇所有屬性節(jié)點(diǎn)

          常用函數(shù)

          表達(dá)式描述position()返回節(jié)點(diǎn)的 index 位置last()返回節(jié)點(diǎn)的個(gè)數(shù)contains(string1,string2)string1 是否包含 string2text()返回文本節(jié)點(diǎn)comment()返回注釋節(jié)點(diǎn)normalize-space(string)去除首位空格,中間多個(gè)空格用一個(gè)空格代替substring(string,start,len)返回從 start 位置開始的指定長度的子字符串,第一個(gè)字符下標(biāo)為1substring-before(string1,string2)返回string1中位于第一個(gè)string2之前的部分substring-after(string1,string2)返回string1中位于第一個(gè)string2之后的部分

          同樣用上面的Html文檔舉個(gè)例子

          路徑表達(dá)式描述//div[position()>1]選擇第二個(gè) div 節(jié)點(diǎn)//div[last()]選擇最后一個(gè) div 節(jié)點(diǎn)contains(//h4[2],’手機(jī)’)第二個(gè) h4 標(biāo)簽是否包含手機(jī)字符串//li/text()li 節(jié)點(diǎn)中的文本內(nèi)容//div/comment()div 節(jié)點(diǎn)下的 html 注釋normalize-space(//li[@class=’blank’])li 節(jié)點(diǎn)下 class屬性為 blank 的文本去掉空格substring(//h4[1],1,2)第一個(gè) h4 節(jié)點(diǎn)的前2個(gè)字substring-before(//h4[1],’品牌商’)第一個(gè) h4 節(jié)點(diǎn)的品牌商字符串之前的字符串substring-after(//h4[1],’品牌商’)第一個(gè) h4 節(jié)點(diǎn)的品牌商字符串之后的字符串

          謂語

          XPath 中的謂語就是刪選表達(dá)式,相當(dāng)于 SQL 中的 Where 條件,謂語被嵌在 [ ] 中

          路徑表達(dá)式描述//div[1]選擇第一個(gè) div 節(jié)點(diǎn)//div[2]/ul/li[last()]選擇第二個(gè) div 節(jié)點(diǎn)下的最后一個(gè) li 節(jié)點(diǎn)//div[2]/ul/li[position()>3]選擇第二個(gè) div 節(jié)點(diǎn)下的前兩個(gè) li 節(jié)點(diǎn)//ul[@class]選擇所有帶 class 屬性的 ul 節(jié)點(diǎn)//ul[@class=’computer’]選擇 class 屬性為 computer 的 ul 節(jié)點(diǎn)//h4[span=4]選擇 h4 節(jié)點(diǎn)下 span 值等于4的節(jié)點(diǎn)

          Xpath 結(jié)語

          以上內(nèi)容介紹了 XPath 的基本語法,下面將介紹 XPath 如何在 Python 中使用。

          lxml 模塊

          安裝

          sudo pip3 install lxml==4.4.1
          

          解析 HTML 文檔

          lxml.etree 一個(gè)強(qiáng)大的 Xml 處理模塊,etree 中的 ElementTree 類是一個(gè)主要的類,用于對(duì)XPath的解析、增加、刪除和修改節(jié)點(diǎn)。

          from lxml import etree
          

          etree.parse() 函數(shù)可以解析一個(gè)網(wǎng)頁文件還可以解析字符串, 在網(wǎng)頁中下載的數(shù)據(jù)一般都是字符串形式的,使用 parse(StringIO(str)) 將整個(gè)頁面內(nèi)容解析加載構(gòu)建一個(gè) ElementTree 對(duì)象,ElementTree 可以使用 XPath 語法精準(zhǔn)找到需要的數(shù)據(jù)。

          1.加載頁面到內(nèi)存

          from lxml import etree
          from io import StringIO
          
          test_html='''
          <html>
              <body>
                  <div>
                      <!-- 這里是注釋 -->
                      <h4>手機(jī)品牌商<span style="margin-left:10px">4</span></h4>
                      <ul>
                         <li>小米</li>
                         <li>華為</li>
                         <li class='blank'> OPPO </li>
                         <li>蘋果</li>
                      </ul>
                  </div>
                  <div>
                      <h4>電腦品牌商<span style="margin-left:10px">3</span></h4>
                      <ul class="ul" style="color:red">
                          <li>戴爾</li>
                          <li>機(jī)械革命</li>
                          <li>ThinkPad</li>
                      </ul>
                  </div>
              </body>
          </html>'''
          
          html=etree.parse(StringIO(test_html))
          print(html)
          

          結(jié)果:

          <lxml.etree._ElementTree object at 0x10bd6b948>
          

          2.獲取所有 li 標(biāo)簽數(shù)據(jù)

          li_list=html.xpath('//li')
          
          print("類型:")
          print(type(li_list))
          
          print("值:")
          print(li_list)
          
          print("個(gè)數(shù):")
          print(len(li_list))
          
          
          for l in li_list:
              print("li文本為:" + l.text)
          

          結(jié)果:

          類型:
          <class 'list'>
          值:
          [<Element li at 0x10543c9c8>, <Element li at 0x10543ca08>, <Element li at 0x10543ca48>, <Element li at 0x10543ca88>, <Element li at 0x10543cac8>, <Element li at 0x10543cb48>, <Element li at 0x10543cb88>]
          個(gè)數(shù):
          7
          li文本為:小米
          li文本為:華為
          li文本為: OPPO 
          li文本為:蘋果
          li文本為:戴爾
          li文本為:機(jī)械革命
          li文本為:ThinkPad
          

          3.獲取帶 class=’blank’ 屬性數(shù)據(jù)

          blank_li_list=html.xpath('//li[@class="blank"]')
          
          print("類型:")
          print(type(blank_li_list))
          
          print("值:")
          print(blank_li_list)
          
          print("個(gè)數(shù):")
          print(len(blank_li_list))
          
          
          for l in blank_li_list:
              print("li文本為:" + l.text)
          

          結(jié)果:

          類型:
          <class 'list'>
          值:
          [<Element li at 0x105253a48>]
          個(gè)數(shù):
          1
          li文本為: OPPO 
          

          4.屬性操作

          ul=html.xpath('//ul')[1]
          #遍歷屬性
          for name, value in ul.attrib.items():
              print('{0}="{1}"'.format(name, value))
          
          #添加新的屬性
          ul.set("new_attr", "true")
          # 獲取單個(gè)屬性
          new_attr=ul.get('new_attr')
          print(new_attr)
          

          結(jié)果:

          class="ul"
          style="color:red"
          true
          

          5.獲取最后一個(gè)div標(biāo)簽數(shù)據(jù)

          last_div=html.xpath('//div[last()]')
          print("TAG:")
          print(last_div.tag)
          print("值:")
          print(last_div.text)
          

          結(jié)果

          div
          值:
          
             
          

          6.添加子節(jié)點(diǎn)

          child=etree.Element("child")
          child.text="這里是新的子元素"
          last_div.append(child)
          # 在最后一個(gè) div 標(biāo)簽查找新的子元素
          clild_text=last_div.find("child").text
          print(clild_text)
          

          7.刪除子元素

          # 查找并設(shè)置第一個(gè)查詢到的元素
          first_ul=html.find("//ul")
          ul_li=first_ul.xpath("li")
          for li in ul_li:
              # 刪除元素
              first_ul.remove(li)
          
          ul_li=first_ul.xpath("li")
          if len(ul_li)==0:
              print("元素被刪除了")
          

          8.遍歷元素后代

          body=html.find("body")
          for sub in body.iter():
              print(sub.tag)
              print(sub.text)
          

          結(jié)果

          body
          
                  
          div
          
                      
          <cyfunction Comment at 0x10c374b10>
           這里是注釋 
          h4
          手機(jī)品牌商
          span
          4
          ul
          ...
          

          工具

          1. 在 google 瀏覽器開發(fā)者模式下,Elements 界面選擇元素后右鍵 Copy,可以 Copy 元素的 XPath 路徑
          2. XPath Helper 是一個(gè) google 瀏覽器插件,可以驗(yàn)證 XPath 是否正確

          總結(jié)

          1. 學(xué)習(xí)了 XPAth 的知識(shí),可以快速匹配單個(gè)或多個(gè)元素節(jié)點(diǎn)和屬性,在工作中大大加快了工作的效率。
          2. lxml 是一個(gè) Python 中強(qiáng)大的 Xml 和 Html 處理模塊,結(jié)合 XPath 的使用在程序中快速、便捷的分析、修改網(wǎng)頁內(nèi)容。

          慶才,Python技術(shù)控,爬蟲博文訪問量已過百萬。喜歡鉆研,熱愛生活,樂于分享。

          個(gè)人博客:靜覓 | http://cuiqingcai.com/

          XPath,全稱 XML Path Language,即 XML 路徑語言,它是一門在XML文檔中查找信息的語言。XPath 最初設(shè)計(jì)是用來搜尋XML文檔的,但是它同樣適用于 HTML 文檔的搜索。

          所以在做爬蟲時(shí),我們完全可以使用 XPath 來做相應(yīng)的信息抽取,本節(jié)我們來介紹一下 XPath 的基本用法。

          1. XPath概覽

          XPath 的選擇功能十分強(qiáng)大,它提供了非常簡潔明了的路徑選擇表達(dá)式,另外它還提供了超過 100 個(gè)內(nèi)建函數(shù)用于字符串、數(shù)值、時(shí)間的匹配以及節(jié)點(diǎn)、序列的處理等等,幾乎所有我們想要定位的節(jié)點(diǎn)都可以用XPath來選擇。

          XPath 于 1999 年 11 月 16 日 成為 W3C 標(biāo)準(zhǔn),它被設(shè)計(jì)為供 XSLT、XPointer 以及其他 XML 解析軟件使用,更多的文檔可以訪問其官方網(wǎng)站:https://www.w3.org/TR/xpath/。

          2. XPath常用規(guī)則

          我們現(xiàn)用表格列舉一下幾個(gè)常用規(guī)則:

          表達(dá)式描述

          nodename選取此節(jié)點(diǎn)的所有子節(jié)點(diǎn)

          /從當(dāng)前節(jié)點(diǎn)選取直接子節(jié)點(diǎn)

          //從當(dāng)前節(jié)點(diǎn)選取子孫節(jié)點(diǎn)

          .選取當(dāng)前節(jié)點(diǎn)

          ..選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)

          @選取屬性

          在這里列出了XPath的常用匹配規(guī)則,例如 / 代表選取直接子節(jié)點(diǎn),// 代表選擇所有子孫節(jié)點(diǎn),. 代表選取當(dāng)前節(jié)點(diǎn),.. 代表選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn),@ 則是加了屬性的限定,選取匹配屬性的特定節(jié)點(diǎn)。

          例如:

          //title[@lang=’eng’]

          這就是一個(gè) XPath 規(guī)則,它就代表選擇所有名稱為 title,同時(shí)屬性 lang 的值為 eng 的節(jié)點(diǎn)。

          在后文我們會(huì)介紹 XPath 的詳細(xì)用法,通過 Python 的 LXML 庫利用 XPath 進(jìn)行 HTML 的解析。

          3. 準(zhǔn)備工作

          在使用之前我們首先要確保安裝好了 LXML 庫,如沒有安裝可以參考第一章的安裝過程。

          4. 實(shí)例引入

          我們現(xiàn)用一個(gè)實(shí)例來感受一下使用 XPath 來對(duì)網(wǎng)頁進(jìn)行解析的過程,代碼如下:

          from lxml import etree

          text='''

          <div>

          <ul>

          <li><a >first item</a></li>

          <li><a >second item</a></li>

          <li><a >third item</a></li>

          <li><a >fourth item</a></li>

          <li><a >fifth item</a>

          </ul>

          </div>

          '''

          html=etree.HTML(text)

          result=etree.tostring(html)

          print(result.decode('utf-8'))

          在這里我們首先導(dǎo)入了 LXML 庫的 etree 模塊,然后聲明了一段 HTML 文本,調(diào)用 HTML 類進(jìn)行初始化,這樣我們就成功構(gòu)造了一個(gè) XPath 解析對(duì)象,在這里注意到 HTML 文本中的最后一個(gè) li 節(jié)點(diǎn)是沒有閉合的,但是 etree 模塊可以對(duì) HTML 文本進(jìn)行自動(dòng)修正。

          在這里我們調(diào)用 tostring() 方法即可輸出修正后的 HTML 代碼,但是結(jié)果是 bytes 類型,在這里我們利用 decode() 方法轉(zhuǎn)成 str 類型,結(jié)果如下:

          <html><body><div>

          <ul>

          <li class="item-0"><a href="link1.html">first item</a></li>

          <li class="item-1"><a href="link2.html">second item</a></li>

          <li class="item-inactive"><a href="link3.html">third item</a></li>

          <li class="item-1"><a href="link4.html">fourth item</a></li>

          <li class="item-0"><a href="link5.html">fifth item</a>

          </li></ul>

          </div>

          </body></html>

          我們可以看到經(jīng)過處理之后 li 節(jié)點(diǎn)標(biāo)簽被補(bǔ)全,并且還自動(dòng)添加了 body、html 節(jié)點(diǎn)。

          另外我們也可以直接讀取文本文件進(jìn)行解析,示例如下:

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=etree.tostring(html)

          print(result.decode('utf-8'))

          其中 test.html 的內(nèi)容就是上面例子中的 HTML 代碼,內(nèi)容如下:

          <div>

          <ul>

          <li class="item-0"><a href="link1.html">first item</a></li>

          <li class="item-1"><a href="link2.html">second item</a></li>

          <li class="item-inactive"><a href="link3.html">third item</a></li>

          <li class="item-1"><a href="link4.html">fourth item</a></li>

          <li class="item-0"><a href="link5.html">fifth item</a>

          </ul>

          </div>

          這次的輸出結(jié)果略有不同,多了一個(gè) DOCTYPE 的聲明,不過對(duì)解析無任何影響,結(jié)果如下:

          <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">

          <html><body><div>

          <ul>

          <li class="item-0"><a href="link1.html">first item</a></li>

          <li class="item-1"><a href="link2.html">second item</a></li>

          <li class="item-inactive"><a href="link3.html">third item</a></li>

          <li class="item-1"><a href="link4.html">fourth item</a></li>

          <li class="item-0"><a href="link5.html">fifth item</a>

          </li></ul>

          </div></body></html>

          5. 所有節(jié)點(diǎn)

          我們一般會(huì)用 // 開頭的 XPath 規(guī)則來選取所有符合要求的節(jié)點(diǎn),以上文的 HTML 文本為例,如果我們要選取所有節(jié)點(diǎn),可以這樣實(shí)現(xiàn):

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//*')

          print(result)

          運(yùn)行結(jié)果:

          [<Element html at 0x10510d9c8>, <Element body at 0x10510da08>, <Element div at 0x10510da48>, <Element ul at 0x10510da88>, <Element li at 0x10510dac8>, <Element a at 0x10510db48>, <Element li at 0x10510db88>, <Element a at 0x10510dbc8>, <Element li at 0x10510dc08>, <Element a at 0x10510db08>, <Element li at 0x10510dc48>, <Element a at 0x10510dc88>, <Element li at 0x10510dcc8>, <Element a at 0x10510dd08>]

          我們?cè)谶@里使用 * 代表匹配所有節(jié)點(diǎn),也就是整個(gè) HTML 文本中的所有節(jié)點(diǎn)都會(huì)被獲取,可以看到返回形式是一個(gè)列表,每個(gè)元素是 Element 類型,其后跟了節(jié)點(diǎn)的名稱,如 html、body、div、ul、li、a 等等,所有的節(jié)點(diǎn)都包含在列表中了。

          當(dāng)然此處匹配也可以指定節(jié)點(diǎn)名稱,如果我們想獲取所有 li 節(jié)點(diǎn),示例如下:

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//li')

          print(result)

          print(result[0])

          運(yùn)行結(jié)果:

          [<Element li at 0x105849208>, <Element li at 0x105849248>, <Element li at 0x105849288>, <Element li at 0x1058492c8>, <Element li at 0x105849308>]

          <Element li at 0x105849208>

          在這里我們可以看到提取結(jié)果是一個(gè)列表形式,其每一個(gè)元素都是一個(gè) Element 對(duì)象,如果要取出其中一個(gè)對(duì)象可以直接用中括號(hào)加索引即可取出,如 [0]。

          6. 子節(jié)點(diǎn)

          我們通過 / 或 // 即可查找元素的子節(jié)點(diǎn)或子孫節(jié)點(diǎn),加入我們現(xiàn)在想選擇 li 節(jié)點(diǎn)所有直接 a 子節(jié)點(diǎn),可以這樣來實(shí)現(xiàn):

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//li/a')

          print(result)

          在這里我們通過追加一個(gè) /a 即選擇了所有 li 節(jié)點(diǎn)的所有直接 a 子節(jié)點(diǎn),因?yàn)?//li 是選中所有l(wèi)i節(jié)點(diǎn), /a 是選中l(wèi)i節(jié)點(diǎn)的所有直接子節(jié)點(diǎn) a,二者組合在一起即獲取了所有l(wèi)i節(jié)點(diǎn)的所有直接 a 子節(jié)點(diǎn)。

          運(yùn)行結(jié)果:

          [<Element a at 0x106ee8688>, <Element a at 0x106ee86c8>, <Element a at 0x106ee8708>, <Element a at 0x106ee8748>, <Element a at 0x106ee8788>]

          但是此處的 / 是選取直接子節(jié)點(diǎn),如果我們要獲取所有子孫節(jié)點(diǎn)就該使用 // 了,例如我們要獲取 ul 節(jié)點(diǎn)下的所有子孫 a 節(jié)點(diǎn),可以這樣來實(shí)現(xiàn):

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//ul//a')

          print(result)

          運(yùn)行結(jié)果是相同的。

          但是這里如果我們用 //ul/a 就無法獲取任何結(jié)果了,因?yàn)?/ 是獲取直接子節(jié)點(diǎn),而在 ul 節(jié)點(diǎn)下沒有直接的 a 子節(jié)點(diǎn),只有 li 節(jié)點(diǎn),所以無法獲取任何匹配結(jié)果,代碼如下:

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//ul/a')

          print(result)

          運(yùn)行結(jié)果:

          []

          因此在這里我們要注意 / 和 // 的區(qū)別,/ 是獲取直接子節(jié)點(diǎn),// 是獲取子孫節(jié)點(diǎn)。

          7. 父節(jié)點(diǎn)

          我們知道通過連續(xù)的 / 或 // 可以查找子節(jié)點(diǎn)或子孫節(jié)點(diǎn),那假如我們知道了子節(jié)點(diǎn)怎樣來查找父節(jié)點(diǎn)呢?在這里我們可以用 .. 來獲取父節(jié)點(diǎn)。

          比如我們現(xiàn)在首先選中 href 是 link4.html 的 a 節(jié)點(diǎn),然后再獲取其父節(jié)點(diǎn),然后再獲取其 class 屬性,代碼如下:

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//a[@]

          檢查一下結(jié)果,正是我們獲取的目標(biāo) li 節(jié)點(diǎn)的 class,獲取父節(jié)點(diǎn)成功。

          同時(shí)我們也可以通過 parent:: 來獲取父節(jié)點(diǎn),代碼如下:

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//a[@)

          print(result)

          8. 屬性匹配

          在選取的時(shí)候我們還可以用 @ 符號(hào)進(jìn)行屬性過濾,比如在這里如果我們要選取 class 為 item-1 的 li 節(jié)點(diǎn),可以這樣實(shí)現(xiàn):

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//li[@class="item-0"]')

          print(result)

          在這里我們通過加入 [@class="item-0"] 就限制了節(jié)點(diǎn)的 class 屬性為 item-0,而 HTML 文本中符合條件的 li 節(jié)點(diǎn)有兩個(gè),所以返回結(jié)果應(yīng)該返回兩個(gè)匹配到的元素,結(jié)果如下:

          [<Element li at 0x10a399288>, <Element li at 0x10a3992c8>]

          可見匹配結(jié)果結(jié)果正是兩個(gè),至于是不是那正確的兩個(gè),我們?cè)诤竺骝?yàn)證一下。

          9. 文本獲取

          我們用 XPath 中的 text() 方法可以獲取節(jié)點(diǎn)中的文本,我們接下來嘗試獲取一下上文 li 節(jié)點(diǎn)中的文本,代碼如下:

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//li[@class="item-0"]/text()')

          print(result)

          運(yùn)行結(jié)果如下:

          ['\n ']

          很奇怪的是我們并沒有獲取到任何文本,而是只獲取到了一個(gè)換行符,這是為什么呢?因?yàn)?XPath 中 text() 前面是 /,而此 / 的含義是選取直接子節(jié)點(diǎn),而此處很明顯 li 的直接子節(jié)點(diǎn)都是 a 節(jié)點(diǎn),文本都是在 a 節(jié)點(diǎn)內(nèi)部的,所以這里匹配到的結(jié)果就是被修正的 li 節(jié)點(diǎn)內(nèi)部的換行符,因?yàn)樽詣?dòng)修正的li節(jié)點(diǎn)的尾標(biāo)簽換行了。

          即選中的是這兩個(gè)節(jié)點(diǎn):

          <li class="item-0"><a href="link1.html">first item</a></li>

          <li class="item-0"><a href="link5.html">fifth item</a>

          </li>

          其中一個(gè)節(jié)點(diǎn)因?yàn)樽詣?dòng)修正,li 節(jié)點(diǎn)的尾標(biāo)簽添加的時(shí)候換行了,所以提取文本得到的唯一結(jié)果就是 li 節(jié)點(diǎn)的尾標(biāo)簽和 a 節(jié)點(diǎn)的尾標(biāo)簽之間的換行符。

          因此,如果我們想獲取 li 節(jié)點(diǎn)內(nèi)部的文本就有兩種方式,一種是選取到 a 節(jié)點(diǎn)再獲取文本,另一種就是使用 //,我們來看下二者的區(qū)別是什么。

          首先我們選取到 a 節(jié)點(diǎn)再獲取文本,代碼如下:

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//li[@class="item-0"]/a/text()')

          print(result)

          運(yùn)行結(jié)果:

          ['first item', 'fifth item']

          可以看到這里返回值是兩個(gè),內(nèi)容都是屬性為 item-0 的 li 節(jié)點(diǎn)的文本,這也印證了我們上文中屬性匹配的結(jié)果是正確的。

          在這里我們是逐層選取的,先選取了 li 節(jié)點(diǎn),又利用 / 選取了其直接子節(jié)點(diǎn) a,然后再選取其文本,得到的結(jié)果恰好是符合我們預(yù)期的兩個(gè)結(jié)果。

          我們?cè)賮砜聪掠昧硪环N方式 // 選取的結(jié)果,代碼如下:

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//li[@class="item-0"]//text()')

          print(result)

          運(yùn)行結(jié)果:

          ['first item', 'fifth item', '\n ']

          不出所料,這里返回結(jié)果是三個(gè),可想而知這里是選取所有子孫節(jié)點(diǎn)的文本,其中前兩個(gè)就是 li 的子節(jié)點(diǎn) a 節(jié)點(diǎn)內(nèi)部的文本,另外一個(gè)就是最后一個(gè) li 節(jié)點(diǎn)內(nèi)部的文本,即換行符。

          所以說,如果我們要想獲取子孫節(jié)點(diǎn)內(nèi)部的所有文本,可以直接用 // 加 text() 的方式獲取,這樣可以保證獲取到最全面的文本信息,但是可能會(huì)夾雜一些換行符等特殊字符。如果我們想獲取某些特定子孫節(jié)點(diǎn)下的所有文本,可以先選取到特定的子孫節(jié)點(diǎn),然后再調(diào)用 text() 方法獲取其內(nèi)部文本,這樣可以保證獲取的結(jié)果是整潔的。

          10. 屬性獲取

          我們知道了用 text() 可以獲取節(jié)點(diǎn)內(nèi)部文本,那么節(jié)點(diǎn)屬性該怎樣獲取呢?其實(shí)還是用 @ 符號(hào)就可以,例如我們想獲取所有 li 節(jié)點(diǎn)下所有 a 節(jié)點(diǎn)的 href 屬性,代碼如下:

          from lxml import etree

          html=etree.parse('./test.html', etree.HTMLParser())

          result=html.xpath('//li/a/@href')

          print(result)

          在這里我們通過 @href 即可獲取節(jié)點(diǎn)的 href 屬性,注意此處和屬性匹配的方法不同,屬性匹配是中括號(hào)加屬性名和值來限定某個(gè)屬性,如 [@],而此處的 @href 指的是獲取節(jié)點(diǎn)的某個(gè)屬性,二者需要做好區(qū)分。

          運(yùn)行結(jié)果:

          ['link1.html', 'link2.html', 'link3.html', 'link4.html', 'link5.html']

          可以看到我們成功獲取了所有 li 節(jié)點(diǎn)下的 a 節(jié)點(diǎn)的 href 屬性,以列表形式返回。

          11. 屬性多值匹配

          有時(shí)候某些節(jié)點(diǎn)的某個(gè)屬性可能有多個(gè)值,例如下面例子:

          from lxml import etree

          text='''

          <li class="li li-first"><a >first item</a></li>

          '''

          html=etree.HTML(text)

          result=html.xpath('//li[@class="li"]/a/text()')

          print(result)

          在這里 HTML 文本中的 li 節(jié)點(diǎn)的 class 屬性有兩個(gè)值 li 和 li-first,但是此時(shí)如果我們還想用之前的屬性匹配獲取就無法匹配了,代碼運(yùn)行結(jié)果:

          []

          這時(shí)如果屬性有多個(gè)值就需要用 contains() 函數(shù)了,代碼可以改寫如下:

          from lxml import etree

          text='''

          <li class="li li-first"><a >first item</a></li>

          '''

          html=etree.HTML(text)

          result=html.xpath('//li[contains(@class, "li")]/a/text()')

          print(result)

          這樣我們通過 contains() 方法,第一個(gè)參數(shù)傳入屬性名稱,第二個(gè)參數(shù)傳入屬性值,這樣只要此屬性包含所傳入的屬性值就可以完成匹配了。

          運(yùn)行結(jié)果:

          ['first item']

          此種選擇方式在某個(gè)節(jié)點(diǎn)的某個(gè)屬性有多個(gè)值的時(shí)候經(jīng)常會(huì)用到,如某個(gè)節(jié)點(diǎn)的 class 屬性通常有多個(gè)。

          12. 多屬性匹配

          另外我們可能還遇到一種情況,我們可能需要根據(jù)多個(gè)屬性才能確定一個(gè)節(jié)點(diǎn),這是就需要同時(shí)匹配多個(gè)屬性才可以,那么這里可以使用運(yùn)算符 and 來連接,示例如下:

          from lxml import etree

          text='''

          <li class="li li-first" name="item"><a >first item</a></li>

          '''

          html=etree.HTML(text)

          result=html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')

          print(result)

          在這里 HTML 文本的 li 節(jié)點(diǎn)又增加了一個(gè)屬性 name,這時(shí)候我們需要同時(shí)根據(jù) class 和 name 屬性來選擇,就可以 and 運(yùn)算符連接兩個(gè)條件,兩個(gè)條件都被中括號(hào)包圍,運(yùn)行結(jié)果如下:

          ['first item']

          這里的 and 其實(shí)是 XPath 中的運(yùn)算符,另外還有很多運(yùn)算符,如 or、mod 等等,在此總結(jié)如下:

          運(yùn)算符描述實(shí)例返回值

          or或price=9.80 or price=9.70如果 price 是 9.80,則返回 true。如果 price 是 9.50,則返回 false。

          and與price>9.00 and price<9.90如果 price 是 9.80,則返回 true。如果 price 是 8.50,則返回 false。

          mod計(jì)算除法的余數(shù)5 mod 21

          \計(jì)算兩個(gè)節(jié)點(diǎn)集//book \//cd返回所有擁有 book 和 cd 元素的節(jié)點(diǎn)集

          +加法6 + 410

          -減法6 - 42

          *乘法6 * 424

          div除法8 div 42

          =等于price=9.80如果 price 是 9.80,則返回 true。如果 price 是 9.90,則返回 false。

          !=不等于price!=9.80如果 price 是 9.90,則返回 true。如果 price 是 9.80,則返回 false。

          <小于price<9.80如果 price 是 9.00,則返回 true。如果 price 是 9.90,則返回 false。

          <=小于或等于price<=9.80如果 price 是 9.00,則返回 true。如果 price 是 9.90,則返回 false。

          >大于price>9.80如果 price 是 9.90,則返回 true。如果 price 是 9.80,則返回 false。

          >=大于或等于price>=9.80如果 price 是 9.90,則返回 true。如果 price 是 9.70,則返回 false。

          此表參考來源:http://www.w3school.com.cn/xpath/xpath_operators.asp。

          13. 按序選擇

          有時(shí)候我們?cè)谶x擇的時(shí)候可能某些屬性同時(shí)匹配了多個(gè)節(jié)點(diǎn),但是我們只想要其中的某個(gè)節(jié)點(diǎn),如第二個(gè)節(jié)點(diǎn),或者最后一個(gè)節(jié)點(diǎn),這時(shí)該怎么辦呢?

          這時(shí)可以利用中括號(hào)傳入索引的方法獲取特定次序的節(jié)點(diǎn),示例如下:

          from lxml import etree

          text='''

          <div>

          <ul>

          <li><a >first item</a></li>

          <li><a >second item</a></li>

          <li><a >third item</a></li>

          <li><a >fourth item</a></li>

          <li><a >fifth item</a>

          </ul>

          </div>

          '''

          html=etree.HTML(text)

          result=html.xpath('//li[1]/a/text()')

          print(result)

          result=html.xpath('//li[last()]/a/text()')

          print(result)

          result=html.xpath('//li[position()<3]/a/text()')

          print(result)

          result=html.xpath('//li[last()-2]/a/text()')

          print(result)

          第一次選擇我們選取了第一個(gè) li 節(jié)點(diǎn),中括號(hào)中傳入數(shù)字1即可,注意這里和代碼中不同,序號(hào)是以 1 開頭的,不是 0 開頭的。

          第二次選擇我們選取了最后一個(gè) li 節(jié)點(diǎn),中括號(hào)中傳入 last() 即可,返回的便是最后一個(gè) li 節(jié)點(diǎn)。

          第三次選擇我們選取了位置小于 3 的 li 節(jié)點(diǎn),也就是位置序號(hào)為 1 和 2 的節(jié)點(diǎn),得到的結(jié)果就是前 2 個(gè) li 節(jié)點(diǎn)。

          第四次選擇我們選取了倒數(shù)第三個(gè) li 節(jié)點(diǎn),中括號(hào)中傳入 last()-2即可,因?yàn)?last() 是最后一個(gè),所以 last()-2 就是倒數(shù)第三個(gè)。

          運(yùn)行結(jié)果如下:

          ['first item']

          ['fifth item']

          ['first item', 'second item']

          ['third item']

          在這里我們使用了 last()、position() 等函數(shù),XPath 中提供了 100 多個(gè)函數(shù),包括存取、數(shù)值、字符串、邏輯、節(jié)點(diǎn)、序列等處理功能,具體所有的函數(shù)作用可以參考:http://www.w3school.com.cn/xpath/xpath_functions.asp。

          14. 節(jié)點(diǎn)軸選擇

          XPath 提供了很多節(jié)點(diǎn)軸選擇方法,英文叫做 XPath Axes,包括獲取子元素、兄弟元素、父元素、祖先元素等等,在一定情況下使用它可以方便地完成節(jié)點(diǎn)的選擇,我們用一個(gè)實(shí)例來感受一下:

          from lxml import etree

          text='''

          <div>

          <ul>

          <li><a ><span>first item</span></a></li>

          <li><a >second item</a></li>

          <li><a >third item</a></li>

          <li><a >fourth item</a></li>

          <li><a >fifth item</a>

          </ul>

          </div>

          '''

          html=etree.HTML(text)

          result=html.xpath('//li[1]/ancestor::*')

          print(result)

          result=html.xpath('//li[1]/ancestor::div')

          print(result)

          result=html.xpath('//li[1]/attribute::*')

          print(result)

          result=html.xpath('//li[1]/child::a[@)

          print(result)

          運(yùn)行結(jié)果:

          [<Element html at 0x107941808>, <Element body at 0x1079418c8>, <Element div at 0x107941908>, <Element ul at 0x107941948>]

          [<Element div at 0x107941908>]

          ['item-0']

          [<Element a at 0x1079418c8>]

          [<Element span at 0x107941948>]

          [<Element a at 0x1079418c8>]

          [<Element li at 0x107941948>, <Element li at 0x107941988>, <Element li at 0x1079419c8>, <Element li at 0x107941a08>]

          第一次選擇我們調(diào)用了 ancestor 軸,可以獲取所有祖先節(jié)點(diǎn),其后需要跟兩個(gè)冒號(hào),然后是節(jié)點(diǎn)的選擇器,這里我們直接使用了 *,表示匹配所有節(jié)點(diǎn),因此返回結(jié)果是第一個(gè) li 節(jié)點(diǎn)的所有祖先節(jié)點(diǎn),包括 html,body,div,ul。

          第二次選擇我們又加了限定條件,這次在冒號(hào)后面加了 div,這樣得到的結(jié)果就只有 div 這個(gè)祖先節(jié)點(diǎn)了。

          第三次選擇我們調(diào)用了 attribute 軸,可以獲取所有屬性值,其后跟的選擇器還是 *,這代表獲取節(jié)點(diǎn)的所有屬性,返回值就是 li 節(jié)點(diǎn)的所有屬性值。

          第四次選擇我們調(diào)用了 child 軸,可以獲取所有直接子節(jié)點(diǎn),在這里我們又加了限定條件選取 href 屬性為 link1.html 的 a 節(jié)點(diǎn)。

          第五次選擇我們調(diào)用了 descendant 軸,可以獲取所有子孫節(jié)點(diǎn),這里我們又加了限定條件獲取 span 節(jié)點(diǎn),所以返回的就是只包含 span 節(jié)點(diǎn)而沒有 a 節(jié)點(diǎn)。

          第六次選擇我們調(diào)用了 following 軸,可以獲取當(dāng)前節(jié)點(diǎn)之后的所有節(jié)點(diǎn),這里我們雖然使用的是 * 匹配,但又加了索引選擇,所以只獲取了第二個(gè)后續(xù)節(jié)點(diǎn)。

          第七次選擇我們調(diào)用了 following-sibling 軸,可以獲取當(dāng)前節(jié)點(diǎn)之后的所有同級(jí)節(jié)點(diǎn),這里我們使用的是 * 匹配,所以獲取了所有后續(xù)同級(jí)節(jié)點(diǎn)。

          以上是XPath軸的簡單用法,更多的軸的使用可以參考:http://www.w3school.com.cn/xpath/xpath_axes.asp。

          End.

          運(yùn)行人員:中國統(tǒng)計(jì)網(wǎng)小編(微信號(hào):itongjilove)

          微博ID:中國統(tǒng)計(jì)網(wǎng)

          中國統(tǒng)計(jì)網(wǎng),是國內(nèi)最早的大數(shù)據(jù)學(xué)習(xí)網(wǎng)站,公眾號(hào):中國統(tǒng)計(jì)網(wǎng)

          http://www.itongji.cn


          主站蜘蛛池模板: 中文字幕在线精品视频入口一区| 夜夜爽一区二区三区精品| 秋霞鲁丝片一区二区三区| 精品国产免费一区二区三区香蕉| 亚洲日韩AV一区二区三区四区| 精品伦精品一区二区三区视频| 无码人妻aⅴ一区二区三区| 无码人妻精品一区二区三区99仓本 | 国产成人欧美一区二区三区 | 无码少妇一区二区三区浪潮AV| 国产精品一区电影| 国模极品一区二区三区| 97久久精品无码一区二区| 78成人精品电影在线播放日韩精品电影一区亚洲 | bt7086福利一区国产| 3d动漫精品一区视频在线观看| 亚洲乱码日产一区三区| 制服中文字幕一区二区| 中文字幕一区二区三区有限公司| 一区二区三区AV高清免费波多| 久久久久人妻精品一区三寸| 国产成人综合一区精品| 国产一区二区三区韩国女主播| 日韩一区二区在线观看视频| 久久无码人妻一区二区三区 | 精品一区二区三区色花堂| 精品一区二区三区在线观看l | 视频一区视频二区在线观看| 无码中文字幕人妻在线一区二区三区| 亚洲视频一区网站| 国产成人精品第一区二区| 欧美日韩国产免费一区二区三区| 无码丰满熟妇浪潮一区二区AV | 乱码精品一区二区三区| 国产精品揄拍一区二区久久| 无码国产精品一区二区免费虚拟VR | 亚洲一区二区三区在线观看精品中文 | 性色av闺蜜一区二区三区| 日韩精品一区二区三区毛片| 波多野结衣在线观看一区二区三区| 日本一区二区三区在线看|