python网络爬虫系列(六)——数据提取 lxml模块
一、數據提取-lxml模塊
知識點
- 了解 lxml模塊和xpath語法的關系
- 了解 lxml模塊的使用場景
- 了解 lxml模塊的安裝
- 了解 谷歌瀏覽器xpath helper插件的安裝和使用
- 掌握 xpath語法-基礎節點選擇語法
- 掌握 xpath語法-節點修飾語法
- 掌握 xpath語法-其他常用語法
- 掌握 lxml模塊中使用xpath語法定位元素提取屬性值或文本內容
- 掌握 lxml模塊中etree.tostring函數的使用
1. 了解 lxml模塊和xpath語法
對html或xml形式的文本提取特定的內容,就需要我們掌握lxml模塊的使用和xpath語法。
- lxml模塊可以利用XPath規則語法,來快速的定位HTML\XML 文檔中特定元素以及獲取節點信息(文本內容、屬性值)
- XPath (XML Path Language) 是一門在 HTML\XML 文檔中查找信息的語言,可用來在 HTML\XML 文檔中對元素和屬性進行遍歷。
- W3School官方文檔:http://www.w3school.com.cn/xpath/index.asp
- 提取xml、html中的數據需要lxml模塊和xpath語法配合使用
知識點:了解 lxml模塊和xpath語法
2. 谷歌瀏覽器xpath helper插件的安裝和使用
要想利用lxml模塊提取數據,需要我們掌握xpath語法規則。接下來我們就來了解一下xpath helper插件,它可以幫助我們練習xpath語法
2.1 谷歌瀏覽器xpath helper插件的作用
在谷歌瀏覽器中對當前頁面測試xpath語法規則
2.2 谷歌瀏覽器xpath helper插件的安裝和使用
我們以windos為例進行xpath helper的安裝
2.2.1 xpath helper插件的安裝
下載Chrome插件 XPath Helper
-
可以在chrome應用商城進行下載,如果無法下載,也可以從下面的鏈接進行下載
-
下載地址:https://pan.baidu.com/s/1UM94dcwgus4SgECuoJ-Jcg 密碼:337b
把文件的后綴名crx改為rar,然后解壓到同名文件夾中
把解壓后的文件夾拖入到已經開啟開發者模式的chrome瀏覽器擴展程序界面
重啟瀏覽器后,訪問url之后在頁面中點擊xpath圖標,就可以使用了
如果是linux或macOS操作系統,無需操作上述的步驟2,直接將crx文件拖入已經開啟開發者模式的chrome瀏覽器擴展程序界面
知識點:了解 谷歌瀏覽器xpath helper插件的安裝和使用
3. xpath的節點關系
學習xpath語法需要先了解xpath中的節點關系
3.1 xpath中的節點是什么
每個html、xml的標簽我們都稱之為節點,其中最頂層的節點稱為根節點。我們以xml為例,html也是一樣的
3.2 xpath中節點的關系
author是title的第一個兄弟節點
4. xpath語法-基礎節點選擇語法
4.1 xpath定位節點以及提取屬性或文本內容的語法
| nodename | 選中該元素。 |
| / | 從根節點選取、或者是元素和元素間的過渡。 |
| // | 從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。 |
| . | 選取當前節點。 |
| … | 選取當前節點的父節點。 |
| @ | 選取屬性。 |
| text() | 選取文本。 |
4.2 語法練習
接下來我們通過itcast的頁面來練習上述語法:http://www.itcast.cn/
- 選擇所有的h2下的文本
- //h2/text()
- 獲取所有的a標簽的href
- //a/@href
- 獲取html下的head下的title的文本
- /html/head/title/text()
- 獲取html下的head下的link標簽的href
- /html/head/link/@href
知識點:掌握 xpath語法-選取節點以及提取屬性或文本內容的語法
5. xpath語法-節點修飾語法
可以根據標簽的屬性值、下標等來獲取特定的節點
5.1 節點修飾語法
| //title[@lang=“eng”] | 選擇lang屬性值為eng的所有title元素 |
| /bookstore/book[1] | 選取屬于 bookstore 子元素的第一個 book 元素。 |
| /bookstore/book[last()] | 選取屬于 bookstore 子元素的最后一個 book 元素。 |
| /bookstore/book[last()-1] | 選取屬于 bookstore 子元素的倒數第二個 book 元素。 |
| /bookstore/book[position()>1] | 選擇bookstore下面的book元素,從第二個開始選擇 |
| //book/title[text()=‘Harry Potter’] | 選擇所有book下的title元素,僅僅選擇文本為Harry Potter的title元素 |
| /bookstore/book[price>35.00]/title | 選取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值須大于 35.00。 |
5.2 關于xpath的下標
- 在xpath中,第一個元素的位置是1
- 最后一個元素的位置是last()
- 倒數第二個是last()-1
5.3 語法練習
從itcast的頁面中,選擇所有學科的名稱、第一個學科的鏈接、最后一個學科的鏈接:http://www.itcast.cn/
- 所有的學科的名稱
- //div[@class="nav_txt"]//a[@class="a_gd"]
- 第一個學科的鏈接
- //div[@class="nav_txt"]/ul/li[1]/a/@href
- 最后一個學科的鏈接
- //div[@class="nav_txt"]/ul/li[last()]/a/@href
知識點:掌握 xpath語法-選取特定節點的語法
6. xpath語法-其他常用節點選擇語法
可以通過通配符來選取未知的html、xml的元素
6.1 選取未知節點的語法
| * | 匹配任何元素節點。 |
| node() | 匹配任何類型的節點。 |
6.2 語法練習
從itcast的頁面中 http://www.itcast.cn/ ,選中全部的標簽、全部的屬性
- 全部的標簽
- //*
- 全部的屬性
- //node()
知識點:掌握 xpath語法-選取位置節點的語法
7. lxml模塊的安裝與使用示例
lxml模塊是一個第三方模塊,安裝之后使用
7.1 lxml模塊的安裝
對發送請求獲取的xml或html形式的響應內容進行提取
pip/pip3 install lxml知識點:了解 lxml模塊的安裝
7.2 爬蟲對html提取的內容
- 提取標簽中的文本內容
- 提取標簽中的屬性的值
- 比如,提取a標簽中href屬性的值,獲取url,進而繼續發起請求
7.3 lxml模塊的使用
導入lxml 的 etree 庫
from lxml import etree
利用etree.HTML,將html字符串(bytes類型或str類型)轉化為Element對象,Element對象具有xpath的方法,返回結果的列表
html = etree.HTML(text) ret_list = html.xpath("xpath語法規則字符串")xpath方法返回列表的三種情況
- 返回空列表:根據xpath語法規則字符串,沒有定位到任何元素
- 返回由字符串構成的列表:xpath字符串規則匹配的一定是文本內容或某屬性的值
- 返回由Element對象構成的列表:xpath規則字符串匹配的是標簽,列表中的Element對象可以繼續進行xpath
7.4 lxml模塊使用示例
運行下面的代碼,查看打印的結果
from lxml import etree text = ''' <div> <ul> <li class="item-1"><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> '''html = etree.HTML(text)#獲取href的列表和title的列表 href_list = html.xpath("//li[@class='item-1']/a/@href") title_list = html.xpath("//li[@class='item-1']/a/text()")#組裝成字典 for href in href_list:item = {}item["href"] = hrefitem["title"] = title_list[href_list.index(href)]print(item)8 練習
將下面的html文檔字符串中,將每個class為item-1的li標簽作為1條新聞數據。提取a標簽的文本內容以及鏈接,組裝成一個字典。
text = ''' <div> <ul> <li class="item-1"><a>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> '''-
注意:
-
先分組,再提取數據,可以避免數據的錯亂
-
對于空值要進行判斷
-
-
參考代碼
from lxml import etree text = '''
- first item
- second item
- third item
- fourth item
- a href="link5.html">fifth item
#根據li標簽進行分組
html = etree.HTML(text)
li_list = html.xpath("//li[@class=‘item-1’]")
#在每一組中繼續進行數據的提取
for li in li_list:
item = {}
item[“href”] = li.xpath("./a/@href")[0] if len(li.xpath("./a/@href"))>0 else None
item[“title”] = li.xpath("./a/text()")[0] if len(li.xpath("./a/text()"))>0 else None
print(item)
10.1 現象和結論
打印結果和原來相比:
結論:
-
lxml.etree.HTML(html_str)可以自動補全標簽
-
lxml.etree.tostring函數可以將轉換為Element對象再轉換回html字符串
-
爬蟲如果使用lxml來提取數據,應該以lxml.etree.tostring的返回結果作為提取數據的依據
知識點:掌握 lxml模塊中etree.tostring函數的使用
item
- fourth item
- fifth item
- ```
結論:
-
lxml.etree.HTML(html_str)可以自動補全標簽
-
lxml.etree.tostring函數可以將轉換為Element對象再轉換回html字符串
-
爬蟲如果使用lxml來提取數據,應該以lxml.etree.tostring的返回結果作為提取數據的依據
知識點:掌握 lxml模塊中etree.tostring函數的使用
爬蟲案例:爬取百度貼吧的數據
基本思路:
-
- 初始化url和headers
- 向目標url發送get請求
- 解析響應回來的數據
a. 通過element對象的xpath()函數提取title和link中的數據
b. 獲取下一頁按鈕的url,用來進行翻頁操作 - 實現循環翻頁
- 保存爬取到的數據 import requests from lxml import etreeclass Tieba(object):def __init__(self,name):self.url = "https://tieba.baidu.com/f?ie=utf-8&kw={}".format(name)self.headers = {'User-agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'# 'User-agent' :'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1'}# 獲取響應中的數據def get_data(self,url):# 發送get請求response = requests.get(url,headers=self.headers)with open("temp.html","wb")as f:f.write(response.content)return response.content # 返回響應的內容# 解析數據def parse_data(self,data):# 注意:在高端的瀏覽器發送的請求返回的響應中,部分html代碼被注釋掉了,# 可以采取以下兩種方式處理:# 1、直接把header里面的User-agent的值換成低端瀏覽器的# 2、自己手動把原本代碼中的注釋符號給去掉,采用replace()函數來實現data = data.decode().replace("<!--","").replace("-->","")# 創建element對象,因為只有element對象才有xpath方法,有xpath方法才能提取到我們想要的數據(a標簽)html = etree.HTML(data)el_list = html.xpath("//li[@class=' j_thread_list clearfix']/div/div[2]/div[1]/div[1]/a")print(len(el_list))# 定義一個列表來存放最終爬取到的所有數據data_list = []# 循環遍歷每一個a標簽(每個a標簽都是一個element對象),所以也具有xpath方法,可以通過這種方法將title和link的數值都提取出來for el in el_list:temp = {} # 定義一個字典,用來存放每一個a標簽對應的title和linktemp['title'] = el.xpath("./text()")[0]temp['link'] = 'https://tieba.baidu.com' + el.xpath("./@href")[0]data_list.append(temp) # 最后再把每一個temp字典添加到data_list列表中保存# 上面的for循環結束后,說明當前url(頁)的所有數據已經爬取完成了,接下來需要進行翻頁操作,也就是需要獲取新的url(頁)繼續爬取數據# 循環翻頁,獲取下一頁的urltry:next_url = 'https:' + html.xpath('//a[contains(text(),"下一頁")]/@href')[0]except:next_url = Nonereturn data_list,next_url# 保存數據:這里采用遍歷data_list打印的方式來查看是否成功爬取到了想要的數據def save_data(self,data_list):for data in data_list:print(data)def run(self):# url# headersnext_url = self.urlwhile True:# 發送請求,獲取響應data = self.get_data(next_url)# 從響應中提取數據(數據和翻頁用的url)data_list , next_url = self.parse_data(data)self.save_data(data_list)print(next_url)# 判斷是否終結,當next_url的值為None時,說明已經無法獲取到下一頁按鈕的url,parse_data()方法中except捕獲到了異常,此時應該結束循環if next_url == None:breakif __name__ == '__main__':tieba = Tieba("李毅")tieba.run()
總結
以上是生活随笔為你收集整理的python网络爬虫系列(六)——数据提取 lxml模块的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三、解决ie缓存问题
- 下一篇: python网络爬虫系列(九)——打码平