Python爬虫学习之数据提取(XPath)

概述

XPath的全称是XML Path Language, 即XML路径语言,用来在XML文档中查找信息。虽然最初是用来搜寻XML文档的,但是同样适用于HTML文档的搜索。

常用规则

表达式描述
nodename选取此节点的所有子节点
/从当前节点选取直接子节点
//从当前节点选取子孙节点
.选取当前节点
. .选取当前节点的父节点
@选取属性

运算符及介绍

运算符描述实例返回值
ornum=1 or num=2如果num值为1或者2,返回true,如果为3,则返回false
andnum> 1 and num<3如果num等于2,返回true,否则返回false
mod计算除法余数3 mod 21
|计算两个节点集//num1|//num2返回所有拥有num1与num2元素的节点
+加法1+12
-减法2-11
*乘法2*36
div除法8 div 42
=等于num=5如果num是5,返回true,否则返回false
!=不等于num!=5如果num是6,返回true,如果num是5则返回false
<小于num<5如果num是3,返回true,如果num是7则返回false
<=小于等于num<=5如果num是5,返回true,如果num是6则返回false
>大于num>5如果num是8,返回true,如果num是3则返回false
>=大于等于num>=5如果num是5,返回true,如果num是3则返回false

准备工作

使用XPath对HTML解析,需要安装Python的lxml库。安装命令如下:

# pip 命令
pip install lxml

# pip3 命令
pip3 install lxml

# conda 命令
conda install lxml

实例

目标网站 http://www.biqugei.net/ , 首先抓取网站首页内容

import requests

res = requests.get("http://www.biqugei.net/")

print(res.text)
# 以下只展示本周热读推荐部分结果

