#数据解析中的最后一种方式,xpath是通用性最强的,注意边界高效的一中解析,最好用它来解析。
零、xpath解析原理与准备:
1.标签定位(实例化一个etree的对象,并且需要将被解析的页面源码数据加载到该对象中)
2.通过调用etree对象中的xpath方法结合着xpath表达式实现这个标签的定位和内容的捕获
3.环境的安装
一、如何实例化一个etree对象(两种形式):from lxml import etree
1.将本地的html文档中的源码数据加载到etree对象中:
etree.parse(filePath) #本地的文件路径 parse方法
2.可以将从互联网上获取的源码数据加载到该对象中
etree.HTML('page_text')
# 这里的etree是一个类,来自于lxml:from lxml import etree
# 当etree对象实例化好了之后就可以调用这个xpath方法了。
3.重点是xpath表达式的编写————xpath(‘xpath表达式’)
from lxml import etree
if __name__=="__main__":
tree=etree.parse('test.html')
#已经实例化好了一个etree对象,且将被解析的源码加载到了该对象中。
下一步是用xpath方法。
比如说现在想去做标签的定位,这里定位就可以使用xpath表达式定位。
这个表达式可以根据层级关系去实现标签定位,这个层级关系在select方法当中有层级关系,而在xpath就是也只能是根据层级表达式去定位。
tree.xpath('/html/head/title')###表示从html里的head里的title去定位,html前的/表示我们是从根节点,或者说是根目录开始遍历的。
根节点或者根目录,即,在当前源码中,最外层的节点就是根节点,那我们从根节点开始从外到内一层一层定位就可以定位到title。
用r去接收一下xpath:
#用r去接收一下xpath:
r=tree.xpath('/html/head/title')
print(r)
返回的是一个列表,列表当中存储的是一个标签,但是是element列表,这是这个标签被抽象成了element对象了。
还可以:
r=tree.xpath('/html/body/div')
print(r)
这个body里有三个div,所以返回的是一个包含三个div的element列表,这三个对象所表示的就是三个div标签。
最左侧的斜杠表示的是从根节点开始做定位,一个斜杠表示的是一个层级
如果:r=tree.xpath('/html//div') ###运行,更刚刚的运行结果一样,
//表示的是多个层级;可以从任意位置开始定位
如果:r=tree.xpath('//div') ###返回的结果依旧是一样的,这三种表达式含义和作用是一样的,作用到最左侧还是表示从任意位置去定位三个div
(能不能用xpat既能进行属性定位?)
固定格式:属性(clxxx)定位:
r=tree.xpath('//div[@class="song"]')
print(r)
# 运行返回的还是一个列表
# 结论!!!
# xpath返回的永远是一个列表把。
//div[@class='song'] tag[@attrName="attrValue"]
二、获取第三个p标签——所以接下来需要实现索引定位
r=tree.xpath('//div[@class="song"]/p[3]') #p是之前标签的直系标签,然后加上三,就是第三个标签,注意!!!这里的索引定位不是从0开始的,而是1!!!
注意!!!这里的索引定位不是从0开始的,而是1!!!
三、学会标签定位后,下一步就是如何取文本了
取文本:(标签中间所存储的文本内容)
1.第一种形式
r=tree.xpath('//div[@class="tang"]/ul/li[5]/a')
#也可以是:
r=tree.xpath('//div[@class="tang"]//li[5]/a')
#a标签获取到了。获取文本在其后加/text()
例如:
r=tree.xpath('//div[@class="tang"]//li[5]/a/text()')
print(r)
获取结果:
>>>['杜牧']
最终发现这个输出结果是存在在一个列表当中的,若想取得字符串,那就在后面加一个:[0]
r=tree.xpath('//div[@class="tang"]//li[5]/a/text()')[0]
>>>杜牧
2.第二种形式
<li><i>度蜜月</i></li> 第七个li标签 (非直系标签里文字的获取)
r=tree.xpath('//li[7]//text()')
# - /text() 获取标签下直系的文本内容
# - //text() 获取非直系标签下的文本内容
3. 以上都是一个标签里的文本获取,如果想要获取div下面的所有标签文本怎么办?
首先必不可少的属性定位:‘//div[@class=“tang”]’
r=tree.xpath('//div[@class="tang"]//text()')
——取属性:(取得定位到标签所对应属性的数值/属值?)
四、 /@attrName(格式)
例如:想要获取img里src储存的值:
<div class="song">
<img src="http://www.baidu.com/meinv.jpg" alt="" />
</div>
输入代码:
r=tree.xpath('//div[@class="song"]/img/@src')
print(r)
输出:
>>>['http://www.baidu.com/meinv.jpg']
五、xpath图片数据爬取要点
1.如果爬取标题的过程中,爬取文字出现乱码情况,应该手动修改encoding,尝试两个方法:
encoding='utf-8'
或者:
title=title.encode('iso-8859-1').decode('gbk')#title是出现乱码的区域
2.将所爬取的资源下载进入文件夹:请求图片,进行持久化存储;
img_data=requests.get(url=img_src,headers=headers).content,,,
img_path='picLibs/'+img_name
with open(img_path,'wb') as fp: ###文件需要打开多次,每打开一次就要需要往文件夹里写入图片一次,循环外部创建一个文件夹:
fp.write(img_data)
print(img_name,"下载成功!")
if not os.path.exists('./picLibs'):
os.mkdir('./picLibs')