爬蟲: 頁面解析 -- XPath語法的使用

摘要

XPath 使用路徑表達(dá)式來選取 XML 文檔中的節(jié)點(diǎn)或節(jié)點(diǎn)集却盘。節(jié)點(diǎn)是通過沿著路徑 (path) 或者步 (steps) 來選取的狰域。可以通過lxml模塊來使用XPath語法

XPath的語法

初步篩選:

<img src="/wp-content/uploads/2018/08/XPath.png" />

注意:
html文檔的根結(jié)點(diǎn)是html黄橘,但是"/body"并不會(huì)返回body兆览,因?yàn)榇藭r(shí)表示從根結(jié)點(diǎn)開始選取,實(shí)際上路徑位于根結(jié)點(diǎn)一級(jí)旬陡,所以
這級(jí)只有html拓颓,沒有body。需要從根結(jié)點(diǎn)選取body描孟,需要表明從根結(jié)點(diǎn)的下一級(jí)選取驶睦,即"./body"

比如:
./body/div//span/@href
表示文檔中body結(jié)點(diǎn)下兒子結(jié)點(diǎn)中所有的div結(jié)點(diǎn)下的所有子孫結(jié)點(diǎn)中的span結(jié)點(diǎn)的兒子結(jié)點(diǎn)中的href屬性
即:

    <html>
        ...
        <body>
            <!-- 兒子中所有的div -->
            <div>
                <!-- 子孫中所有的span -->
                <span>
                    <!-- 兒子結(jié)點(diǎn)中所有的href屬性的值 -->
                    href的值
                </span>
            </div>
        </body>
    </html>

我們發(fā)現(xiàn)砰左,每一級(jí)的標(biāo)簽名都默認(rèn)了選取“所有”該名字標(biāo)簽的前提,而body標(biāo)簽我之所以不用所有的來定義场航,只是因?yàn)橐粋€(gè)html文檔中只有一個(gè)body標(biāo)簽
/和//的區(qū)分是很重要的缠导,后面進(jìn)一步篩選結(jié)點(diǎn)也應(yīng)該在它們的前提下

進(jìn)一步篩選:

謂語:寫在在[]中
相關(guān)函數(shù) :
last() : 獲取最后一個(gè)元素的序號(hào)
position() : 獲取元素的位置序號(hào)
在[]中的可以是序號(hào)(從1開始),可以是屬性溉痢,也可以是邏輯表達(dá)式(等式直接用"=")

比如:
./body/div[last()-1]/div[@id]/span[position()<3]/a[@href="#"]
表示選取文檔中的根結(jié)點(diǎn)下的body的兒子結(jié)點(diǎn)中倒數(shù)第二個(gè)div結(jié)點(diǎn)的兒子結(jié)點(diǎn)中含id屬性的所有div結(jié)點(diǎn)的兒子結(jié)點(diǎn)中前面兩個(gè)span結(jié)點(diǎn)中的兒子結(jié)點(diǎn)中href屬性等于"#"的a結(jié)點(diǎn)
即:

    <html>
        <body>
            .......
            <!-- 最后一個(gè)div -->
            <div>
                <!-- 帶有id屬性的所有div -->
                <div id = "...">
                    <!-- 前面兩個(gè)span-->
                    <span>
                        <!-- href屬性等于"#"的a -->
                        <a href = "#"></a>
                    </span>
                </div>
            </div>
        </body>
    </html>

我們知道僻造,上面選取方式都比較具體,那么有沒有一種比較寬泛的方式選取結(jié)點(diǎn)呢孩饼?有髓削,通配符

  • 匹配任何元素節(jié)點(diǎn)。
    @* 匹配任何屬性節(jié)點(diǎn)镀娶。
    node() 匹配任何類型的節(jié)點(diǎn)立膛。
    text() 匹配文本結(jié)點(diǎn)
    string() 匹配所有文本結(jié)點(diǎn)

比如:
./body//[@]//*:
表示文檔中body結(jié)點(diǎn)下的所有兒子結(jié)點(diǎn)的帶屬性的兒子結(jié)點(diǎn)的任何類型的子孫結(jié)點(diǎn)
即:

    <html>
        <body>
            <!-- 所有任何類型的兒子結(jié)點(diǎn) -->
            <node>
                <!-- 所有帶屬性的任何兒子結(jié)點(diǎn)-->
                <node attr>
                    <!-- 所有任何類型的子孫結(jié)點(diǎn) -->
                    <node>...</node>
                </node>
            </node>
        </body>
    </html>