<div class="tMEWK container body-content">
	<div class="enW3B panel panel-default">
		<div class="5232g panel-heading">
			<span class="3bNs6 glyphicon glyphicon-fire" aria-hidden="true"></span> 本周热读推荐<a class="6B69i pull-right" href="/top.html">More+</a>
		</div>
		<div class="5chMn panel-body">
			<div class="Zi0mT row">
			    							<div class="elytd col-xs-4 book-coverlist">
					<div class="9XaRE row">
						<div class="7ukSL col-sm-5">
							<a href="/page/detail65541.html" class="vqocg thumbnail" style="background-image:url(https://img.picturecdn.com/files/article/image/65/65536/65536s.jpg)"></a>
						</div>
						<div class="HFrEh col-sm-7 pl0">
							<div class="RAgOj caption">
								<h4 class="sYdCt fs-16 text-muted"><a href="/page/detail65541.html" title="皇家的和尚">皇家的和尚</a></h4>
								<small class="rI9eW fs-14 text-muted">蓅謃</small>
								<p class="UxRCn fs-12 text-justify hidden-xs">冯小宝穿越了,竟然变成了名副其实的花和尚。别人穿越都是带着王霸之气,他却只想如何活下去!大唐高宗年间,那是一个多姿多彩的时代,既有威震天下的名臣武将,李靖,..</p>
							</div>
						</div>
					</div>
				</div>
											<div class="PIM0V col-xs-4 book-coverlist">
					<div class="T3nv6 row">
						<div class="hG1m3 col-sm-5">
							<a href="/page/detail1038.html" class="2JGuv thumbnail" style="background-image:url(https://img.picturecdn.com/files/article/image/1/1033/1033s.jpg)"></a>
						</div>
						<div class="IB1G8 col-sm-7 pl0">
							<div class="Bf5Dy caption">
								<h4 class="M8e22 fs-16 text-muted"><a href="/page/detail1038.html" title="此情惟你独钟">此情惟你独钟</a></h4>
								<small class="Ekvg8 fs-14 text-muted">阮白</small>
								<p class="q87XX fs-12 text-justify hidden-xs">定好的试管婴儿,突然变成了要跟那个男人同床怀孕,一夜缠绵,她被折磨的浑身瘫软!慕少凌,慕家高高在上的继承人,沉稳矜贵,冷厉霸道,这世上的事,只有他不想办的,..</p>
							</div>
						</div>
					</div>
				</div>
											<div class="im7CT col-xs-4 book-coverlist">
					<div class="y7Rws row">
						<div class="9wTjx col-sm-5">
							<a href="/page/detail1292.html" class="faVGI thumbnail" style="background-image:url(https://img.picturecdn.com/files/article/image/1/1287/1287s.jpg)"></a>
						</div>
						<div class="4kF22 col-sm-7 pl0">
							<div class="Foeeo caption">
								<h4 class="ASXDs fs-16 text-muted"><a href="/page/detail1292.html" title="神宠又给我开挂了">神宠又给我开挂了</a></h4>
								<small class="sh9S5 fs-14 text-muted">石三</small>
								<p class="VIXfx fs-12 text-justify hidden-xs">万古八荒第一神挂!上溯三层世界,最巅峰律令!……三年前,天空坠落三个生灵。西岭秦王得其一,横扫六国统一西岭。南荒大周武曌得其一,纵横南荒十九教,登顶第一。孙长..</p>
							</div>
						</div>
					</div>
				</div>
											<div class="TccVX col-xs-4 book-coverlist">
					<div class="v9Pwk row">
						<div class="kAogg col-sm-5">
							<a href="/page/detail860.html" class="eDtiC thumbnail" style="background-image:url(https://img.picturecdn.com/files/article/image/0/855/855s.jpg)"></a>
						</div>
						<div class="lkUzL col-sm-7 pl0">
							<div class="JFM5a caption">
								<h4 class="DNS2q fs-16 text-muted"><a href="/page/detail860.html" title="上门狂婿">上门狂婿</a></h4>
								<small class="ojhVV fs-14 text-muted">狼叔当道</small>
								<p class="xOIIA fs-12 text-justify hidden-xs"> 入赘三年,受尽羞辱;扫墓归来,开启逆袭之路!</p>
							</div>
						</div>
					</div>
				</div>
											<div class="ZOyht col-xs-4 book-coverlist">
					<div class="1f2SU row">
						<div class="Fmpdx col-sm-5">
							<a href="/page/detail825.html" class="4DE5C thumbnail" style="background-image:url(https://img.picturecdn.com/files/article/image/0/820/820s.jpg)"></a>
						</div>
						<div class="GkkON col-sm-7 pl0">
							<div class="nS15F caption">
								<h4 class="vjFQk fs-16 text-muted"><a href="/page/detail825.html" title="巨甜!我在禁欲冷王的怀里恃宠而骄">巨甜!我在禁欲冷王的怀里恃宠而骄</a></h4>
								<small class="SdR5f fs-14 text-muted">浩瀚之渊</small>
								<p class="P8nkE fs-12 text-justify hidden-xs">一场事故,让恶名昭昭的医学博士江云缨穿到了相府又丑又哑的嫡女身上,开局就是与人偷腥?满级邪恶大佬华丽登场,不做柔弱小白花,谁来惹她,个个反杀!什么?渣爹要把她嫁给克妻的痴傻璃王,双腿残疾还不能人道?完美!药死他是不是可以妻承夫业?于是江云缨带着小算盘当上人人同情的璃王妃,摇身成了京都第一美人,还一边风风火火搞事业。开连锁医馆,建最大商会,立暗杀组织,各方势力纷纷栽在她手里,她还直呼不刺激!被甩满脸</p>
							</div>
						</div>
					</div>
				</div>
											<div class="uDYsa col-xs-4 book-coverlist">
					<div class="pl93M row">
						<div class="IWnsF col-sm-5">
							<a href="/page/detail131077.html" class="GHFXb thumbnail" style="background-image:url(https://img.picturecdn.com/files/article/image/131/131072/131072s.jpg)"></a>
						</div>
						<div class="iaNh7 col-sm-7 pl0">
							<div class="Mo7As caption">
								<h4 class="Q4a49 fs-16 text-muted"><a href="/page/detail131077.html" title="穿越无限之旅">穿越无限之旅</a></h4>
								<small class="LcMVz fs-14 text-muted">神人无名</small>
								<p class="vIKcM fs-12 text-justify hidden-xs">金庸武侠中有不少绝世高手,书中有提及名字的,也有不曾提及名字的,但都是拥有自己独有的绝世武功而名动天下。段誉有六脉神剑,欧阳锋有蛤蟆功,林朝英有玉女素心剑法,..</p>
							</div>
						</div>
					</div>
				</div>
								
								<div class="OiqUA clear"></div>
			</div>
		</div>
	</div>

文本获取

