爬蟲-lxml解析庫(kù)、XPah語(yǔ)法

lxml是python的一個(gè)解析庫(kù)族展,支持HTML和XML的解析审葬,支持XPath解析方式深滚,而且解析效率非常高

XPath,全稱XML Path Language涣觉,即XML路徑語(yǔ)言痴荐,它是一門在XML文檔中查找信息的語(yǔ)言,它最初是用來(lái)搜尋XML文檔的官册,但是它同樣適用于HTML文檔的搜索

XPath的選擇功能十分強(qiáng)大生兆,它提供了非常簡(jiǎn)明的路徑選擇表達(dá)式,另外膝宁,它還提供了超過(guò)100個(gè)內(nèi)建函數(shù)鸦难,用于字符串、數(shù)值员淫、時(shí)間的匹配以及節(jié)點(diǎn)合蔽、序列的處理等,幾乎所有我們想要定位的節(jié)點(diǎn)介返,都可以用XPath來(lái)選擇

XPath的常用規(guī)則

表達(dá)式 描述
nodename 選取此節(jié)點(diǎn)的所有子節(jié)點(diǎn)
/ 從當(dāng)前節(jié)點(diǎn)拴事,選取直接子節(jié)點(diǎn)
// 從當(dāng)前節(jié)點(diǎn),選取所有子孫節(jié)點(diǎn)
. 選取當(dāng)前節(jié)點(diǎn)
.. 選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)
@ 選取屬性
* 通配符圣蝎,選擇所有元素節(jié)點(diǎn)與元素名
@* 選取所有屬性
[@attrib] 選取具有給定屬性的所有元素
[@attrib='value'] 選取給定屬性具有給定值的所有元素
[tag] 選取所有具有指定元素的直接子節(jié)點(diǎn)
[tag='text'] 選取所有具有指定元素并且文本內(nèi)容是text節(jié)點(diǎn)

構(gòu)建etree實(shí)例

首先需要引入etree

from lxml import etree

  • etree.HTML()
    解析字符串格式的HTML文檔對(duì)象刃宵,將傳進(jìn)去的字符串轉(zhuǎn)變成_Element對(duì)象。
    -- text:HTML文檔的字符串格式

  • parse()
    讀取HTML文件進(jìn)行解析徘公,將其轉(zhuǎn)變成_Element對(duì)象牲证。
    -- source:文件路徑
    -- parser:該方法默認(rèn)使用的是“XML”解析器,所以如果碰到不規(guī)范的html文件時(shí)就會(huì)解析錯(cuò)誤步淹,需要將此參數(shù)設(shè)置為etree.HTMLParser()

  • etree.tostring()
    將_Element對(duì)象轉(zhuǎn)換成字符串从隆。

注意:

  • etree.tostring()方法返回的是bytes類型诚撵,需要調(diào)用decode方法將其改變編碼類型。
  • 解析html代碼時(shí)键闺,會(huì)自動(dòng)修正寿烟,添加缺少的標(biāo)簽。

XPath語(yǔ)法實(shí)例

  • 選中所有節(jié)點(diǎn)
    # 選中所有的節(jié)點(diǎn)
    html = etree.parse("./test.html", etree.HTMLParser())
    results = html.xpath("http://*")
    print(results)

    # 選中所有的li節(jié)點(diǎn)
    results = html.xpath("http://li")
    print(results)
    print(results[0])
  • 選中子節(jié)點(diǎn)
    # 選中直接子節(jié)點(diǎn)
    html = etree.parse("./test.html",etree.HTMLParser())
    result = html.xpath("http://li/a")
    print(result)

    # 選取所有子孫節(jié)點(diǎn)
    result = html.xpath("http://ul//a")
    print(result)
  • 選取父親節(jié)點(diǎn)
    html = etree.parse("./test.html",etree.HTMLParser())
    # 選中屬性href='link4.html'的a標(biāo)簽的父親
    result = html.xpath("http://a[@href='link4.html']/..")
    print(result)

    # 選中屬性href='link4.html'的a標(biāo)簽的父親的class屬性
    result = html.xpath("http://a[@href='link4.html']/../@class")
    print(result)

    # 使用parent:: 選中父親
    result = html.xpath("http://a[@href='link4.html']/parent::*/@class")
    print(result)
  • 按屬性選取節(jié)點(diǎn)
    html = etree.parse("./test.html",etree.HTMLParser())
    result = html.xpath("http://li[@class='item-0']")
    print(result)
  • 獲取節(jié)點(diǎn)文本內(nèi)容
    需要調(diào)用text()函數(shù)
    html = etree.parse("./test.html", etree.HTMLParser())
    print(etree.tostring(html).decode("utf-8"))
    # 使用/僅獲取自身的文本內(nèi)容
    result = html.xpath("http://li[@class='item-0']/text()")
    print(result) # 輸出:['\r\n\t']
    # 使用//獲取自己以及子孫的文本內(nèi)容
    result = html.xpath("http://li[@class='item-0']//text()")
    print(result)  # 輸出:['first item', 'fifth item', '\r\n\t']
  • 獲取節(jié)點(diǎn)屬性的值
    html = etree.parse("./test.html", etree.HTMLParser())
    result = html.xpath("http://li/a/@href")
    print(result)
  • 多值屬性匹配
    需要使用contains()函數(shù)
    text = '''
        <li class="li li-first"><a href="link1.html">first item</a></li>
    '''
    html = etree.HTML(text)
    result = html.xpath("http://li[@class='li']/a/text()")
    print(result) # 輸出 []

    result = html.xpath("http://li[contains(@class,'li')]/a/text()")
    print(result) # 輸出:['first item']
  • 多屬性匹配
    text = '''
            <li class="li li-first" name="item"><a href="link1.html">first item</a></li>
    '''
    html = etree.HTML(text)
    result = html.xpath("http://li[contains(@class,'li') and @name='item']/a/text()")
    print(result)

