爬蟲教程---第三章:信息提取之XPath

第三章:信息提取

雖然學了前面兩章可以自己爬取網頁內容了,但這些內容夾雜了很多html代碼啊,不相關的信息啊等等。

那本章就是解決一些手段對想要信息進行精準的提取,進而使爬取下來的信息都是我們想要的。

提取信息的技術有三種:XPathBeautifulSoup正則表達式

3.1 XPath

什麼是 XPath ?(XML Path Language)

xpath是一門在XML和HTML文檔中查找信息的語言,可用來在XML和HTML文檔中對元素和屬性進行遍歷。

工欲善其事,必先利其器。當我們掌握了XPath語法時,可以利用瀏覽器自帶的插件來幫我們現在瀏覽器中進行語法測試。

  • Goolege瀏覽器: XPath Helper
  • 火狐瀏覽器:try XPath

來看一下基本用法:(我的是谷歌瀏覽器,火狐的操作也類似)
在這裏插入圖片描述


3.1.1 XPath語法:

  1. 選取節點:使用路徑表達式來選取XML文件中的節點或節點集。

    表達式 描述 實例 結果
    nodename (節點名字)選取此節點的所有子節點 div 選取div下的所有子節點
    / 選擇某節點下的直接指定子節點 div/p div下的子p節點
    // 查找某節點下的所有指定子孫節點 /div//p div下的所有子孫p節點
    @ 選取某個節點的屬性 //div[@class=‘j’] 選取所有擁有 class=“j” 的屬性的div
  2. 謂詞:使用謂詞來過濾一些節點,比如上面的 class=“j”

    • 格式:[謂詞]

    • 路徑表達式 描述
      /body/div[1] body下的第一個直接div元素(下標從1開始)
      /body/div[last()] 最後一個div
      /body/div[position()< 3] 前面兩個的div
      //div[contains(@class,‘f1’)] 模糊匹配:class屬性中含有f1的div
      //div[@class=‘job’ and @id=‘ok’] class=job並且id=ok的div
      //div[name] 所有擁有name屬性的div
  3. 通配符:

    通配符 描述 實例 結果
    * 匹配任意節點 /nook/* 選取nook下所有的子元素
    @* 匹配節點的任何屬性 //book[@*] 選取所有帶有屬性的book元素
  4. 選取多個路徑: |

    • 同時獲取class=‘c’的div和dd元素
      //div[@class='c'] | //dd
      

3.1.2 lxml庫

lxml是用C語言編寫的HTML/XML解析器,主要功能是如何解析和提取HTML/XML數據

我們可以利用之前學習的XPath語法,來快速定位特定元素以及節點。

使用前需要先安裝:pip install lxml

基本使用的方式有兩種:一個是對字符串進行解析,另一個是對HTML文件進行解析。


解析HTML文件

運用場景:當你需要對一個HTML文件進行解析或提取一些信息的時候。

聲明:爲了方便演示,下面我將假設我在D://TEST.html路徑下的內容都可以滿足要查找的條件

# 第一步:從lxml中導入etree。
# 注意,由於lxml是用c寫的所以etree會沒有提示
from lxml import etree

# 指定HTML解析器
parser = etree.HTMLParser()
# 解析HTML文件
html = etree.parse('D://TEST.html',parser) # 返回的是一個Element對象

# 1、獲取所有tr標籤
trs = html.xpath("//tr")
for tr in trs:
    print(etree.tostring(tr,encoding='utf-8').decode('utf-8'))
    
#2、獲取第2個tr標籤
tr = html.xpath("//tr[2]")[0]  # xpath返回的永遠是一個列表
print(etree.tostring(tr,encoding='utf-8').decode('utf-8'))

#3、獲取所有class等於even的tr標籤
trs = html.xpath("//tr[@class="even"]")

#4、獲取所有a標籤的href屬性(注意)
alist = html.xpath("//tr/@href")
for a in alist:
    print("a")

#5、獲取所有職位信息
trs = html.xpath("//tr[position()>1]")
for tr in trs:
    # “.” 表示獲取這個標籤下的子孫元素。
    href = tr.xpath(".//a/@href")[0]
    print(href)
    text = tr.xpath(".//a/text()")  # 獲取a標籤下的文本內容

etree.HTMLParser() 是一種解析器方式,如果 **etree.parse**不指定解析器則默認使用的是XML解析器。

text() 表示提取該元素包裹的直接內容,比如<p>aaa</p> 當你使用p/text() 時獲取到的內容爲aaa。在比如<p><div>aaa</div></p>此時如果你使用 p/text() 的方法則獲取不到內容,爲什麼呢?因爲text()獲取的是該標籤下的內容,而aaa在div標籤下,所以獲取不到。

元素 /@ 屬性名 的理解:表示取出該元素的屬性名對應的屬性值。區別於 /元素[@屬性名=‘屬性值’]

解析字符串

運用場景:當從網上爬取到信息時,需要對這些信息進行過濾,而這些爬取下來的信息就是字符串,所以我們可以利用lxml來解析它。

那來個小案例吧,這個小案例需要先把上面的5個知識點搞懂,理解起來纔會比較容易。

案例:利用lxml爬取快代理的IP地址。

# 第一步:從lxml中導入etree。
from lxml import etree
import requests

# 要爬取的url,這裏只爬取第一頁內容
Proxy_url = "https://www.kuaidaili.com/free/inha/1/"
pro = ""  # 用來存放拼接好的IP地址
PROXY = []  # 存放爬取下來的IP地址的列表

# 獲取爬取內容
response = requests.get(Proxy_url)
text = response.text

# 將爬取的字符串放進lxml中解析
html = etree.HTML(text)  # 返回的也是一個Element對象

# 利用xpath語法查找IP地址內容所在的元素
trs = html.xpath("//table[@class='table table-bordered table-striped']//tr")[1:]

# 把IP、端口號一個個提取出來並拼接在一起形成IP地址
for tr in trs:
	# 提取IP
    IP = tr.xpath("./td[@data-title='IP']/text()")[0]
    # 提取端口號
    PORT = tr.xpath("./td[@data-title='PORT']/text()")[0]
    # 拼接成url
    pro = "HTTP://" + IP + ":" + PORT
    PROXY.append(pro)
print(PROXY)

trs = html.xpath("//table[@class='table table-bordered table-striped']//tr")[1:] 這句代碼的意思是選取class爲table table-bordered table-stripedtable 下面除去第一個的所有tr。因爲你檢查元素後會發現,第一個tr是沒有用的,所以要除去第一個。

tr.xpath("./td[@data-title='IP']/text()")[0] 表示提取當前的**tr標籤下的 含有data-title='IP'td** 下面的直接內容,又因爲xpath返回的是一個列表,所以需要[0]

小結:

  1. 解析html字符串使用etree.HTML(string)解析,此方法默認使用HTML解析器
  2. 解析html文件使用etree.parse(‘文件路徑’)解析,此方法默認使用XML解析器
  3. xpath返回的永遠是一個列表
  4. etreelxml庫中
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章