我们的目的是抓取本周热读推荐的所有小说名字。分析上面的结果可知,所有的名字都在标签h4里面。所有代码可以写成如下格式:

import requests
from lxml import etree

res = requests.get("http://www.biqugei.net/")

html = etree.HTML(res.text)

result = html.xpath('//h4')
print(result)

在这几行代码中,我们先将通过requests获取的html文本,使用etree.HTML类初始化,这样就构成了一个XPath解析对象。我们通过//h4查找元素的所有子孙节点h4。结果如下所示。

[<Element h4 at 0x1cbd02f5688>, <Element h4 at 0x1cbd02f5648>, <Element h4 at 0x1cbd02f5588>, <Element h4 at 0x1cbd02f55c8>, <Element h4 at 0x1cbd02f56c8>, <Element h4 at 0x1cbd02f5388>]

我们获得了小说名所在的元素,如果要获取具体的文本内容,可以使用/text()方法,修改代码如下:

result = html.xpath('//h4/text()')

运行结果如下:

[]

意外的是我们没有获取到任何文本,只有一个空集合。这是什么原因呢?因为 xpath 中 text 方法前面是/,而/的含义是选取直接子节点,很明显h4的直接子节点是a节点,文本都是在a节点的内部的,所以这里没有匹配到任何文本。因此,如果想要获取h4节点内部的文本,有两种方式,一种是先获取a节点,再获取文本。另一种是使用//获取子孙节点。

第一种方式代码如下:

result = html.xpath('//h4/a/text()')
print(result)

第二种方式代码如下:

result = html.xpath('//h4//text()')
print(result)

最终运行结果如下:

['巨甜!我在禁欲冷王的怀里恃宠而骄', '此情惟你独钟', '穿越无限之旅', '上门狂婿', '神宠又给我开挂了', '皇家的和尚']

可以看到我们获取的内容都是h4标签里面的文本。说明我们的属性匹配是正确的。

属性获取

我们已经能够通过text方法获取节点内部的文本了,那么节点的属性该怎么获取呢,比如说如何获取小说链接,也即a标签内的href属性值呢?我们可以使用@符号获取。

import requests
from lxml import etree

res = requests.get("http://www.biqugei.net/")

html = etree.HTML(res.text)

result = html.xpath('//h4/a/@href')
print(result)

运行结果如下:

['/page/detail1292.html', '/page/detail825.html', '/page/detail860.html', '/page/detail65541.html', '/page/detail1038.html', '/page/detail131077.html']

可以看到,我们成功的获取了小说链接,并返回列表。

属性值匹配

<div class="RAgOj caption">
	<h4 class="sYdCt fs-16 text-muted"><a href="/page/detail65541.html" title="皇家的和尚">皇家的和尚</a></h4>
	<small class="rI9eW fs-14 text-muted">蓅謃</small>
	<p class="UxRCn fs-12 text-justify hidden-xs">冯小宝穿越了,竟然变成了名副其实的花和尚。别人穿越都是带着王霸之气,他却只想如何活下去!大唐高宗年间,那是一个多姿多彩的时代,既有威震天下的名臣武将,李靖,..</p>
</div>

在选择节点的时候我们可能需要选择特定属性的节点,比如在以上文本中,我们想选择title皇家的和尚a标签的href值。我们还可以使用@符号过滤。

import requests
from lxml import etree

res = requests.get("http://www.biqugei.net/")

html = etree.HTML(res.text)

result = html.xpath('//h4/a[@title="皇家的和尚"]/@href')
print(result)

结果如下:

['/page/detail65541.html']

可见,我们获取了正确的小说链接。

属性多值匹配

但是,在有些时候节点的某个属性有多个值,如上面html文本中。最外面的div节点class属性有两个值RAgOjcaption。如果我们使用一下代码获取时:

result = html.xpath('//div[@class="RAgOj caption"]')
result = html.xpath('//div[@class="RAgOj"]')
result = html.xpath('//div[@class="caption"]')

结果如下:

[]

发现无法正确的获取数据。返回空列表。在这种情况下,就要使用contains方法,代码如下所示。

result = html.xpath('//div[contains(@class, "RAgOj")]')
print(result)

此时,运行结果如下:

[<Element div at 0x21ac2c044c8>]

可以看到完成了匹配。

多属性匹配

