Python----Xpath入门到精通与案例详解

本文详细介绍了XPath的原理、工具使用和语句介绍,并结合Python的lxml模块进行实战演示。通过案例展示了如何利用XPath在XML和HTML文档中查找、提取数据,以及在豆瓣电影Top250页面中爬取电影信息,包括标题、评分、评价人数等。同时,文章还提供了翻页和数据保存的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Xpath入门到精通与案例详解



提示:以下是本篇文章正文内容,下面案例可供参考

一、Xpath介绍

● XPath(XML Path Language)是一种XML的查询语言,他能在XML树状结构中寻找节点。XPath 用于在 XML 文档中通过元素和属性进行导航
● xml是一种标记语法的文本格式,xpath可以方便的定位xml中的元素和其中的属性值。lxml是python中的一个第三方模块,它包含了将html文本转成xml对象,和对对象执行xpath的功能

1、结点的关系

xml_content = '''
<bookstore>
<book>
    <title lang='eng'>Harry Potter</title>
    <author>JK.Rowing</author>
    <year>2005</year>
    <price>29<price>
</book>
</bookstore>
'''

● 父(Parent) book元素是title、author、year、price元素的父
● 子(Children) title、author、year、price都是book元素的子
● 同胞(Sibling) title、author、year、price都是同胞
● 先辈(Ancestor) title元素的先辈是 book元素和bookstore元素

2、为什么学习Xpath

正则比较复杂,根据不同网页结构 灵活的选择解析方法

3、Xpath原理

X path根据路径找到数据的技术
xml path language
html是xml的一个子集
根据元素和属性进行导航

二、Xpath工具使用

xpath入门测试一

from lxml import etree

xml_content = '''
<html>
    <head>
         <title>Harry Potter</title>
    </head>
    <body>
         <li class="author">JK.Rowing</li>
         <li class="year">2005</li>
         <li class="price">29</li>
         <div>
             <li class="book">harry potter</li>
         </div>
         <span>
         <li class="price">29</li>
         <div>
             <li class="book">harry potter</li>
         </div>
         </span>
    </body>
</html>
'''
tree = etree.HTML(xml_content)
# /表示层级关系 第一个/是根节点
bookstore_html = tree.xpath('/html')
# print(bookstore_html)
# text()获取文本内容的
title_html = tree.xpath('/html/head/title/text()')
# print(title_html)
# [0]把列表里面的数据取出
tit_html = tree.xpath('/html/head/title/text()')[0]
# print(author_html)
li_html = tree.xpath('/html/body/li/text()')
# [<Element li at 0x1f6b74c5488>, <Element li at 0x1f6b76fa3c8>, <Element li at 0x1f6b76fa448>]
# ['JK.Rowing', '2005', '29']
# print(li_html)
div_html = tree.xpath('/html/body/div/li/text()')
# print(div_html)
# //用于查找节点内部所有的子节点(后代)
li_div = tree.xpath('/html/body//li/text()')
# print(li_div)
div_li = tree.xpath('/html/body/div/li/text()')
# print(div_li)
span_li = tree.xpath('/html/body/span//li/text()')
# print(span_li)
# *可用匹配任意节点,看作一种通配符
div_span_li = tree.xpath('/html/body/*/li/text()')
print(div_span_li)

xpath入门测试二

from lxml import etree

# 网页源代码
html = '''
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>test2</title>
    </head>
    <body>
        <div id="songs-list">
            <h2 class="title">经典老歌</h2>
            <p class="introduction">经典老歌列表</p>
            <ul id="list" class="list-group">
                <li><a href="/1.mp3" singer="任贤齐">沧海一声笑</a></li>
                <li><a href="/2.mp3" singer="齐秦">往事随风</a></li>
                <li><a href="/3.mp3" singer="beyond">光辉岁月</a></li>
                <li><a href="/4.mp3" singer="陈慧琳">记事本</a></li>
                <li><a href="/5.mp3" singer="邓丽君">但愿人长久</a></li>
            </ul>
        </div>
    </body>
</html>
'''
tree = etree.HTML(html)
a_result = tree.xpath('/html/body/div/ul/li/a/text()')
# print(a_result)

# 一般用于没有属性值,或者说属性值重复 不太方便定位属性的就会使用位置定位
# 通过节点位置进行定位,定位到某些节点
# 节点下标从1开始
b_result = tree.xpath('/html/body/div/ul/li[1]/a/text()')
# print(b_result)

# 列表下标从零开始
c_result = tree.xpath('/html/body/div/ul/li/a/text()')[0]
# # print(c_result)

# 通过节点里面的属性值定位到具体的节点
d_result = tree.xpath('/html/body/div/ul/li/a[@href="/1.mp3"]/text()')
# print(d_result)

# 找到ul下面所有的li节点
e_result = tree.xpath('/html/body/div/ul/li')
# print(e_result)
for li in e_result:
    # print(li)
    # . 表示在当前li节点的基础上
    # xpath 一般是把符合xpath语句的数据 放在列表里面统一返回
    li_result = li.xpath('./a/text()')
    # print(li_result)
    # @href 用于获取属性值
    a_href = li.xpath('./a/@href')
    print(a_href)

三、Xpath语句介绍

符号作用
/从根节点选取
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
.选取当前节点
选取当前节点的父节点
@选取属性
*可用匹配任意节点,匹配当前节点下的任意节点,简单理解为通配符
text()获取当前选取节点的数据

位置定位

