(数据科学学习手札61)xpath进阶用法
一、簡介
xpath作為對網(wǎng)頁、對xml文件進(jìn)行定位的工具,速度快,語法簡潔明了,在網(wǎng)絡(luò)爬蟲解析內(nèi)容的過程中起到很大的作用,除了xpath的基礎(chǔ)用法之外(可參考我之前寫的(數(shù)據(jù)科學(xué)學(xué)習(xí)手札50)基于Python的網(wǎng)絡(luò)數(shù)據(jù)采集-selenium篇),xpath中還存在著非常之多的進(jìn)階用法,本文將對筆者日常使用中積累的xpath進(jìn)階用法進(jìn)行總結(jié)并舉例說明:
?
二、xpath進(jìn)階用法
本文以http://quotes.toscrape.com/示例頁面,首先抓取網(wǎng)頁源碼并利用etree解析:
import requestsfrom lxml import etreehtml = requests.get('http://quotes.toscrape.com/') tree = etree.HTML(html.text)
2.1 獲取某一節(jié)點的上一級節(jié)點
在xpath中/..表示向上一級,這里我們用xpath按照下圖中的路徑提取a標(biāo)簽里的內(nèi)容:
'''提取頁面中符合下列位置規(guī)則的所有keyword''' tree.xpath("//meta[@class='keywords']/../a[@class='tag']/text()")
? 或者利用parent來向上一級跳轉(zhuǎn),效果是一樣的:
'''提取頁面中符合下列位置規(guī)則的所有keyword''' tree.xpath("//meta[@class='keywords']/parent::*/a[@class='tag']/text()")2.2 定位指定屬性以某個特定字符開頭的標(biāo)簽
在xpath中有函數(shù)starts-with(屬性名稱,開始字符),可用于定位指定屬性以某個特定字符開頭的標(biāo)簽,如下例,實現(xiàn)與2.1中相同功能:
'''提取href屬性以/tag開頭的a標(biāo)簽內(nèi)容''' tree.xpath("//a[starts-with(@href,'/tag')]/text()")
2.3 定位指定屬性值包含特定字符片段的標(biāo)簽
在xpath中函數(shù)contains(屬性名稱,包含字符)可用于定位指定屬性值包含特定字符片段的標(biāo)簽內(nèi)容,比如我們想要找到所有text()內(nèi)容中帶有know的名人名言,就可以像下面這樣做:
'''提取text()內(nèi)容包含know的span標(biāo)簽對應(yīng)的text()內(nèi)容''' tree.xpath("//span[contains(text(),'know')]/text()")?
2.4 匹配具有某屬性的所有標(biāo)簽
比如說我們想獲取頁面中所有的href超鏈接,就可以用下面的方式:
'''獲取整個頁面內(nèi)所有href屬性''' tree.xpath("//@href")?
2.5 同時定位多個內(nèi)容
比如說我們想在一行代碼里同時取得兩種不同的規(guī)則下匹配的內(nèi)容,可以在xpath語句中將不同的多個xpath語句用|連接起來,最終返回的結(jié)果在同一個列表里,所以使用這種語法時需要考慮取得的內(nèi)容是否適合放在一起:
?
2.6 選取指定節(jié)點下所有子元素
有時候我們想要快捷的獲取某一節(jié)點下一級所有標(biāo)簽的某一屬性內(nèi)容,可以使用child來表示下一級節(jié)點:
'''選取class為quote的div節(jié)點下所有span子節(jié)點的text()內(nèi)容''' tree.xpath("//div[@class='quote']/child::span/text()")? 當(dāng)不指定標(biāo)簽名稱而使用*代替時,代表匹配所有子節(jié)點:
'''選取class為quote的div節(jié)點下所有子節(jié)點的text()內(nèi)容''' tree.xpath("//div[@class='quote']/child::*/text()")?
2.7 選取某一節(jié)點所有的屬性值
有時候我們想要獲取滿足條件的節(jié)點下所有的屬性值:
'''選取class為quote的div標(biāo)簽下所有的屬性值''' tree.xpath("//div[@class='quote']/attribute::*")
也可以指定要提取的具體屬性值,如這里我們只提取href,只需要將*替換成href即可:
'''選取class為tag的a標(biāo)簽下所有的href屬性值''' tree.xpath("//a[@class='tag']/attribute::href")?
2.8 定位某一節(jié)點的祖先節(jié)點
比如我們想要獲取class為keywords的meta標(biāo)簽之上所有標(biāo)簽的class屬性內(nèi)容,可以像下面這樣:
tree.xpath("//meta[@class='keywords']/ancestor::*/@class")? 若想同時包含所有祖先節(jié)點及自己本身,則可使用ancestor-or-self:
tree.xpath("//meta[@class='keywords']/ancestor-or-self::*/text()")?
2.9 定位某一節(jié)點的后代節(jié)點
類似2.8,只不過這里我們來定位某一節(jié)點之下的所有后代節(jié)點,使用descendant:
'''獲取class為tags的標(biāo)簽下所有后代節(jié)點中a標(biāo)簽的href信息''' tree.xpath("//div[@class='tags']/descendant::a/@href")?2.10 條件與或非
在xpath中使用邏輯運算來定位的方法如下:
與:
'''定位class為text且itemprop為text的span標(biāo)簽''' tree.xpath("//span[@class='text' and @itemprop='text']/text()")或:
tree.xpath("//div[@class='quote' or @class='tags']/@class")?
?非:
'''提取所有span標(biāo)簽class屬性不為text的class屬性值''' tree.xpath("//span[not(@class='text')]/@class")?2.11 選取指定標(biāo)簽結(jié)束之后的所有指定標(biāo)簽
在xpath中我們可以使用following來定位以某個標(biāo)簽在文檔中的位置為起點的所有指定標(biāo)簽:
'''提取所有class為keywords的meta標(biāo)簽結(jié)束標(biāo)簽之后出現(xiàn)的標(biāo)簽a的text()內(nèi)容''' tree.xpath("//meta[@class='keywords']/following::a/text()")2.12?選取指定標(biāo)簽開始之前的所有指定標(biāo)簽
與following的功能截然相反,在xpath中使用preceding可以定位指定標(biāo)簽之前的所有標(biāo)簽:
'''選取body標(biāo)簽之前的所有標(biāo)簽的text()內(nèi)容''' tree.xpath("//body/preceding::*/text()")?
2.13 選取指定標(biāo)簽結(jié)束之后的所有同級指定標(biāo)簽
在following的基礎(chǔ)上,若想定位所有指定標(biāo)簽之后且與指定標(biāo)簽同一級別的標(biāo)簽,可使用following-sibling:
'''提取所有class為keywords的meta標(biāo)簽結(jié)束標(biāo)簽之后出現(xiàn)的同級別標(biāo)簽a的text()內(nèi)容''' tree.xpath("//meta[@class='keywords']/following-sibling::a/text()")2.14 選取指定標(biāo)簽開始之前的所有同級指定標(biāo)簽
類似following-sibling,使用preceding-sibling可以實現(xiàn)相反的效果:
'''選取body標(biāo)簽之前的所有同級標(biāo)簽的text()內(nèi)容''' tree.xpath("//body/preceding-sibling::*/text()")?
2.15 對提取內(nèi)容中的空格進(jìn)行規(guī)范化處理
在xpath中我們可以使用normalize-space對目標(biāo)內(nèi)容中的多余空格進(jìn)行清洗,其作用是刪除文本內(nèi)容之前和之后的所有\(zhòng)s類的內(nèi)容,并將文本中夾雜的兩個及以上空格轉(zhuǎn)化為單個空格,下面比較使用normalize-space前后對提取結(jié)果的影響:
'''清洗前''' tree.xpath("//p[@class='text-muted']/text()") '''清洗后''' tree.xpath("normalize-space(//p[@class='text-muted']/text())")使用normalize-space之后得到的結(jié)果更加的規(guī)整,可以提高爬取數(shù)據(jù)的效率。
?
2.16 在xpath中使用正則表達(dá)式
有時候一些任務(wù)情況比較特殊,在xpath中可能沒有對應(yīng)的函數(shù)直接可以使用,這時可以在xpath語句中穿插正則表達(dá)式,比如我們想要提取class為tag且href屬性符合.*?-.*?page.*?規(guī)則的a標(biāo)簽中的href與text()內(nèi)容,就可以在傳入規(guī)范的正則命名空間,并利用match來匹配自定義的正則語句,如下:
tree.xpath(r"//a[@class='tag' and ns:match(@href, '.*?-.*?page.*?')]/text() | //a[@class='tag' and ns:match(@href, '.*?-.*?page.*?')]/@href",namespaces={"ns": "http://exslt.org/regular-expressions"})?
?
以上就是本文的全部內(nèi)容,實際上xpath中還有更多方便使用的功能,本文僅根據(jù)筆者的日常使用積累做了片面的總結(jié),如有筆誤之處望斧正!
?
?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/feffery/p/10996526.html
總結(jié)
以上是生活随笔為你收集整理的(数据科学学习手札61)xpath进阶用法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用户故事与敏捷方法阅读笔记03
- 下一篇: 使用装饰器配置路由的