整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Python小案例77-解析HTML文檔

          解析HTML文檔,可以使用一些編程語言中的HTML解析庫或工具。以下是一些常用的方法:

          1. 使用Python中的BeautifulSoup庫:BeautifulSoup是一個功能強大的HTML解析庫,可以幫助你從HTML文檔中提取數據。你可以使用pip安裝BeautifulSoup,然后使用它的解析器來解析HTML文檔。
          from bs4 import BeautifulSoup
          
          # 讀取HTML文檔
          with open('example.html', 'r') as file:
              html = file.read()
          
          # 創建BeautifulSoup對象
          soup = BeautifulSoup(html, 'html.parser')
          
          # 使用BeautifulSoup對象提取數據
          # 例如,提取所有的鏈接
          links = soup.find_all('a')
          for link in links:
              print(link.get('href'))
          
          1. 使用JavaScript中的DOM解析器:如果你在瀏覽器環境中,可以使用JavaScript的DOM解析器來解析HTML文檔。你可以使用document對象來訪問和操作HTML元素。
          // 讀取HTML文檔
          var html = document.documentElement.innerHTML;
          
          // 使用DOM解析器提取數據
          // 例如,提取所有的鏈接
          var links = document.getElementsByTagName('a');
          for (var i = 0; i < links.length; i++) {
              console.log(links[i].getAttribute('href'));
          }
          
          1. 使用其他編程語言的HTML解析庫:除了Python和JavaScript,還有許多其他編程語言也有自己的HTML解析庫,例如Java中的Jsoup、Ruby中的Nokogiri等。你可以根據自己的編程語言選擇適合的HTML解析庫來解析HTML文檔。

          無論你選擇哪種方法,解析HTML文檔的關鍵是了解HTML的結構和標簽,并使用相應的解析器或工具來提取所需的數據。

          當你解析HTML文檔時,你可能會遇到以下一些常見的任務和技術:

          1. 選擇器:使用選擇器可以方便地定位和提取HTML文檔中的特定元素。例如,你可以使用CSS選擇器來選擇具有特定類名或ID的元素,或者使用XPath來選擇具有特定屬性或層次結構的元素。
          2. 提取數據:一旦你定位到了要提取的元素,你可以使用相應的方法或屬性來獲取元素的文本內容、屬性值或其他相關信息。例如,你可以使用getText()方法來獲取元素的文本內容,使用getAttribute()方法來獲取元素的屬性值。
          3. 遍歷文檔:HTML文檔通常是一個樹狀結構,你可以使用遍歷方法來訪問和操作文檔中的不同元素。例如,你可以使用遞歸或循環來遍歷文檔的子元素、父元素或兄弟元素。
          4. 處理嵌套結構:HTML文檔中的元素可能會有嵌套的結構,你需要處理這些嵌套關系來正確地提取數據。例如,你可以使用遞歸方法來處理嵌套的列表、表格或嵌套的div元素。
          5. 處理特殊情況:在解析HTML文檔時,可能會遇到一些特殊情況,例如處理動態生成的內容、處理特殊字符或處理錯誤的HTML結構。你需要根據具體情況選擇合適的方法來處理這些特殊情況。

          總的來說,解析HTML文檔需要一定的HTML知識和編程技巧。你需要了解HTML的結構和標簽,選擇合適的解析器或工具,使用選擇器來定位元素,提取所需的數據,并處理特殊情況。通過不斷練習和實踐,你將能夠更熟練地解析HTML文檔并提取所需的數據。

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

          個人博客:靜覓 | http://cuiqingcai.com/

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

          所以在做爬蟲時,我們完全可以使用 XPath 來做相應的信息抽取,本節我們來介紹一下 XPath 的基本用法。

          1. XPath概覽

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

          XPath 于 1999 年 11 月 16 日 成為 W3C 標準,它被設計為供 XSLT、XPointer 以及其他 XML 解析軟件使用,更多的文檔可以訪問其官方網站:https://www.w3.org/TR/xpath/。

          2. XPath常用規則

          我們現用表格列舉一下幾個常用規則:

          表達式描述

          nodename選取此節點的所有子節點

          /從當前節點選取直接子節點

          //從當前節點選取子孫節點

          .選取當前節點

          ..選取當前節點的父節點

          @選取屬性

          在這里列出了XPath的常用匹配規則,例如 / 代表選取直接子節點,// 代表選擇所有子孫節點,. 代表選取當前節點,.. 代表選取當前節點的父節點,@ 則是加了屬性的限定,選取匹配屬性的特定節點。

          例如:

          //title[@lang=’eng’]

          這就是一個 XPath 規則,它就代表選擇所有名稱為 title,同時屬性 lang 的值為 eng 的節點。

          在后文我們會介紹 XPath 的詳細用法,通過 Python 的 LXML 庫利用 XPath 進行 HTML 的解析。

          3. 準備工作

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

          4. 實例引入

          我們現用一個實例來感受一下使用 XPath 來對網頁進行解析的過程,代碼如下:

          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'))

          在這里我們首先導入了 LXML 庫的 etree 模塊,然后聲明了一段 HTML 文本,調用 HTML 類進行初始化,這樣我們就成功構造了一個 XPath 解析對象,在這里注意到 HTML 文本中的最后一個 li 節點是沒有閉合的,但是 etree 模塊可以對 HTML 文本進行自動修正。

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

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

          我們可以看到經過處理之后 li 節點標簽被補全,并且還自動添加了 body、html 節點。

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

          from lxml import etree

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

          result = etree.tostring(html)

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

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

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

          這次的輸出結果略有不同,多了一個 DOCTYPE 的聲明,不過對解析無任何影響,結果如下:

          <!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. 所有節點

          我們一般會用 // 開頭的 XPath 規則來選取所有符合要求的節點,以上文的 HTML 文本為例,如果我們要選取所有節點,可以這樣實現:

          from lxml import etree

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

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

          print(result)

          運行結果:

          [<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>]

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

          當然此處匹配也可以指定節點名稱,如果我們想獲取所有 li 節點,示例如下:

          from lxml import etree

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

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

          print(result)

          print(result[0])

          運行結果:

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

          <Element li at 0x105849208>

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

          6. 子節點

          我們通過 / 或 // 即可查找元素的子節點或子孫節點,加入我們現在想選擇 li 節點所有直接 a 子節點,可以這樣來實現:

          from lxml import etree

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

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

          print(result)

          在這里我們通過追加一個 /a 即選擇了所有 li 節點的所有直接 a 子節點,因為 //li 是選中所有li節點, /a 是選中li節點的所有直接子節點 a,二者組合在一起即獲取了所有li節點的所有直接 a 子節點。

          運行結果:

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

          但是此處的 / 是選取直接子節點,如果我們要獲取所有子孫節點就該使用 // 了,例如我們要獲取 ul 節點下的所有子孫 a 節點,可以這樣來實現:

          from lxml import etree

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

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

          print(result)

          運行結果是相同的。

          但是這里如果我們用 //ul/a 就無法獲取任何結果了,因為 / 是獲取直接子節點,而在 ul 節點下沒有直接的 a 子節點,只有 li 節點,所以無法獲取任何匹配結果,代碼如下:

          from lxml import etree

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

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

          print(result)

          運行結果:

          []

          因此在這里我們要注意 / 和 // 的區別,/ 是獲取直接子節點,// 是獲取子孫節點。

          7. 父節點

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

          比如我們現在首先選中 href 是 link4.html 的 a 節點,然后再獲取其父節點,然后再獲取其 class 屬性,代碼如下:

          from lxml import etree

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

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

          檢查一下結果,正是我們獲取的目標 li 節點的 class,獲取父節點成功。

          同時我們也可以通過 parent:: 來獲取父節點,代碼如下:

          from lxml import etree

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

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

          print(result)

          8. 屬性匹配

          在選取的時候我們還可以用 @ 符號進行屬性過濾,比如在這里如果我們要選取 class 為 item-1 的 li 節點,可以這樣實現:

          from lxml import etree

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

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

          print(result)

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

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

          可見匹配結果結果正是兩個,至于是不是那正確的兩個,我們在后面驗證一下。

          9. 文本獲取

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

          from lxml import etree

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

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

          print(result)

          運行結果如下:

          ['\n ']

          很奇怪的是我們并沒有獲取到任何文本,而是只獲取到了一個換行符,這是為什么呢?因為 XPath 中 text() 前面是 /,而此 / 的含義是選取直接子節點,而此處很明顯 li 的直接子節點都是 a 節點,文本都是在 a 節點內部的,所以這里匹配到的結果就是被修正的 li 節點內部的換行符,因為自動修正的li節點的尾標簽換行了。

          即選中的是這兩個節點:

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

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

          </li>

          其中一個節點因為自動修正,li 節點的尾標簽添加的時候換行了,所以提取文本得到的唯一結果就是 li 節點的尾標簽和 a 節點的尾標簽之間的換行符。

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

          首先我們選取到 a 節點再獲取文本,代碼如下:

          from lxml import etree

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

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

          print(result)

          運行結果:

          ['first item', 'fifth item']

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

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

          我們再來看下用另一種方式 // 選取的結果,代碼如下:

          from lxml import etree

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

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

          print(result)

          運行結果:

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

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

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

          10. 屬性獲取

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

          from lxml import etree

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

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

          print(result)

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

          運行結果:

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

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

          11. 屬性多值匹配

          有時候某些節點的某個屬性可能有多個值,例如下面例子:

          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 節點的 class 屬性有兩個值 li 和 li-first,但是此時如果我們還想用之前的屬性匹配獲取就無法匹配了,代碼運行結果:

          []

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

          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() 方法,第一個參數傳入屬性名稱,第二個參數傳入屬性值,這樣只要此屬性包含所傳入的屬性值就可以完成匹配了。

          運行結果:

          ['first item']

          此種選擇方式在某個節點的某個屬性有多個值的時候經常會用到,如某個節點的 class 屬性通常有多個。

          12. 多屬性匹配

          另外我們可能還遇到一種情況,我們可能需要根據多個屬性才能確定一個節點,這是就需要同時匹配多個屬性才可以,那么這里可以使用運算符 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 節點又增加了一個屬性 name,這時候我們需要同時根據 class 和 name 屬性來選擇,就可以 and 運算符連接兩個條件,兩個條件都被中括號包圍,運行結果如下:

          ['first item']

          這里的 and 其實是 XPath 中的運算符,另外還有很多運算符,如 or、mod 等等,在此總結如下:

          運算符描述實例返回值

          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計算除法的余數5 mod 21

          \計算兩個節點集//book \//cd返回所有擁有 book 和 cd 元素的節點集

          +加法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. 按序選擇

          有時候我們在選擇的時候可能某些屬性同時匹配了多個節點,但是我們只想要其中的某個節點,如第二個節點,或者最后一個節點,這時該怎么辦呢?

          這時可以利用中括號傳入索引的方法獲取特定次序的節點,示例如下:

          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)

          第一次選擇我們選取了第一個 li 節點,中括號中傳入數字1即可,注意這里和代碼中不同,序號是以 1 開頭的,不是 0 開頭的。

          第二次選擇我們選取了最后一個 li 節點,中括號中傳入 last() 即可,返回的便是最后一個 li 節點。

          第三次選擇我們選取了位置小于 3 的 li 節點,也就是位置序號為 1 和 2 的節點,得到的結果就是前 2 個 li 節點。

          第四次選擇我們選取了倒數第三個 li 節點,中括號中傳入 last()-2即可,因為 last() 是最后一個,所以 last()-2 就是倒數第三個。

          運行結果如下:

          ['first item']

          ['fifth item']

          ['first item', 'second item']

          ['third item']

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

          14. 節點軸選擇

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

          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)

          result = html.xpath('//li[1]/descendant::span')

          print(result)

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

          print(result)

          result = html.xpath('//li[1]/following-sibling::*')

          print(result)

          運行結果:

          [<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>]

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

          第二次選擇我們又加了限定條件,這次在冒號后面加了 div,這樣得到的結果就只有 div 這個祖先節點了。

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

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

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

          第六次選擇我們調用了 following 軸,可以獲取當前節點之后的所有節點,這里我們雖然使用的是 * 匹配,但又加了索引選擇,所以只獲取了第二個后續節點。

          第七次選擇我們調用了 following-sibling 軸,可以獲取當前節點之后的所有同級節點,這里我們使用的是 * 匹配,所以獲取了所有后續同級節點。

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

          End.

          運行人員:中國統計網小編(微信號:itongjilove)

          微博ID:中國統計網

          中國統計網,是國內最早的大數據學習網站,公眾號:中國統計網

          http://www.itongji.cn

          • 使用XPath解析庫

          @(這里寫自定義目錄標題)

          使用XPath解析庫

          1.簡介

          ??XPath(全稱XML Path Languang),即XML路徑語言,是一種在XML文檔中查找信息的語言。適用于XML和HTML文檔的搜索。
          ??優點:提供了非常簡潔明了的路徑選擇表達式。還提供了超過100個內建函數,可以匹配大部分的節點。
          ??官網
          ??準備工作:需要安裝lxml庫。


          2.常用規則

          表達式功能nodename選取此節點的所有子節點/從當前節點選取直接子節點//從當前節點選取直接子孫節點.選取當前節點..選取當前節點的父節點@選取屬性


          3.etree模塊解析網頁簡介

          ??etree是lxml庫中的函數,可以自動修正HTML文本。下面是兩種導入方法:
          ??直接讀取網頁代碼進行解析:

          from lxml import etree
          text = '''
          HTML文本
          '''
          # 將HTML文本轉化為可以用etree解析的對象,
          html = etree.HTML(text) # 結果是bytes類型,如果需要文本輸出,則需要用decode()轉碼為Unicode編碼

          ??讀取文本文件進行解析(這里既會自動修正文件,又會補充DOCTYPE聲明):

          from lxml import etree
          html = etree.parse('文本文件路徑/文本文件名字.html',etree.HTMLParse()) # 結果是bytes類型,如果需要文本輸出,則需要用decode()轉碼為Unicode編碼

          ??用tostring()方法即可輸出修正后的HTML代碼。

          4.選取所有節點,子節點和父節點

          (1)選取所有節點

          ??一般用//開頭的XPath規則,就會選擇從當前節點開始的所有子孫節點,也就是所有節點。所以要匹配所有的節點代碼如下:

          a = html.xpath('//*') # 選取所有的節點
          b = html.xpath('//a') # 選取所有的a節點,是一個例子

          ??這里的a和b,也就是xpath方法的返回值是一個列表,每個元素是Element類型,后面跟著節點的名稱,是一個可迭代對象。要取出某一個對象,就需要用處理列表的方法進行。

          (2)選取子節點

          ??選取子節點只需要在后面加上/節點名稱(選擇直接子節點,也就是與其相鄰的第一個子節點),如果直接子節點沒有就會報錯,或者//節點名稱(選擇所有子孫節點),例子如下:

          c = html.xpath('//li/a') # 選取li節點的直接a子節點
          d = html.xpath('//li//a') # 選取li節點的所有a子節點

          (3)選取父節點

          ??獲取某個節點的父節點有兩個方法,一個是用..,另一個是用parent::。
          同理,如果沒有父節點,就會報錯,例子如下:

          e = html.xpath('//li/../a') # 選取li節點的父節點下的a節點
          f = html.xpath('//li/parent::/a') # 選取li節點的父節點下的直接a節點
          g = html.xpath('//li/parent::*/a') # 選取li節點的父節點下的所有a節點


          5.屬性匹配,文本獲取和屬性多值匹配

          (1)屬性匹配

          ??在選取節點的時候,可以用@符號進行屬性過濾,用[@屬性名="屬性值"]進行實現,例子如下:

          s = html.xpath('//li[@class="ming"]') # 選取屬性值class="ming"的所有li節點

          ??要注意的是里面的括號和外面的括號盡量一個用雙引號,一個用單引號。

          (2)文本獲取

          ??我們用Xpath中的text()方法即可獲取節點中的文本。要注意的是獲取到的數據可能包括換行符'\n'。

          (3)屬性多值匹配

          ??要是屬性有多個值的話,用上面的方法就無法匹配了。需要用到contains()函數,包含兩個參數,即@屬性名和屬性值,例子如下:

          # 源代碼中為<li class="ming1 ming2">
          s1 = html.xpath('//li[contains(@class,"ming1")]') # 選取屬性值class="ming1"的所有li節點
          s2 = html.xpath('//li[contains(@class,"ming2")]') # 選取屬性值class="ming2"的所有li節點


          6.屬性獲取和多屬性匹配

          (1)屬性獲取

          ??屬性獲取直接用@獲取即可,例子如下:

          s = html.xpath('//li/a/@href]') # 獲取所有li節點下的直接a子節點的href屬性

          (2)多屬性匹配

          ??有時候需要根據多個屬性值確定一個節點,就需要同時匹配多個屬性。要用and進行連接,可以把contains(@屬性名,"屬性名")和@屬性名="屬性值"混合使用,例子如下:

          # 選取所有屬性值class="a"和_target="ming"的li節點下的所有a節點的href屬性
          two_s = html.xpath('//li[contains(@class,"a") and @_target="ming"]//a/@href')


          7.按次序選擇

          ??有時候選擇到的某些屬性可能同時匹配了多個節點,但是要想得到其中的某一個節點,該如何獲取呢?可以用中括號傳入索引的方法獲取特定次序的節點。下面是一些常用方法的總結:

          方法功能[n]選取第n個節點,序號是以1開頭的[last()]選取最后一個節點[position() < n]選取位置小于n的節點,這里可以用算術運算符進行選擇[last() - n]選取倒數第n+1個節點,由于last()是倒數第一個,則last() - n就是倒數第n+1個


          8.節點軸選擇

          ??由于網頁代碼是一個DOM樹,因此可以用相對的位置進行選擇節點的子節點,兄弟節點,父節點或者祖先節點等。python的節點軸選擇常用的如下:

          節點軸選擇節點ancestor:: *獲取所有祖先節點ancestor::條件獲取指定條件的祖先節點attribute:: *獲取節點的所有屬性attribute::屬性名獲取節點的指定屬性child:: *獲取所有子節點child::條件獲取指定條件的子節點descendent:: *獲取所有的子孫節點descendent::條件獲取指定條件的子孫節點following:: *獲取當前節點之后的所有節點following:: *[n]獲取當前節點之后的第n個節點following-sibing:: *獲取當前節點之后的所有同級節點following-sibing::條件獲取當前節點之后指定條件的所有同級節點


          9.開發者工具查看xpath選擇器路徑

          ??用F12打開開發者工具,按才Copy->Copy Xpath就可以把該段代碼的XPath路徑代碼復制下來,很方便。

          最后,小編想說:我是一名python開發工程師,整理了一套最新的python系統學習教程,想要這些資料的可以關注私信小編“01”即可,希望能對你有所幫助。


          主站蜘蛛池模板: 一区二区三区精密机械| 精品国产亚洲一区二区在线观看 | 精品国产一区二区三区久久蜜臀 | 国产伦精品一区二区三区在线观看| 日本免费一区二区三区四区五六区| 亚洲国产av一区二区三区| 国产在线一区二区三区av| 免费观看日本污污ww网站一区| 日本一区二区三区四区视频| 国产一区二区三区美女| 一区 二区 三区 中文字幕| 一区二区三区午夜| 成人国产一区二区三区| 国精产品一区一区三区| 人妻少妇精品视频一区二区三区| 亚洲一区在线免费观看| 亚洲国产系列一区二区三区 | 中文字幕在线无码一区二区三区| 红杏亚洲影院一区二区三区| 在线观看免费视频一区| 午夜福利av无码一区二区| 成人免费观看一区二区| 夜夜精品视频一区二区| 视频一区视频二区日韩专区| 久久精品人妻一区二区三区 | 亚洲一区二区三区精品视频| 亚洲无码一区二区三区| 国产精品视频无圣光一区| 国产一区二区精品久久91| 精品视频一区二区三区四区五区| 国产精品免费一区二区三区四区| 亚洲天堂一区在线| 国产日韩精品一区二区三区| 久久99精品免费一区二区| 久久无码人妻一区二区三区午夜| 欧美一区内射最近更新| 国产无码一区二区在线| 精品一区二区三区在线成人| 国产精品va一区二区三区| 国产在线精品一区二区不卡| 另类国产精品一区二区|