tree.xpath('')[列表下标]#通过列表下标定位
tree.xpath('/html/body/li[节点下标]')#通过节点下标定位
tree.xpath('/html/body/li[last()]')#选取最后一个
tree.xpath('/html/body/li[last()-1]')#选取倒数第二个
tree.xpath('/html/body/li/a[属性名=""]')#通过属性值筛选数据

四、lxml模块

lxml介绍

lxml 是 一个HTML/XML的解析器,主要的功能是如何解析和提取HTML/XML数据利用etree.HTML,将字符串转化为Element对象
lxml python 官方文档:http://lxml.de/index.html
可使用 pip 安装:pip install lxml
lxml 可以⾃动修正 html 代码

lxml下载

第三方模块 需要安装

pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple

lxml的使用

使用:

1、代码导入etree: from lxml import etree

2、发请求 获得相应 拿到网页源代码(html)

3、tree = etree.HTML(html)

4、找数据:title = tree.xpath(xxxxx)

5、保存数据(csv)

五、豆瓣–案例详解

豆瓣案例–网址与需求

 https://movie.douban.com/top250

爬取需求:详情页的url、图片的url、标题、评分、评价人数、引言

页面分析

一部影片的数据是放在一个li节点下面
这些所有li节点都是放在ol[class=“grid_view”]节点下面

详情页的url:先找到class="pic"的div节点下面的一个a节点 里面有一个href属性 放的是详情页的url

/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[1]/a

标题,图片的url:先找到class="pic"的div节点下面的一个a节点,在a节点下面有一个img节点 里面能通过alt属性获得标题,src可以获得img的url

/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[1]/a/img

评分:是class="rating_num"的span节点里面的文本

/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[2]

评价人数:class="star"的div节点 再往下找到最后一个span节点 里面有评价人数

/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[4]

引言:通过class="inq"的span节点获取引言

/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[2]/p[2]/span

翻页

翻页:

https://movie.douban.com/top250?start=0&filter= 第一页
https://movie.douban.com/top250?start=25&filter= 第二页
https://movie.douban.com/top250?start=50&filter= 第三页

动态更替start能够实现翻页 增长基数为25

代码演示

import time

from lxml import etree
import csv
import requests

# # 目标url
# url = "https://movie.douban.com/top250"
# # 请求头
# header = {
#     "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
#                   "Chrome/97.0.4692.99 Safari/537.36 "
# }
"""
页面分析:
一部影片的数据是放在一个li节点下面
这些所有li节点都是放在ol节点下面grid_view

详情页的url:先找到class="pic"的div节点下面的一个a节点 里面有一个href属性 放的是详情页的url
/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[1]/a
标题,图片的url:先找到class="pic"的div节点下面的一个a节点,在a节点下面有一个img节点 里面能通过alt属性获得标题,src可以获得img的url
/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[1]/a/img
评分:是class="rating_num"的span节点里面的文本
/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[2]
评价人数:class="star"的div节点 再往下找到最后一个span节点 里面有评价人数
/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[4]
引言:通过class="inq"的span节点获取引言
/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[2]/p[2]/span
"""
"""
翻页:
https://movie.douban.com/top250?start=0&filter=  第一页
https://movie.douban.com/top250?start=25&filter=  第二页
https://movie.douban.com/top250?start=50&filter=  第三页

动态更替start能够实现翻页 增长基数为25
"""


class DoubanMovie():
    def __init__(self):
        header = ['排名', "详情页url", "图片url", "标题", "评分", "评价人数", "引言"]
        self.file_obj = open('movie.csv', 'w', encoding='utf-8', newline='')
        # 1、创建csv对象
        self.Dictwrite = csv.DictWriter(self.file_obj, header)
        # 2、写入表头
        self.Dictwrite.writeheader()

    def get_html(self, url, header):
        res_obj = requests.get(url, headers=header)
        html = res_obj.text
        # print(html)
        return html

    def parse_data(self, html):
        # 把网页源码加载成element对象 赋值给tree
        tree = etree.HTML(html)
        li_list = tree.xpath('//ol[@class="grid_view"]/li')
        for li in li_list:
            item = {}
            # print(li)
            # 基于已经找到的li节点继续往下
            item['排名'] = li.xpath('.//div[@class="pic"]/em/text()')[0]
            item['详情页url'] = li.xpath('.//div[@class="pic"]/a/@href')[0]
            item['图片url'] = li.xpath('.//div[@class="pic"]/a/img/@src')[0]
            item['标题'] = li.xpath('.//div[@class="pic"]/a/img/@alt')[0]
            item['评分'] = li.xpath('.//span[@class="rating_num"]/text()')[0]
            item['评价人数'] = li.xpath('.//div[@class="star"]/span/text()')[-1]
            item['引言'] = li.xpath('.//span[@class="inq"]/text()')[0]
            print(item)
            try:
                item['inq'] = li.xpath('.//span[@class="inq"]/text()')[0]
            except:
                item['inq'] = ''
            print(item)
            self.save_data(item)

    def save_data(self, item):
        self.Dictwrite.writerow(item)

    def main(self):
        # 目标url
        url = "https://movie.douban.com/top250?start=0&filter="
        # 请求头
        header = {
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                          "Chrome/97.0.4692.99 Safari/537.36 "
        }
        # 处理翻页
        for i in range(5):
            # 1、i=0
            # 2、i=1
            print("正在爬取第{}页数据".format(i + 1))
            next_url = url.format(i * 25)
            html = self.get_html(next_url, header)
            self.parse_data(html)
            time.sleep(2)

        self.file_obj.close()


if __name__ == '__main__':
    douban = DoubanMovie()
    douban.main()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猩猩文学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值