and 是xpath中的運(yùn)算符辛燥。常見(jiàn)的運(yùn)算符如下:

運(yùn)算符 描述 實(shí)例
or age=19 or age=20
and age >19 and age <21
mod 取余數(shù) 5 mod 2
計(jì)算兩個(gè)節(jié)點(diǎn)集 //book | //cd :返回所有擁有book和cd元素的節(jié)點(diǎn)集
+ 加法 6 + 4
- 減法 6 - 4
* 乘法 6 * 3
div 除法 6 div 3
= 等于 age=19
!= 不等于 age !=19
< 小于 age <19
<= 小于或等于 age <= 19
> 大于 age >19
>= 大于或等于 age >= 19
  • 按順序選取節(jié)點(diǎn)
    html = etree.parse("./test.html",etree.HTMLParser())
    # 選取第一個(gè)節(jié)點(diǎn)
    result = html.xpath("http://li[1]/a/text()")
    print(result)
    # 選取最后一個(gè)節(jié)點(diǎn)
    result = html.xpath("http://li[last()]/a/text()")
    print(result)

    # 選取前兩個(gè)節(jié)點(diǎn)
    result = html.xpath('//li[position() < 3]/a/text()')
    print(result)

    # 選取倒數(shù)第三個(gè)節(jié)點(diǎn)
    result = html.xpath("http://li[last()-2]/a/text()")
    print(result)
  • 按節(jié)點(diǎn)軸選取元素
    text = '''
        <div>
            <ul>
                <li class="item-0" name="first-li"><a href="link1.html"><span>first item</span></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)
    # 選中指定元素所有的祖先
    result = html.xpath("http://li[1]/ancestor::*")
    print(result)

    # 選中祖先中的div
    result = html.xpath("http://li[1]/ancestor::div")
    print(result)

    # 獲取所有的屬性值
    result = html.xpath("http://li[1]/attribute::*")
    print(result)

    # 找到直接子節(jié)點(diǎn)中滿足條件的元素
    result = html.xpath("http://li[1]/child::a[@href='link1.html']")
    print(result)

    # 找到所有的后代元素
    result = html.xpath("http://li[1]/descendant::*")
    print(result)

    # 找到后代元素中的span
    result = html.xpath("http://li[1]/descendant::span")
    print(result)

    # 獲取該節(jié)點(diǎn)后面的兄弟節(jié)點(diǎn)以及這些兄弟節(jié)點(diǎn)的子孫節(jié)點(diǎn)
    result = html.xpath("http://li[1]/following::*")
    print(result)

    # 獲取該節(jié)點(diǎn)后面的兄弟節(jié)點(diǎn)以及這些兄弟節(jié)點(diǎn)的子孫節(jié)點(diǎn)中的第一個(gè)節(jié)點(diǎn)
    result = html.xpath("http://li[1]/following::*[1]")
    print(result)

    # 獲取該節(jié)點(diǎn)后面的所有兄弟節(jié)點(diǎn)
    result = html.xpath("http://li[1]/following-sibling::*")
    print(result)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末筛武,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子挎塌,更是在濱河造成了極大的恐慌徘六,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榴都,死亡現(xiàn)場(chǎng)離奇詭異待锈,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)嘴高,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門竿音,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人拴驮,你說(shuō)我怎么就攤上這事春瞬。” “怎么了套啤?”我有些...
    開(kāi)封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵宽气,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我潜沦,道長(zhǎng)萄涯,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任止潮,我火速辦了婚禮窃判,結(jié)果婚禮上钞楼,老公的妹妹穿的比我還像新娘喇闸。我一直安慰自己,他們只是感情好询件,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布燃乍。 她就那樣靜靜地躺著,像睡著了一般宛琅。 火紅的嫁衣襯著肌膚如雪刻蟹。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天嘿辟,我揣著相機(jī)與錄音舆瘪,去河邊找鬼片效。 笑死,一個(gè)胖子當(dāng)著我的面吹牛英古,可吹牛的內(nèi)容都是我干的淀衣。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼召调,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼膨桥!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起唠叛,我...
    開(kāi)封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤只嚣,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后艺沼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體册舞,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年障般,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了环础。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡剩拢,死狀恐怖线得,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情徐伐,我是刑警寧澤贯钩,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站办素,受9級(jí)特大地震影響角雷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜性穿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一勺三、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧需曾,春花似錦吗坚、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至谋减,卻和暖如春牡彻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背出爹。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工庄吼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缎除,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓总寻,卻偏偏與公主長(zhǎng)得像伴找,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子废菱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容