通過上面的知識(shí),我們已經(jīng)可以很好的選取html文檔中的元素了梯码。

總結(jié):

獲取XPath路徑宝泵,就是先使用/或//等初步篩選元素,然后通過謂語或者通配符進(jìn)行進(jìn)一步篩選

說明

以下代碼默認(rèn)已導(dǎo)入lxml模塊中的etree模塊

    from lxml import etree

解析過程如下:

  1. 通過html內(nèi)容生成selector
  2. 通過selector的xpath方法得到符合匹配條件的元素轩娶,返回列表
  3. 遍歷列表或者獲取列表中特定元素

比如:

    # html內(nèi)容
    html = "<!DOCTYPE HTML><html><body><p><a>123</a></p></body></html>"
    # 生成解析html的selector
    selector = etree.HTML(html)
    # 獲取符合條件的元素
    content = selector.xpath("http://a")
    print(content[0].text) # 123
    # 或者
    content = selector.xpath("http://a/text()")
    print(content[0]) # 123

補(bǔ)充內(nèi)容

沒有特定需求儿奶,其實(shí)不需要用到補(bǔ)充內(nèi)容。
1.選取多個(gè)路徑:
使用"|"運(yùn)算符連接兩個(gè)路徑表示或鳄抒,比如:
./body/div | ./body/div//a
表示./body/div 或 ./body/div//a

2.謂語中能夠使用的運(yùn)算符:

<img src="/wp-content/uploads/2018/08/XPathOpera.png" />

  1. 軸:
    通過“軸名::”的前綴形式改變/的含義闯捎,可用改變選取元素的順序,比如/默認(rèn)為子元素軸可用/child:表示
    a/parent::node() :表示a所有的任意類型父節(jié)點(diǎn)

比如许溅,./body//a/parent::node()
表示選取文檔中body的子孫結(jié)點(diǎn)中的所有a結(jié)點(diǎn)的任意類型的父節(jié)點(diǎn)
即:

    <html>
        <body>
            <!--a的所有任意類型的父節(jié)點(diǎn) -->
            <node>
               <!-- body的所有子孫結(jié)點(diǎn)中的a結(jié)點(diǎn)隙券,記為a -->
               <a></a>
            </node>
        </body>
    </html>

可以容易發(fā)現(xiàn),parent::改變了在文檔樹中從上到下選取元素的順序

相關(guān)的軸:

<img src="/wp-content/uploads/2018/08/XPathAxes.jpg">

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末闹司,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子沐飘,更是在濱河造成了極大的恐慌游桩,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耐朴,死亡現(xiàn)場(chǎng)離奇詭異借卧,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)筛峭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門铐刘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人影晓,你說我怎么就攤上這事镰吵¢莺蹋” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵疤祭,是天一觀的道長(zhǎng)盼产。 經(jīng)常有香客問我,道長(zhǎng)勺馆,這世上最難降的妖魔是什么戏售? 我笑而不...
    開封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮草穆,結(jié)果婚禮上灌灾,老公的妹妹穿的比我還像新娘。我一直安慰自己悲柱,他們只是感情好锋喜,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诗祸,像睡著了一般跑芳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上直颅,一...
    開封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天博个,我揣著相機(jī)與錄音,去河邊找鬼功偿。 笑死盆佣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的械荷。 我是一名探鬼主播共耍,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼吨瞎!你這毒婦竟也來了痹兜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤颤诀,失蹤者是張志新(化名)和其女友劉穎字旭,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體崖叫,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡遗淳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了心傀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屈暗。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出养叛,到底是詐尸還是另有隱情种呐,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布一铅,位于F島的核電站陕贮,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏潘飘。R本人自食惡果不足惜肮之,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望卜录。 院中可真熱鬧戈擒,春花似錦、人聲如沸艰毒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丑瞧。三九已至柑土,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绊汹,已是汗流浹背稽屏。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留西乖,地道東北人狐榔。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像获雕,于是被迫代替她去往敵國(guó)和親薄腻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

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