环境安装:
基于xpath的数据解析主要使用lxml
库中的etree
类
# pip install lxml
代码中引入类
from lxml import etree
解析原理:
- 实例化一个
etree
类型的对象,然后将待解析的页面源码数据加载到此对象中 - 调用
etree
对象的xpath
方法,然后结合不同的xpath
表达式,来实现网页中局部位置的标签定位和数据提取 (这里主要是提取文本文件和标签属性值)
测试页面:
测试页面代码数据
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>测试xpath和bs4</title>
</head>
<body>
<div>
<p>百里守约</p>
</div>
<div class="song">
<p>李清照</p>
<p>王安石</p>
<p>苏轼</p>
<p>柳宗元</p>
<a href="http://www.song.com/" title="赵匡胤" target="_self">
<span>this is span</span>
宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</a>
<a href="" class="du">总为浮云能蔽日,长安不见使人愁</a>
<img src="http://www.baidu.com/meinv.jpg" alt="" />
</div>
<div class="tang">
<ul>
<li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>
<li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li>
<li><a href="http://www.126.com" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li>
<li><a href="http://www.sina.com" class="du">杜甫</a></li>
<li><a href="http://www.dudu.com" class="du">杜牧</a></li>
<li><b>杜小月</b></li>
<li><i>度蜜月</i></li>
<li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li>
</ul>
</div>
</body>
</html>
具体操作:
1. 实例化etree对象
etree.parse('filename')
:表示将本地文件加载到该对象中etree.HTML(page_text)
:表示将网站获取的页面数据加载到该对象中
from lxml import etree
tree = etree.parse('mytest.html') #test.html是保存在本地的测试网页
tree #打印出的tree = <lxml.etree._ElementTree at 0x106bbla88>
tree.xpath('xpath表达式') #返回的是一个列表
2. 实现标签定位
- 基于
xpath
方式定位标签的原理:HTML
标签可以看成以自上而下以树状图形式进行展示的文件,xpath
因此可以较低的时间复杂度逐层帮我们快速定位需要的标签,计算机中的目录结构其实也是一个树状结构,xpath
的写法实际上和计算机的子目录路径差不多,例如/html/head/meta
和/user/Desktop/test
- 使用
.xpath(‘xpath定位标签的表达式’)
方法,然后以列表形式返回定位到的数据 - 定位标签时
xpath
表达式的语法- 1)最左侧的
/
:如果xpath
表达式最左侧是以/
开头的,则表示该xpath
表达式一定要从根标签节点开始定位指定标签,类似于绝对路径,但是通常不用最左侧斜杠 (可以忽略不记,了解即可) - 2)非最左侧的
/
:表示一个层级 - 3)非最左侧的
//
:表示多个层级 - 4)最左侧的
//
:表示我们的xpath
表达式可以从任意的层级开始定位寻找,类似于相对路径,所有符合的标签都找到 - 5)属性定位:
tagName[@attrName="value"]
就可以定位到我们指定的属性标签,例如[@class="song"]
- 6)索引定位:
tag[index]
,xpath
表达式的索引是从1开始,不是从0开始 - 7)模糊匹配:
//div[contains(@class, "ng")]
和//div[starts-with(@class, "ta")]
注意:平时我们只需要使用属性定位和索引定位就可定位到任意的局部标签
- 1)最左侧的
tree.xpath('/html/head/meta') #帮我们从树的根节点一层一层的遍历找到meta,返回的是[<Elements meta at 0x106c9ae48>]
tree.xpath('/html//meta') #定位meta方式2,非最左侧为'//',表示中间多个层级
#最左侧为"//"
tree.xpath('//meta') #定位meta方式3,最左侧为'//',表示相对位置
tree.xpath('//div') #表示在我当前文档中,给我找到所有的div标签
#属性定位:定位到class为song的div下面所有的p标签
tree.xpath('//div[@class="song"]/p')
#索引定位:定位到class为song的div下面的第二个p标签
tree.xpath('//div[@class="song"]/p[2]')
3. 题取内容(文本内容和属性值)
- 提取文本内容
/text()
:表示提取出直系的文本内容//text()
:表示提取出所有的文本内容
- 提取属性
/@attrName
:表示提取属性值,例如/@href
#提取song的第二个p标签下面的直系文本内容
tree.xpath('//div[@class="song"]/p[2]/text()')
#提取song的第二个p标签下面的所有文本内容
tree.xpath('//div[@class="song"]/p[2]//text()')
#提取id为"feng"所对应的a标签里的href属性的值和内容
tree.xpath('//a[@id="feng"]/@href')
实例项目练习
- 使用
xpath
爬取前5页所有的图片名称和图片数据:练习网站网址 - 项目代码展示:
import requests
from lxml import etree
headers = {'User-Agent':''}
转载:https://blog.csdn.net/qq_40272386/article/details/105415266
查看评论