首先先来介绍下XPath是什么东西:
XPath是一个用路径表达式来提取XML文档中节点的工具,我们有很多像有界面的东西都是用xml语言写的,其中HTML就是xml的一种;下面举个栗子理解一下:
<html>
<body>
<h1>title</h1>
<p>paragraph</p>
<div id="img-13012085" class="box">
<h1>title2</h1>
<a title="bizhi..." href="/p/13012085.html" >
<img alt="bizhi..." src="https://img11.51tietu.net/pic/2019112816/dgmgjm04q53dgmgjm04q53280x180.jpg" >
</a>
</div>
<div id="img-13012083" class="box">
<h1>title3</h1>
<a title="bizhi..." href="/p/13012083.html" >
<img alt="bizhi..." src="https://img11.51tietu.net/pic/2019112816/yxjxlzj0atayxjxlzj0ata280x180.jpg" >
</a>
</div>
</body>
</html>
什么是路径,比如我们要从上面找到 “title” 这个文字,我们要怎么找:html -> body -> h1,我们需要的文字就在<h1></h1>标签之间,我们只需要把h1标签找到,再把里面的内容提取出来就好了,那么像html、body这些标签就是我们的节点;XPath就是一种通过节点一层一层找到内容的文本提取工具;下面我们就通过代码把上面的那段文字提取出来:
from lxml import etree # 如果没有安装的话,用 pip install lxml 安装
# 我们需要把etree库导入
with open('test.html','r') as f: # 打开我们的html文件,内容就是上面的内容
read = f.read() # 将文件的内容读取出来
html = etree.HTML(read) # 返回lxml.etree._Element对象
# 这一步还有补全代码的功能,如果代码有标签的闭合确实,他可以自动补全
str = html.xpath('/html/body/h1/text()') # 通过xpath()方法进行匹配,后面的text()就是指文本值的意思
# h1下面的文本就是'title'了
print(str) # 最后我们让结果输出
# 输出结果:
# ['title']
上面我们使用的是绝对路径的方法,我们发现上面的代码中有三个<h1>,如果我想搜索所有的<h1>标签,那需要怎么处理呢?
from lxml import etree
with open('test.html','r') as f:
read = f.read()
html = etree.HTML(read)
str = html.xpath('//h1/text()') # //h1表示所有的h1节点,
print(str)
# 输出结果:
# ['title', 'title2', 'title3']
现在我需要获取第一张图片的所有信息,想要将红框框选的代码单独提取出来,然后再做处理,这该怎么做呢?
from lxml import etree
with open('test.html','r') as f:
read = f.read()
html = etree.HTML(read)
data = html.xpath('//div[@id="img-13012085"]') # []代表匹配里面的属性,@id表示属性的名字
# 注意://匹配,最后返回的是一个列表,我们要在最后指明是哪一个匹配项,
# 或者遍历列表的所有项
# data = html.xpath('//div[@id="img-13012085"]')[0]
for d in data: # 遍历所有匹配项
print(d.xpath('./h1/text()')) # 将所有匹配项的h1标签内容输出
print(str)
# 输出结果:
# ['title2']
现在问题又来了,我需要将所有div便签内的h1内容输出,那么该怎么做:
from lxml import etree
with open('test.html','r') as f:
read = f.read()
html = etree.HTML(read)
data = html.xpath('//div[contains(@id,"img-1301")]') # contains是一种不完全匹配,就是说相应属性值包含字段即可
for d in data:
print(d.xpath('./h1/text()'))
# 输出结果:
# ['title2']
# ['title3']