在python中,主要使用 lxml 库来进行xpath获取(在框架中不使用lxml,框架内直接使用xpath即可)
lxml 是 一个HTML/XML的解析器,主要的功能是如何解析和提取 HTML/XML 数据。
lxml和正则一样,也是用 C 实现的,是一款高性能的 Python HTML/XML 解析器,快速的定位特定元素以及节点信息。
1. 安装
pip install lxml
2. lxml使用流程
- 导入模块
from lxml import etree
注:pycharm中etree下方会有红色波浪线但不影响 - 创建HTML解析对象
parse_html = etree.Element(html) # 读取文本,自动转换为符合规范的HTML文档格式
注:返回类型:<class 'lxml.etree._Element'>,返回值<Element html at 0x1448fcc3dc0> - 调用xpath表达式
r_list = parse_html.xpath("Xpath表达式") # list类型
# 标签元素转为字符串
# res = etree.tostring(parse_html) # 字节类型
# print(type(res)) # <class 'bytes'>
# print(res.decode("utf-8"))
3. lxml库数据提取
3.1 etree.parse 读取HTML文件进行解析
html = etree.parse("baidu_百草.html", etree.HTMLParser())
# parse(self, source, parser=None)
# Load external XML document into element tree.
# *source* is a file name or file object, 文件或文件对象
# *parser* is an optional parser instance that defaults to XMLParser.
# 解析器,默认XMLParser;若指定HTMLParser会修复HTML文件中缺失内容,如声明
# ParseError is raised if the parser fails to parse the document.
# Returns the root element of the given source document.
# 返回<lxml.etree._ElementTree object at 0x00000237143BD3C0>,类型<class 'lxml.etree._ElementTree'>
res = etree.tostring(html) # 解析成字节类型
3.2 html.xpath 获取节点
from lxml import etree
with open("baidu_百草.html", "r", encoding="utf-8") as f:
html = f.read()
# 2. 创建HTML解析对象(读取文本)
parse_html = etree.HTML(html)
# 3. 调用xpath表达式
xpath = "//h3//a[@tabindex]//text()" # 获取a的文本
xpath = "//h3//a[@tabindex]/@href" # 获取a的href属性值
xpath = "//*" # 获取所有节点
xpath = "//a[@href="link2.html"]/parent::*/@class" # 父级元素匹配
xpath = "//a[@href="link2.html"]/../@class" # 父级元素匹配..
xpath = "//li[contains(@class,"aaa") and @name="fore"]/a/text()" # 多属性匹配and
r_list = parse_html.xpath(xpath)
print(r_list)
# 输出1:['青岛', '百草', '新材料股份有限公司', '百草', '乳膏 - 京东', ……]
# 输出2:['http://www.baidu.com/link?url=xx', 'http://www.baidu.com/link?url=xx',……]
# 输出3:[<Element html at 0x1a7f12be540>, ……]
# body = etree.Element("body")
# tree.append(body) # 添加body为子级
# sub = etree.SubElement(body, "p") # 添加子节点
# sub = etree.SubElement(body, "div").append(etree.Element("child"))
4. 示例
# 目标:获取所有h3的文本
xpath = "//h3//a[@tabindex]/text()" # 获取a的所有文本
# 但是下图中a的文本通过em标签分割,若全量获取,则无法区分
xpath = "//h3/a[@tabindex]" # 获取a元素
r_list = parse_html.xpath(xpath)
print(r_list)
for ele in r_list:
res = "".join(ele.xpath(".//text()"))
# ele.xpath 再次提取数据;拼接后获取需要的值
# . 表示当前节点
-
核对后发现有遗漏的h3:该h3子元素a无tabindex属性
- 修改xpath:
xpath = "//h3"
;核对后发现输出多余结果
- 修改xpath:
xpath = "//h3/a[1]"
,满足要求
参考
- python3解析lxml
- python lxml库的安装和使用
- python lxml解析库实战