python爬蟲基礎之xpath使用教程


介紹

XPath是一種XML路徑語言,被用於在XML文檔中通過元素和屬性進行導航

安裝

pip install lxml

使用

html示例內容,下面的所有練習全都來自與此段示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
    <style>
        .color1 {
            color: red;
            text-decoration: none;
        }
        .color2 {
            color: blue;
        }
        #color3 {
            color: pink;
            text-decoration: none;
        }
    </style>
</head>
<body>
<p>this is a text</p>
<span class="color1">
    <p>this is a span</p>
</span>
<div>
    <p>this is a list</p>
    <ul>
        <li><a href="#" class="color1">北京</a></li>
        <li><a href="#" id="color3">上海</a></li>
        <li><a href="#" class="color2">廣州</a></li>
        <li><a href="https://www.dogfei.cn">西二旗</a></li>
    </ul>
</div>
</body>
</html>

讀取html內容

from lxml import etree

with open('test.html', 'r', encoding='utf-8') as fr:
    html = fr.read()
    et = etree.HTML(html)

下面就接着這個代碼段往下寫。

所有節點、父節點、子孫節點

所有節點是通過指定'//*'來獲取,例如

et.xpath('//*')

返回如下:

[<Element html at 0x173aa409e88>, <Element head at 0x173aa540788>, <Element meta at 0x173aa5407c8>, <Element title at 0x173aa540848>, <Element style at 0x173aa540a48>, <Element body at 0x173aa540a88>, <Element p at 0x173aa540b08>, <Element div at 0x173aa540b48>, <Element p at 0x173aa540b88>, <Element ul at 0x173aa540948>, <Element li at 0x173aa540bc8>, <Element a at 0x173aa540c08>, <Element li at 0x173aa540c48>, <Element a at 0x173aa540c88>, <Element li at 0x173aa540cc8>, <Element a at 0x173aa540d08>, <Element li at 0x173aa540d48>, <Element a at 0x173aa540d88>]

子孫結點是通過'//'來獲取

# 獲取所有的li節點
et.xpath('//li')

父節點是通過'..'來獲取,有點像linux的..上級目錄

et.xpath('//p/../@class')

結果為

['color1']

獲取文本text()

res0 = et.xpath('//body/p/text()')

返回結果

['this is a text']

獲取指定標簽下的內容

res1 = et.xpath('//li[1]/a/text()')
print(res1)

返回結果

['北京']

指定具體的標簽

res2 = et.xpath('//div/p/')
print(res2)

返回內容

[<Element p at 0x23b49990888>]

指定類選擇器

res3 = et.xpath('//li/a[@class="color2"]/text()')
print(res3)

返回結果

['廣州']

指定id選擇器

res4 = et.xpath('//li/a[@id="color3"]/text()')
print(res4)

返回結果

['上海']

模糊匹配

res5 = et.xpath('//li/a[contains(@href, "http")]/text()')
print(res5)

返回結果

['西二旗']

指定某個屬性的具體值

res6 = et.xpath('//li/a[@href="https://www.dogfei.cn"]/text()')
print(res6)

返回結果

['西二旗']

獲取指定位置的內容

res7 = et.xpath('//li[last()]/a/text()')
print(res7)

返回結果

['西二旗']

也可以用[last() - 1]

還可以使用position()

res8 = et.xpath('//li[position() < 3]/a/text()')
print(res8)

返回結果

['北京', '上海']

通過使用position()可以獲取到一組數據

通配符

res9 = et.xpath('//li/*/text()') # *也可以省略
print(res9)

返回結果

['北京', '上海', '廣州', '西二旗']

指定所有屬性

res10 = et.xpath('//li//a[@*]/text()')
print(res10)

返回結果

['北京', '上海', '廣州', '西二旗']

使用./再次查找

res11 = et.xpath('//li')
for i in res11:
    r = i.xpath('./a/text()')[0]
    print(r)

返回結果

北京
上海
廣州
西二旗

實戰案例

此案例簡單來爬取豆瓣電影的top250,只拿第一頁的數據,打印出排名和電影名,重點是來掌握xpath的用法

豆瓣電影top250的訪問地址為:https://movie.douban.com/top250

查看頁面源代碼或者瀏覽器f12查看頁面元素定位到標簽位置,打開其中一段分析來看:

<ol class="grid_view">
                    <li>
                        <div class="item">
                            <div class="pic">
                                <em class="">1</em>
                                <a href="https://movie.douban.com/subject/1292052/">
                                    <img width="100" alt="肖申克的救贖"
                                         src="https://img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp"
                                         class="">
                                </a>
                            </div>
                            <div class="info">
                                <div class="hd">
                                    <a href="https://movie.douban.com/subject/1292052/" class="">
                                        <span class="title">肖申克的救贖</span>
                                        <span class="title">&nbsp;/&nbsp;The Shawshank Redemption</span>
                                        <span class="other">&nbsp;/&nbsp;月黑高飛(港)  /  刺激1995(台)</span>
                                    </a>


                                    <span class="playable">[可播放]</span>
                                </div>
                                <div class="bd">
                                    <p class="">
                                        導演: 弗蘭克·德拉邦特 Frank Darabont&nbsp;&nbsp;&nbsp;主演: 蒂姆·羅賓斯 Tim Robbins /...<br>
                                        1994&nbsp;/&nbsp;美國&nbsp;/&nbsp;犯罪 劇情
                                    </p>


                                    <div class="star">
                                        <span class="rating5-t"></span>
                                        <span class="rating_num" property="v:average">9.7</span>
                                        <span property="v:best" content="10.0"></span>
                                        <span>2468198人評價</span>
                                    </div>

                                    <p class="quote">
                                        <span class="inq">希望讓人自由。</span>
                                    </p>
                                </div>
                            </div>
                        </div>
                    </li>
.....
.....
.....
.....
</ol>
  1. 可以看到電影都在ol這個有序標簽內,ol標簽中的類屬性值grid_view這個是惟一的,直接用xpath,通過類選擇器來拿到這段html,然后再進一步處理。

  2. 由於這里是一個列表,所以得需要進行遍歷,既然是遍歷,那就應該拿到所有的li標簽下的內容,然后遍歷

  3. 每遍歷一次列表,就會拿到每一個電影的信息,然后可以找到排名信息是在em標簽下,電影名稱是在第一個span標簽下

from lxml import etree
import requests


def get_resource_html(url):
    headers = {
        "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36"
    }
    res = requests.get(url, headers=headers).text
    res.encode('utf-8')
    return res


def parse_html(html):
    et = etree.HTML(html)
    movie_list = et.xpath('//ol[@class="grid_view"]/li')
    for movie in movie_list:
        movie_ranking = movie.xpath('.//div[@class="pic"]/em/text()')[0]
        movie_title = movie.xpath('.//div[@class="info"]//span[1]/text()')[0]
        with open('movie.csv', 'a+', encoding='utf-8') as fw:
            fw.write(f"{movie_ranking},{movie_title}\n")
    return

def main():
    url = "https://movie.douban.com/top250"
    html = get_resource_html(url)
    parse_html(html)

if __name__ == '__main__':
    main()

執行結果

image-20211018185735047


歡迎各位朋友關注我的公眾號,來一起學習進步哦
images


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM