python爬蟲系列之 xpath:html解析神器

一、前言

通過前面的文章,我們已經(jīng)知道了如何獲取網(wǎng)頁和下載文件,但是前面我們獲取的網(wǎng)頁都是未經(jīng)處理的,冗余的信息太多,無法進行分析和利用

這一節(jié)我們就來學習怎么從網(wǎng)頁中篩選自己需要的信息

說到信息篩選我們立馬就會想到正則表達式,不過今天我們不講正則表達式。因為對于爬蟲來講,正則表達式太復雜對新手十分不友好,而且正則表達式的容錯率差,網(wǎng)頁有稍微的改動就得重新寫匹配表達式,另外正則表達式可讀性幾乎沒有。

當然,這并不是說正則不好,只是正則不適合爬蟲和新手。其實正則是十分強大的,在后面的數(shù)據(jù)清洗里我們會用到正則。

既然正則不能用,那該用什么呢?別擔心,python為我們提供了很多解析 html頁面的庫,其中常用的有:

  • bs4中的 BeautifulSoup
  • lxml中的 etree(一個 xpath解析庫)

BeautifulSoup類似 jQuery的選擇器,通過 id、css選擇器和標簽來查找元素,xpath主要通過 html節(jié)點的嵌套關系來查找元素,和文件的路徑有點像,比如:

#獲取 id為 tab的 table標簽下所有 tr標簽
path = '//table[@id="tab"]//tr'
#和文件路徑對比
path = 'D:\Github\hexo\source\_posts'

BeautifulSoup和 xpath沒有好壞優(yōu)劣之分,講 xpath是因為個人覺得 xpath更好用一些,后面如果時間允許的話再講 BeautifulSoup。

現(xiàn)在,讓我們先從 xpath開始!

二、xpath的安裝和使用

  1. 安裝 lxml庫
    pip install lxml
    
  2. 簡單的使用

    在使用 xpath之前,先導入 etree類,對原始的 html頁面進行處理獲得一個_Element對象

    我們可以通過_Element對象來使用 xpath

    #導入 etree類
    from lxml import etree
    
    
    #作為示例的 html文本
    html = '''<div class="container">
                    <div class="row">
                        <div class="col">
                            <div class="card">
                                <div class="card-content">
                                    <a href="#123333" class="box">
                                        點擊我
                                    </a>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>'''
    
    #對 html文本進行處理 獲得一個_Element對象
    dom = etree.HTML(html)
    
    #獲取 a標簽下的文本
    a_text = dom.xpath('//div/div/div/div/div/a/text()')
    
    print(a_text)
    

    打印結果:

    result-1

    熟悉 html的朋友都知道在 html中所有的標簽都是節(jié)點。一個 html文檔是一個文檔節(jié)點,一個文檔節(jié)點包含一個節(jié)點樹,也叫做 dom樹。

    節(jié)點樹中的節(jié)點彼此擁有層級關系。

    父(parent)、子(child)和同胞(sibling)等術語用于描述這些關系。父節(jié)點擁有子節(jié)點。同級的子節(jié)點被稱為同胞(兄弟或姐妹)。

    • 在節(jié)點樹中,頂端節(jié)點被稱為根(root)
    • 每個節(jié)點都有父節(jié)點、除了根(它沒有父節(jié)點)
    • 一個節(jié)點可擁有任意數(shù)量的子
    • 同胞是擁有相同父節(jié)點的節(jié)點

    from w3school:http://www.w3school.com.cn/htmldom/dom_nodes.asp

    另外,我們把距離某個節(jié)點最近的子節(jié)點叫做它的直接子節(jié)點,如下圖所示的 body和 head就是 html的直接子節(jié)點

    dom樹 w3school

    了解了 html結構之后我們再來看 xpath的使用。

    首先,我們通過 etree.HTML( )來生成一個_Element對象,etree.HTML() 會將傳入的文本處理成一個 html文檔節(jié)點。這樣就能保證我們總是能獲得一個包含文檔節(jié)點的_Element對象。

  3. xpath語法
    • a / b :‘/’在 xpath里表示層級關系,左邊的 a是父節(jié)點,右邊的 b是子節(jié)點,這里的 b是 a的直接子節(jié)點

    • a // b:兩個 / 表示選擇所有 a節(jié)點下的 b節(jié)點(可以是直接子節(jié)點,也可以不是),在上面的例子中我們要選擇 a標簽是這樣寫的

      a_text = dom.xpath('//div/div/div/div/div/a/text()')
      #用 //
      a_text = dom.xpath('//div//a/text()')
      #如果 div標簽下有兩個 a標簽,那么這兩個 a標簽都會被選擇(注意兩個 a標簽并不一定是兄弟節(jié)點)
      #比如下面的例子中的兩個 a標簽都會被選擇 因為這兩個 a標簽都是 div的子節(jié)點
             '''<div class="container">
                      <div class="row">
                          <div class="col">
                              <div class="card">
                                 <a href="#123332" class="box">
                                          點擊我
                                  </a>
                                  <div class="card-content">
                                      <a href="#123333" class="box">
                                          點擊我
                                      </a>
                                  </div>
                              </div>
                          </div>
                      </div>
                  </div>'''
      
    • [@]:選擇具有某個屬性的節(jié)點

      • //div[@classs], //a[@x]:選擇具有 class屬性的 div節(jié)點、選擇具有 x屬性的 a節(jié)點
      • //div[@class="container"]:選擇具有 class屬性的值為 container的 div節(jié)點
    • //a[contains(text(), "點")]:選擇文本內容里含有 “點” 的 a標簽,比如上面例子中的兩個 a標簽

    • //a[contains(@id, "abc")]:選擇 id屬性里有 abc的 a標簽,如

      #這兩條 xpath規(guī)則都可以選取到例子中的兩個 a標簽
      path = '//a[contains(@href, "#123")]'
      path = '//a[contains(@href, "#1233")]'
      
    • //a[contains(@y, "x")]:選擇有 y屬性且 y屬性包含 x值的 a標簽

總結

  1. 使用 xpath之前必須先對 html文檔進行處理
  2. html dom樹中所有的對象都是節(jié)點,包括文本,所以 text()其實就是獲取某個標簽下的文本節(jié)點
  3. 通過_Element對象的 xpath方法來使用 xpath
  4. 注意?。?!_Element.xpath( path) 總是返回一個列表

有問題歡迎評論

上一篇:python爬蟲系列之 requests實戰(zhàn):用 requests庫下載網(wǎng)頁和圖片

下一篇:python爬蟲系列之 xpath實戰(zhàn):批量下載壁紙

下一篇實戰(zhàn)我們會用 requests和 xpath寫一個批量下載壁紙的爬蟲

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容