Datawhale-爬蟲-Task4(學習xpath)

TNTZS666發表於2019-03-04

XPath簡介

XPath 是一門在 XML 文件中查詢資訊的語言。XPath 用於在 XML 文件中通過元素和屬性進行導航。
什麼是XPath?

  • XPath 使用路徑表示式在 XML 文件中進行導航
    • XPath 使用路徑表示式來選取 XML 文件中的節點或者節點集。這些路徑表示式和我們在常規的電腦檔案系統中看到的表示式非常相似。
  • XPath 包含一個標準函式庫
    • XPath 含有超過 100 個內建的函式。這些函式用於字串值、數值、日期和時間比較、節點和 QName 處理、序列處理、邏輯值等等
  • XPath 是 XSLT 中的主要元素
    • XPath 是 XSLT 標準中的主要元素。如果沒有 XPath 方面的知識,您就無法建立 XSLT 文件。
  • XPath 是一個 W3C 標準
    • XPath 於 1999 年 11 月 16 日 成為 W3C 標準。
      XPath 被設計為供 XSLT、XPointer 以及其他 XML 解析軟體使用。

XPath節點:
在 XPath 中,有七種型別的節點:元素、屬性、文字、名稱空間、處理指令、註釋以及文件節點(或稱為根節點)
具體介紹見W3school:W3school之XPath節點

XPath語法:
XPath 使用路徑表示式來選取 XML 文件中的節點或節點集。節點是通過沿著路徑 (path) 或者步 (steps) 來選取的。
下表給出最有用的路徑表示式:

表示式 描述
nodename 選取此節點的所有子節點。
/ 從根節點選取。
// 從匹配選擇的當前節點選擇文件中的節點,而不考慮它們的位置。
選取當前節點。
.. 選取當前節點的父節點。
@ 選取屬性。

具體例項及用法見:W3school之XPath語法

lxml簡介

lxml是 Python 處理 xml 文件的一個庫,速度快,易程式設計。

在lxml中,只有Element,Element有子Element,構成一棵樹。具體關於Element屬性介紹:lxml教程

例項:使用xpath提取丁香園論壇的回覆內容。

實現程式碼:

import requests
from lxml import etree
from bs4 import BeautifulSoup as bs

def get_html():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36'
    }
    url = 'http://www.dxy.cn/bbs/thread/626626'
    try:
        html = requests.get(url,headers = headers)
        if html.status_code == 200:
            return html.text
    except:
        pass

def get_item(html):
    topic_con = etree.HTML(html)
    #result = etree.tostring(topic_con)
    #print(result.decode('utf-8'))
    content = []
    user_id = topic_con.xpath('//div[@class="auth"]/a/text()')
    #print(user_id)
    #content = topic_con.xpath('//td[@class="postbody"]/text()|//td[@class="postbody"]/a/text()')
    for i in range(len(user_id)):
        content_test = topic_con.xpath(f'//*[@id="post_{i+1}"]/table/tbody/tr/td[2]/div[2]/div/table/tbody/tr/td//text()')
        content_test = "".join(content_test)
        content.append(content_test.replace("\n","").replace("\t",""))
    #print(len(content))
    #print(len(fixed))
    zipped = zip(user_id,content)
    for i in zipped:
         print(i)

def main():
    html = get_html()
    info = get_item(html)

if __name__ == '__main__':
    main()

從程式碼中我們不難發現,xpath和昨天beautiful soup 總體框架都是類似的,只是在獲取網頁的時候xpath改用etree去解析。
注意:由於xpath爬取下來的網頁資料以列表形式存放,所以當我們分別爬取下使用者名稱和其發帖的內容的時候,是存放在兩個不同的列表中,一開始我的xpath語句寫的有問題,雖然完整的爬取了所需要的資料,但是content列表的len缺是11,這意味著我不能用zip函式將使用者名稱和其發的帖子內容一一對應。最後在求助群裡大佬,特別感謝大鵬哥的助攻,將我的xpath語句改了,最後成功匹配。
執行結果:
在這裡插入圖片描述

相關文章