使用XPathXPath,全稱XML Path Language,即XML路徑語(yǔ)言,它是在XML語(yǔ)言中查找信息的語(yǔ)言。它最初是用來(lái)搜尋XML文檔的,但是它同樣適用于HTML文檔的搜索。 在上一篇文章中講述了正則表達(dá)式的使用方法,正則表達(dá)式的難度還是比較大的,如果不花足夠多的時(shí)間去做的話還是比較難的,所以今天就來(lái)分享比正則簡(jiǎn)單的內(nèi)容,方便大家接下來(lái)的學(xué)習(xí)。 XPath常用規(guī)則XPath的規(guī)則是非常豐富的,本篇文章無(wú)法一次性全部概括,只能為大家介紹幾個(gè)常用的規(guī)則。
準(zhǔn)備工作在使用之前得先安裝好lxml這個(gè)庫(kù),如果沒有安裝請(qǐng)參考下面的安裝方式。
案例導(dǎo)入現(xiàn)在通過(guò)實(shí)例來(lái)xpath對(duì)網(wǎng)頁(yè)解析的過(guò)程
這里首先通過(guò)lxml這個(gè)庫(kù)導(dǎo)入etree這個(gè)模塊,然后聲明一段HTML文本,調(diào)用HTML類進(jìn)行初始化,這就成功構(gòu)造了xpath對(duì)象。 細(xì)心的讀者朋友應(yīng)該會(huì)發(fā)現(xiàn)我上面的代碼片段中標(biāo)簽ul是沒有閉合的,但是運(yùn)行之后你會(huì)發(fā)現(xiàn)運(yùn)行結(jié)果是閉合的,并且還自動(dòng)添加了html和body標(biāo)簽。 這是因?yàn)槲覀冋{(diào)用了tostring( )方法幫助我們將HTML文本進(jìn)行修正,但是要注意的是tostring( )方法 當(dāng)然,etree這個(gè)模塊也可以直接讀取文本文件進(jìn)行解析,具體代碼如下所示:
其中文件test.html的內(nèi)容就是上面示例的HTML代碼。 獲取所有的節(jié)點(diǎn)我們一般會(huì)使用 // 開頭的Xpath規(guī)則來(lái)選取所有符合要求的節(jié)點(diǎn),假如我需要獲取所有的節(jié)點(diǎn),示例代碼如下所示:
首先對(duì)上面的代碼做簡(jiǎn)單的說(shuō)明,這里的 * 代表匹配全部,所以所有的節(jié)點(diǎn)都會(huì)獲取到,返回值是一個(gè)列表。 每個(gè)元素是Element類型,其中后面跟的就是節(jié)點(diǎn)的名稱。 運(yùn)行結(jié)果如下所示:
從上面的運(yùn)行結(jié)果你會(huì)發(fā)現(xiàn),html、body、div、ul、li等等節(jié)點(diǎn)。 獲取指定節(jié)點(diǎn)例如,在這里我要獲取到所有的li節(jié)點(diǎn),那該怎么辦呢?其實(shí)很簡(jiǎn)單,具體代碼示例如下所示:
通過(guò)上面的幾個(gè)例子,不知道大家有沒有明白節(jié)點(diǎn)的含義。 其實(shí)節(jié)點(diǎn)的含義你可以理解為當(dāng)前的html文檔開始的地方。 如果上面的代碼你修改一段,變成這樣:
運(yùn)行之后你會(huì)發(fā)現(xiàn)列表是空的,因?yàn)樵撐臋n的的子節(jié)點(diǎn)中沒有 li 這個(gè)節(jié)點(diǎn),li 是該文檔的子孫節(jié)點(diǎn),而該文檔的子節(jié)點(diǎn)是html。 所以,你將代碼這樣修改:
運(yùn)行之后你會(huì)驚喜的發(fā)現(xiàn),成功獲取到了html節(jié)點(diǎn)。 子節(jié)點(diǎn)與子孫節(jié)點(diǎn)通過(guò)/或//即可查好元素的子節(jié)點(diǎn)或者是子孫節(jié)點(diǎn),假如你想要選擇 li 節(jié)點(diǎn)下的所有 a 節(jié)點(diǎn)可以這樣實(shí)現(xiàn),具體代碼如下所示:
先對(duì)上面的代碼做簡(jiǎn)要的說(shuō)明://li表示獲取所有的li節(jié)點(diǎn),/a表示獲取 li 節(jié)點(diǎn)下的子節(jié)點(diǎn) a 。 或者也可以這樣寫,你可以先獲取到所有的 ul 節(jié)點(diǎn),再獲取 ul 節(jié)點(diǎn)下的所有子孫節(jié)點(diǎn) a 節(jié)點(diǎn)。 具體示例代碼如下所示:
運(yùn)行上面的代碼你會(huì)發(fā)現(xiàn)結(jié)果是相同的。 獲取父節(jié)點(diǎn)通過(guò)上面的幾個(gè)例子,想必應(yīng)該知道何為子節(jié)點(diǎn)與子孫節(jié)點(diǎn)。那么如何尋找父節(jié)點(diǎn)呢?這里可以通過(guò) .. 來(lái)實(shí)現(xiàn)。 比如,我現(xiàn)在要選中href屬性為link4.html的a節(jié)點(diǎn),然后再獲取其父節(jié)點(diǎn),再獲取其class屬性??粗鴥?nèi)容好多,那就要一個(gè)一個(gè)來(lái),不要著急。 具體代碼示例如下所示:
運(yùn)行結(jié)果
屬性的匹配在選取數(shù)據(jù)的時(shí)候,可以使用@符號(hào)進(jìn)行屬性的過(guò)濾,比如:這里通過(guò)選取 li 標(biāo)簽屬性class為item-0的節(jié)點(diǎn),可以這樣實(shí)現(xiàn):
你可以試著運(yùn)行上面的代碼,你會(huì)發(fā)現(xiàn)匹配到了兩個(gè)正確的結(jié)果。 文本獲取在整個(gè)HTML文檔中肯定會(huì)有很多的文本內(nèi)容,有些恰恰是我們需要的,那么應(yīng)該如何獲取這些文本內(nèi)容呢? 接下來(lái)可以嘗試使用text( )方法獲取節(jié)點(diǎn)中的文本。 具體代碼實(shí)例如下所示:
試著運(yùn)行上面的代碼,你會(huì)發(fā)現(xiàn),已經(jīng)獲取到了所有class屬性為item-0的 li 節(jié)點(diǎn)下的文本。 獲取標(biāo)簽屬性值在編寫爬蟲的過(guò)程中,很多時(shí)候我們需要的數(shù)據(jù)可能是屬性值,那就要學(xué)會(huì)如何來(lái)獲取我們想要的屬性值了。 例如,我想要獲取 li 節(jié)點(diǎn)下的a節(jié)點(diǎn)的所有href屬性,具體代碼示例如下所示:
通過(guò)@href就獲取到了該節(jié)點(diǎn)的href屬性值,當(dāng)然,它們都是以列表的形式返回。 屬性多值的匹配在編寫前端代碼的時(shí)候,有些節(jié)點(diǎn)為了方便可能就會(huì)存在多個(gè)值,那么就要使用contains函數(shù)了,例如:
要是你說(shuō)我怎么記得住這些函數(shù),那好,還可以這樣寫。 具體代碼示例如下:
看出區(qū)別了嗎? 運(yùn)行上面的兩段代碼,你會(huì)發(fā)現(xiàn)結(jié)果是一樣的。 多屬性匹配另外,我們寫寫爬蟲的時(shí)候會(huì)遇到另一種情況,那就是在一個(gè)標(biāo)簽內(nèi)存在多個(gè)屬性。那此時(shí)可以用and操作符來(lái)連接 具體代碼示例如下所示:
xpath運(yùn)算符的簡(jiǎn)單介紹從上面的示例你應(yīng)該知道了,and是xpath的運(yùn)算符,xpath的運(yùn)算符也是比較多的,那么接下來(lái)對(duì)xpath運(yùn)算符做簡(jiǎn)單的介紹。
按序選擇有時(shí)候,我們編寫爬蟲的時(shí)候可能會(huì)匹配到幾個(gè)相同的 li 節(jié)點(diǎn),但是,我只需要第一個(gè)或者最后一個(gè)就可以了。那這時(shí)該怎么樣處理那? 這時(shí)可以通過(guò)索引的方式,傳入指定的索引,獲取指定節(jié)點(diǎn)。 具體代碼示例如下所示:
上述內(nèi)容所描述的是xpath的在爬蟲應(yīng)用中常見使用方法,如果各位小伙伴想要繼續(xù)深入學(xué)習(xí)的話,可以參考w3c進(jìn)行學(xué)習(xí),網(wǎng)址如下:
實(shí)戰(zhàn)上面的內(nèi)容是描述xpath的使用語(yǔ)法,建議大家要花一個(gè)小時(shí)左右的時(shí)間去練習(xí)。 那么接下來(lái)就帶大家進(jìn)入實(shí)戰(zhàn)演練了,乘熱打鐵是最好的學(xué)習(xí)方式。 今天我?guī)?lái)的內(nèi)容就是爬取 準(zhǔn)備工作工欲善其事,必先利其器。玩爬蟲也是同樣的道理。 首先,安裝好兩個(gè)庫(kù):lxml與requests。
需求分析爬取的網(wǎng)址: 抓包分析首先打開開發(fā)者工具,隨便點(diǎn)擊一張圖片進(jìn)入它的高清大圖,點(diǎn)擊network進(jìn)行抓包,在點(diǎn)擊圖片的下載按鈕。 點(diǎn)擊下載按鈕之后,你會(huì)發(fā)現(xiàn),瀏覽器向圖中的網(wǎng)址發(fā)起了請(qǐng)求,點(diǎn)擊進(jìn)去之后發(fā)現(xiàn)這個(gè)就是高清圖片的鏈接地址。 從而我們的第一個(gè)需求就是獲取所有圖片的鏈接地址。 獲取圖片鏈接為什么要獲取圖片鏈接呢? 首先,你思考一下,每一張圖片你都要點(diǎn)擊下載按鈕來(lái)將圖片保存到本地嗎?如果你不懂爬蟲那當(dāng)然沒有辦法了。但是,我們懂爬蟲的人還會(huì)這么干嗎? 既然每一次點(diǎn)擊下載按鈕,瀏覽器都是向?qū)?yīng)的高清大圖發(fā)起請(qǐng)求,那么也就是說(shuō)我們可以獲取到所有的圖片鏈接,然后利用Python模擬瀏覽器向這些鏈接發(fā)起請(qǐng)求,即可下載這些圖片。 鏈接如下:
關(guān)于翻頁(yè)打開網(wǎng)頁(yè)之后,你會(huì)發(fā)現(xiàn)起碼有100頁(yè)的圖片。那這100頁(yè)的圖片怎么樣獲取呢? 很簡(jiǎn)單,依然還是先分析每一頁(yè)的URL地址,看看有沒什么變化規(guī)律。
其實(shí)看到上面的URL變化之后,我想你也應(yīng)該明白了變化的規(guī)律了吧。 功能實(shí)現(xiàn)構(gòu)造每一頁(yè)的鏈接其實(shí)就是實(shí)現(xiàn)簡(jiǎn)單的翻頁(yè)功能。 具體代碼示例如下所示:
上面代碼的功能是構(gòu)造每一頁(yè)的鏈接。將鏈接保存在page_url中。 獲取每一頁(yè)中的圖片鏈接在上圖中你會(huì)發(fā)現(xiàn),圖片的鏈接就藏在了 但是細(xì)心的朋友就會(huì)發(fā)現(xiàn),這個(gè)鏈接和我們最開始抓包的鏈接是不一樣的,到底哪里不一樣呢? 我們來(lái)具體看看
發(fā)現(xiàn)了嗎?分辨率是不一樣的。其他都相同的,那只要將分辨率替換掉就可以了呀。 具體代碼如下所示:
上面的代碼是獲取每一頁(yè)的圖片鏈接,將鏈接保存在img_urls中。 保存圖片
保存圖片的代碼還是比較簡(jiǎn)單的,可以將獲取到的所有圖片鏈接作為參數(shù)傳進(jìn)來(lái),進(jìn)行逐個(gè)訪問(wèn),即可。 文章來(lái)源:https://www./blog-lyU3E5QA6g.htm |
|
來(lái)自: 昵稱73595512 > 《Python》