有时候,我们可能需要根据多个属性来确定一个节点,这时候就需要匹配多个属性值,可以使用运算符and连接多个属性。
html文本如下:

<li class="FQd8o list-group-item"><a class="JGfFp list-name" href="/page/detail165426.html" title="仙在囧途:天上掉下个仙妹妹">仙在囧途:天上掉下个仙妹妹</a><span class="Uq0lo pull-right fs-12">单兮</span></li>
								
<li class="dM9ix list-group-item"><a class="IX3kF list-name" href="/page/detail165482.html" title="重写九九">重写九九</a><span class="YcVhY pull-right fs-12">一桶布丁</span></li>
								
<li class="QfEts list-group-item"><a class="9w6dR list-name" href="/page/detail165530.html" title="绝世驭鬼师:邪王,要翻身!">绝世驭鬼师:邪王,要翻身!</a><span class="BHJhj pull-right fs-12">南北火</span></li>
								
<li class="sRGTS list-group-item"><a class="oLw1q list-name" href="/page/detail165557.html" title="宿命之环">宿命之环</a><span class="87T2L pull-right fs-12">爱潜水的乌贼</span></li>

如果我们要匹配重写九九这本小说的链接,可以使用以下代码获取:

result = html.xpath('//a[contains(@class, "list-name") and @title="重写九九"]/@href')
print(result)

结果如下:

['/page/detail165482.html']

按序选择

在选择节点时,如果匹配到多个数据,而我们只要某一个数据时该怎么办呢?比如我想获取以下文本最后一条数据。可以通过往括号传入索引的方式选择特定次序的数据,代码如下:

<li class="FQd8o list-group-item"><a class="JGfFp list-name" href="/page/detail165426.html" title="仙在囧途:天上掉下个仙妹妹">仙在囧途:天上掉下个仙妹妹</a><span class="Uq0lo pull-right fs-12">单兮</span></li>
								
<li class="dM9ix list-group-item"><a class="IX3kF list-name" href="/page/detail165482.html" title="重写九九">重写九九</a><span class="YcVhY pull-right fs-12">一桶布丁</span></li>
								
<li class="QfEts list-group-item"><a class="9w6dR list-name" href="/page/detail165530.html" title="绝世驭鬼师:邪王,要翻身!">绝世驭鬼师:邪王,要翻身!</a><span class="BHJhj pull-right fs-12">南北火</span></li>
								
<li class="sRGTS list-group-item"><a class="oLw1q list-name" href="/page/detail165557.html" title="宿命之环">宿命之环</a><span class="87T2L pull-right fs-12">爱潜水的乌贼</span></li>
result = html.xpath('//li[last()]/a/text()')
print(result)
['宿命之环']
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Python爬虫中,我们可以使用XPath提取网页中的图片链接并进行下载。XPath是一种在XML和HTML文档中查找和定位元素的语言。要在Python中使用XPath,我们需要使用相关的库,如lxml库或BeautifulSoup库。下面是一个示例代码,演示了如何使用XPath来下载图片: ```python import requests from lxml import html # 定义目标网页的URL url = 'http://example.com' # 发送请求获取网页内容 response = requests.get(url) content = response.text # 使用lxml库解析网页内容 tree = html.fromstring(content) # 使用XPath表达式提取图片链接 image_urls = tree.xpath('//img/@src') # 遍历图片链接列表,下载图片 for image_url in image_urls: # 发送请求获取图片内容 image_response = requests.get(image_url) # 将图片保存到本地 with open('image.jpg', 'wb') as f: f.write(image_response.content) ``` 在上面的代码中,我们首先发送请求获取网页的内容,然后使用lxml库将网页内容转换为可解析的树结构。接下来,我们使用XPath表达式`//img/@src`提取所有`<img>`标签的`src`属性值,即图片链接。最后,我们遍历图片链接列表,发送请求获取图片内容,并将图片保存到本地。 请注意,上面的代码只是一个示例,具体的使用情况可能因不同的网站而有所差异。你需要根据目标网站的实际情况,调整XPath表达式和代码逻辑。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Python爬虫实战之xpath解析](https://blog.csdn.net/weixin_58667126/article/details/126105955)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Python3爬虫学习-爬取图片批量下载 XPATH](https://blog.csdn.net/xunxue1523/article/details/104584361)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值