爬虫之xpath解析
xpath
1、相关安装
安装lxml
在python Terminal终端安装
pip install lxml
谷歌浏览器xpath插件安装
文件链接
链接:https://pan.baidu.com/s/1YOeSPWFqZCrfXsC_B4ZlqQ
提取码:d7st
首先建一个空文件夹,将压缩包解压到此文件夹
然后打开谷歌浏览器
然后加载文件夹
加载完后重启一下浏览器
当右键检查页面的时候,使用快捷键ctrl+shift+x启动此插件
xpath使得正则匹配等方式爬取网页更加方便
2、一个测试用的html页面
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>测试页面</title>
</head>
<body>
<ol>
<li class="haha">醉卧沙场君莫笑,古来征战几人回</li>
<li class="heihei">两岸猿声啼不住,轻舟已过万重山</li>
<li id="hehe" class="nene">一骑红尘妃子笑,无人知是荔枝来</li>
<li class="xixi">停车坐爱枫林晚,霜叶红于二月花</li>
<li class="lala">商女不知亡国恨,隔江犹唱后庭花</li>
</ol>
<div id="pp">
<div>
<a href="http://www.baidu.com">李白</a>
</div>
<ol>
<li class="huanghe">君不见黄河之水天上来,奔流到海不复回</li>
<li id="tata" class="hehe">李白乘舟将欲行,忽闻岸上踏歌声</li>
<li class="tanshui">桃花潭水深千尺,不及汪伦送我情</li>
</ol>
<div class="hh">
<a href="http://mi.com">雷军</a>
</div>
<ol>
<li class="dudu">are you ok</li>
<li class="meme">会飞的猪</li>
</ol>
</div>
</body>
</html>
联想一下,将html页面转化为节点树的模型
3、xpath的相关语法
myxpath .py
该文件和html文件同级目录,如果不同级,需要修改下方的路径
from lxml import etree
# 1 将一个xml文件创建成一个树形结构
html_tree = etree.parse('./test.html')
print(html_tree)
# 得到结果是一个对象 <lxml.etree._ElementTree object at 0x0000013D7CF0DD88>
# 节点树
# 2 获取节点树上节点
# 用xpath路径在节点树上获取目标节点
ret = html_tree.xpath('/html/body/ol/li[1]')
# '/' 代表当前目录的子目录(当前节点的子节点) '//'代表当前节点的后代节点
# '[]' 代表对前面的节点进行条件修饰 [1]表示第一个
print(ret)
# 提取根节点的后代中所有的li节点
ret2 = html_tree.xpath('//li')
print(ret2)
# 查找页面上所有的带属性的li
ret3 = html_tree.xpath ('//li[@id]')
print(ret3)
# 3 提取内容和属性
#注意
# 1) 在xpath语法中所有的属性前面都要加上 @ 符号
# 2) xpath的属性修饰条件中,如果属性的取值有多个,一定要写全而且中间的间隔也要按照文件源码来写
# 提取节点的内容
ret4 = html_tree.xpath('/html/body/ol/li[3]/text()')
print(ret4) #['一骑红尘妃子笑,无人知是荔枝来']
# 提取节点的属性
ret5 = html_tree.xpath('/html/body/div/div[1]/a/@href')
print(ret5)
#查找页面上所有的class值为li的内容
ret6 = html_tree.xpath('//li/text()')
print(ret6)
#查找页面上所有的class值为dudu的li的内容
ret6 = html_tree.xpath('//li[@class="dudu"]/text()')
print(ret6) #['are you ok']
#查找页面上所有的div中的文本内容
ret7 = html_tree.xpath('//div//text()')
# 如果子节点中文本在提取的时候和上级节点重复,则不再提取
print(ret7)
# 查找页面上div属性中所有的后代节点id属性
ret8 = html_tree.xpath('//div//@id')
print(ret8)
# 4 模糊匹配
# 包含: 查找所有的class中包含h的li的文本
ret9 = html_tree.xpath('//li[contains(@class,"h")]/text()')
print(ret9)
# 开头: 查找所有的class值以h开头的li的文本
reta = html_tree.xpath('//li[starts-with(@class,"h")]/text()')
print(reta)
print('*****************')
# 5 逻辑匹配
# 与: 查找所有的既有id属性又有class属性的li的文本
ret_1 = html_tree.xpath("//li[@id and @class]/text()")
# 或: 查找所有的id值为hh或者class值为name的li的文本
ret_2 = html_tree.xpath("//li[@id='hh' or @class='meme']/text()")
print('*****************')
# 6 相对定位
# 以上的xpath路径都是从根节点开始查找的,这种路径为绝对路径
# 查找第二个ol
ol = html_tree.xpath("//ol[2]")[0]
# 以ol这个节点为基准向下查找
# 这样找到的其实是根节点下li的文本
ret_root = ol.xpath('//li/text()')
print(ret_root)
# 如果xpath路径中写的是绝对路径,根谁调xpath函数没有关系,查找的时候依然是从整个文件的根节点来查找
# 找ol节点下的li的文本
ret_revelative = ol.xpath('.//li//text()')
print(ret_revelative)
# "."代表当前路径相对路径,我们以哪个节点为基准(即用这个调用xpath函数),就会根据相对路径从这个节点向下查找
# ".."代表上一级路径,即以上一级路径为基准