Python__模块(网络-HTML解析)__lxml

简介

HTML解析工具、HTML页面生成工具。

安装

pip install lxml

文档查询

https://lxml.de/index.html


Element类

可以直观的理解为XML的节点

Element 是 ElementTree API 的主要容器对象。大多数 XML 树功能可通过此类进行访问


Element类(参考代码)

XML增删改

from lxml import etree
""" 节点创建 """
root = etree.Element("root")
""" 节点创建+属性创建 """
root = etree.Element("root", dataName="自定义属性")
""" 属性 """
root.get("dataName")                  # 获取指定属性
sorted(root.keys())                   # 获取所有属性
attributes = root.attrib
attributes["dataName"] = "修改的属性" # 修改属性值
""" 节点内容创建 """
root.text = "这是一段内容"
""" 节点名称 """
root.tag
""" 子节点创建 """
child2 = etree.SubElement(root, "child2")
child3 = etree.SubElement(root, "child3")
""" 序列化已创建的XML """
htmlText = etree.tostring(root, pretty_print=True)
print(htmlText)
""" 访问元素 """
child = root[0]      # 索引方式获取
child.tag
len(root)            # 统计子节点数量
root.index(root[1])  # 获取节点的索引位置
list(root)           # 转化为列表
""" 插入元素 """
root.insert(0, etree.Element("child0"))  # 创建的节点插入到,索引为0的位置
""" 节点跳转 """
root[0].getparent()              # 父节点
root[0] is root[1].getprevious() # 上一个节点
root[1] is root[0].getnext()     # 下一个节点
""" 删除 """
root.remove(root[0])

toString序列化

from lxml import etree
root = etree.XML('<root><a><b/></a></root>')
''' 【默认输出】 '''
etree.tostring(root)
# >>> b'<root><a><b/></a></root>' 
''' 【XML格式】 '''
print(etree.tostring(root, xml_declaration=True))
# >>> b"<?xml version='1.0' encoding='ASCII'?>\n<root><a><b/></a></root>"
''' 【编码】 '''
print(etree.tostring(root, encoding='iso-8859-1'))
''' 【漂亮打印】 '''
print(etree.tostring(root, pretty_print=True))
''' 【提取内容】 '''
root = etree.XML('<html><head/><body><p>Hello<br/>World</p></body></html>')
etree.tostring(root, method='text')
# >>> b'HelloWorld'

HTML构造

from lxml import etree
root = etree.Element("p", data="txt")
root.text = "Hello,World!"
print(root.text)                        # >>> Hello,World!
print(etree.tostring(root))             # >>> b'<p data="txt">Hello,World!</p>'

html = etree.Element("html")
body = etree.SubElement(html, "body")   # 添加节点
body.text = "Text"
print(etree.tostring(html))             # b'<html><body>Text</body></html>'

ElementTree类

ElementTree 主要是围绕树的文档包装器,带有根节点。

大部分方法与Element类相同。


ElementTree类(参考代码)

HTML构造器

E-factory 提供了一种简单而紧凑的语法,用于生成 XML 和 HTML格式。

from lxml.builder import E
from lxml import etree

def CLASS(*args):  # class is a reserved word in Python
    return {"class": " ".join(args)}

html = page = E.html(  # create an Element called "html"
    E.head(E.title("This is a sample document")),
    E.body(
        E.h1("Hello!", CLASS("title")),
        E.p("This is a paragraph with ", E.b("bold"), " text in it!"),
        E.p(
            "This is another paragraph, with a",
            "\n      ",
            E.a("link", href="http://www.python.org"),
            ".",
        ),
        E.p("Here are some reserved characters: <spam&egg>."),
        etree.XML("<p>And finally an embedded XHTML fragment.</p>"),
    ),
)

print(etree.tostring(page, pretty_print=True))
# >>>
'''
<html>
  <head>
    <title>This is a sample document</title>
  </head>
  <body>
    <h1 class="title">Hello!</h1>
    <p>This is a paragraph with <b>bold</b> text in it!</p>
    <p>This is another paragraph, with a
      <a href="http://www.python.org">link</a>.</p>
    <p>Here are some reserved characters: &lt;spam&amp;egg&gt;.</p>
    <p>And finally an embedded XHTML fragment.</p>
  </body>
</html>
'''

字符串和文件解析

常用解析函数

etree.XMLParser

创建解析器

【删除空文本】

etree.XMLParser(remove_blank_text=True)

etree.fromstring 解析字符串
etree.XML解析XML对象
etree.HTML解析HTML对象
etree.parse

解析文件类型对象

【提示】

parse() 返回一个 ElementTree 对象,而不是一个 Element 对象


Xpath 

Xpath路径

  • element.xpath(path)  指定在某个element,指定使用
  • etree.xpath(path)  包装在一个函数,频繁使用

Xpath(参数列表)

Xpath元素路径

iterfind()遍历与路径匹配的所有元素 表达
findall()返回匹配元素的列表
find()有效地只返回第一个匹配项
findtext()返回第一个匹配项的 .text 内容

Xpath提取内容

string()返回字符串
text()返回列表

Xpath常用规则

nodename

选取此节点的所有子节点

【例子】

bookstore(选取 bookstore 元素的所有子节点。)

/

从当前节点选取直接子节点

【例子】

/bookstore(选取根元素 bookstore。)

bookstore/book (选取属于 bookstore 的子元素的所有 book 元素。)

//

从当前节点选取子孙节点

【例子】

//book(选取所有 book 子元素,不限位置)

.

选取当前节点

..

选取当前节点的父节点

@

选取属性

【例子】

//@lang(选取名为 lang 的所有属性。)

*

通配符

【例子】

/bookstore/*(选取 bookstore 元素的所有子元素。)

//*(选取文档中的所有元素。)

@*

选取所有属性

【例子】

//title[@*](选取所有带有属性的 title 元素。)

[@attrib]

选取具有给定属性的所有元素

[@attrib='value']

选取给定属性具有给定值的所有属性

[tag]

选取所有具有指定元素的直接子节点

[tag='text']

选取所有具有指定元素并且文本内容是text节点

Xpath运算符

运算符描述实例返回值

or

age=19 or age=20如果age等于19或者等于20则返回true反正返回false
andage>19 and age<21如果age等于20则返回true,否则返回false
mod取余5 mod 21
|取两个节点的集合//book | //cd返回所有拥有book和cd元素的节点集合
+6+410
-6-42
*6*424
div除法8 div 42
=等于age=19true
!=不等于age!=19true
<小于age<19true
<=小于或等于age<=19true
>大于age>19true
>= 大于或等于age>=19true

Xpath常用函数

contains(string1,string2)

如果 string1 包含 string2,则返回 true,否则返回 false。

例子:contains(@classs,”classame“)

结果:true

name()返回当前节点的名称或指定节点集中的第一个节点。
position()

返回当前正在被处理的节点的 index 位置。

例子://book[position()<=3]

结果:选择前三个 book 元素

last()

返回在被处理的节点列表中的项目数目

例子://book[last()]

结果:选择最后一个 book 元素

更多函数了解https://www.w3school.com.cn/xpath/xpath_functions.asp

Xpath节点

ancestor

选取当前节点的所有先辈(父、祖父等)。

【例子】

ancestor::book 选择当前节点的所有 book 先辈。

ancestor-or-self

选取当前节点的所有先辈(父、祖父等)以及当前节点本身。

【例子】

ancestor-or-self::book 选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点)

attribute

选取当前节点的所有属性。

【例子】

attribute::lang 选取当前节点的 lang 属性。

attribute::*       选取当前节点的所有属性。

child

选取当前节点的所有子元素。

【例子】

child::book 选取所有属于当前节点的子元素的 book 节点。

child::*  选取当前节点的所有子元素。

child::text() 选取当前节点的所有文本子节点。

descendant

选取当前节点的所有后代元素(子、孙等)。

【例子】

descendant::book 选取当前节点的所有 book 后代。

descendant-or-self

选取当前节点的所有后代元素(子、孙等)以及当前节点本身。

following

选取文档中当前节点的结束标签之后的所有节点。

namespace

选取当前节点的所有命名空间节点。

parent

选取当前节点的父节点。

preceding

选取文档中当前节点的开始标签之前的所有节点。

preceding-sibling

选取当前节点之前的所有同级节点。

self

选取当前节点。

Xpath谓语

表达式结果
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3]选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang]选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang='eng']选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。

Xpath更多获取

路径表达式结果
//book/title | //book/price选取 book 元素的所有 title 和 price 元素。
//title | //price选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

Xpath(参考代码)

HTML文件解析

from lxml import etree
xp = etree.parse("123.html", etree.HTMLParser()) # HTMLParser 指定解析器
#'//td[@class='xxx']/text()'                     # 获取td 指定类型下的内容
htm = xp.xpath("//*")                            # 获取所有//下的所有节点
print(htm)

HTML解码输出

from lxml import etree
e_text = """
    <div>
        <ul>
            <li class='item-0'><a href='link1.html'>第一个</a></li>
            <li class='item-1'><a href='link2.html'>second item</a></li>
            <li class='item-0'><a href='link5.html'>a属性</a>
        </ul>
    </div>
"""
html = etree.HTML(e_text)                        # 解析HTML
result = etree.tostring(html).decode("utf-8")    # 将字符串序列化为html
print(result)                                    # 输出HTML内容

获取内容(创建功能函数获取内容)

# ======解析HTML文件======#
from lxml import etree
e_text = """
    <div>
        <ul>
            <li class='item-0'><a href='link1.html'>第一个</a></li>
            <li class='item-1'><a href='link2.html'>second item</a></li>
            <li class='item-0'><a href='link5.html'>a属性</a>
        </ul>
    </div>
"""
text = e_text
text = etree.HTML(text)
''' 方式一(获取内容)'''
st1 = text.xpath("string()")
st1 = [x.strip() for x in st1.split("\n") if x.strip() != ""]
print(st1)  # >>> ['第一个', 'second item', 'a属性']
''' 方式二(获取内容)'''
content = text.xpath("//text()")
st2 = [x.strip() for x in content if x.strip() != ""]
print(st2) # >>> ['第一个', 'second item', 'a属性']
# 获取所属节点
parent = content[0].getparent()
print(parent.tag) # >>> div



获取内容(HTML解析器获取内容)

from lxml import etree
html = """
<html>
<head>
  <title>网页标题</title>
</head>
<body>
  <h1>欢迎使用lxml</h1>
  <p>这是一个示例文档</p>
</body>
</html>
"""
# 创建解析器
parser = etree.HTMLParser()
tree = etree.fromstring(html, parser)
# 获取标题
title = tree.findtext('.//title')
print(title)   # >>> 网页标题
 

元素路径(综合例子)

from lxml import etree
root = etree.XML("<root><a x='123'>aText<b/><c/><b/></a></root>")

''' 获取内容 '''
print(root.find(".//b").tag)              # >>> b
[ b.tag for b in root.iterfind(".//b") ]  # >>> ['b', 'b']
print(root.findall(".//a[@x]")[0].tag)    # >>> a

''' 获取元素路径 '''
tree = etree.ElementTree(root)
a = root[0] 
print(tree.getelementpath(a[0]))             # >>> a/b[1]
print(tree.getelementpath(a[1]))             # >>> a/c
tree.find(tree.getelementpath(a[2])) == a[2] # >>> True

 元素路径(进阶搜索)

''' 加入函数或运算符,筛选获取的内容 '''
from lxml import etree
text1="""
<div>
    <ul>
         <li class="aaa" name="item"><a href="link1.html">第一个</a></li>
         <li class="aaa" name="item"><a href="link1.html">第二个</a></li>
         <li class="aaa" name="item"><a href="link1.html">第三个</a></li>
         <li class="aaa" name="item"><a href="link1.html">第四个</a></li> 
     </ul>
 </div>
"""
html=etree.HTML(text1,etree.HTMLParser())
r0=html.xpath('//li[contains(@class,"aaa")]/a/text()') 
# >>> ['第一个', '第二个', '第三个', '第四个']
r1=html.xpath('//li[2][contains(@class,"aaa")]/a/text()') 
# >>> ["第二个"]
r2=html.xpath('//li[last()][contains(@class,"aaa")]/a/text()') 
# >>> ["第四个"]
r3=html.xpath('//li[position()>2 and position()<4][contains(@class,"aaa")]/a/text()')
# >>> ["第三个"]
r4=html.xpath('//li[last()-2][contains(@class,"aaa")]/a/text()')
# >>> ["第二个"]


获取节点 

from lxml import etree

text1 = """
<div>
    <ul>
         <li class="aaa" name="item"><a href="link1.html">第一个</a></li>
         <li class="aaa" name="item"><a href="link1.html">第二个</a></li>
         <li class="aaa" name="item"><a href="link1.html">第三个</a></li>
         <li class="aaa" name="item"><a href="link1.html">第四个</a></li> 
     </ul>
 </div>
"""

html = etree.HTML(text1, etree.HTMLParser())
''' 获取所有祖先节点 '''
r0 = html.xpath("//li[1]/ancestor::*")           
r0 = [x.tag for x in r0]                        # >>> ['html', 'body', 'div', 'ul'] 
''' 获取div祖先节点 '''
r1 = html.xpath("//li[1]/ancestor::div")         
r1 = [x.tag for x in r1]                        # >>> ['div']
''' 获取所有属性值 '''
r2 = html.xpath("//li[1]/attribute::*")       
''' 获取所有直接子节点 '''   
r3 = html.xpath("//li[1]/child::*")              
r3 = [x.tag for x in r3]                        # >>> ['aaa', 'item']
''' 获取所有子孙节点的a节点 '''
r4 = html.xpath("//li[1]/descendant::a")         
r4 = [x.tag for x in r4]                        # >>> ['a']
''' 获取当前子节之后的所有节点 '''
r5 = html.xpath("//li[1]/following::*")          
r5 = [x.tag for x in r5]                        # >>> ['a']
''' 获取当前节点的所有同级节点 '''
r6 = html.xpath("//li[1]/following-sibling::*")  
r6 = [x.tag for x in r6]                        # >>>  ['li', 'a', 'li', 'a', 'li', 'a']


其它API

lxml.html

基于 lxml 的 HTML 解析器, 但为 HTML 元素提供了一个特殊的 Element API,以及 用于常见 HTML 处理任务的实用程序数量。

适用于快速生成HTML页面


lxml.html(参考代码)

创建HTML

import lxml.html
from lxml.html import builder as E

html = E.HTML(
    E.HEAD(
        E.LINK(rel="stylesheet", href="great.css", type="text/css"),
        E.TITLE("Best Page Ever"),
    ),
    E.BODY(
        E.H1(E.CLASS("heading"), "Top News"),
        E.P("start...", style="font-size: 200%"),
        "###########",
        E.P("end...", id="txt", data_value="1", style="font-size:16px;"),
        lxml.html.fromstring("<p>xxxxxxxxxx</p>"),
    ),
)

print(lxml.html.tostring(html))
# >>>
"""
<html>
  <head>
    <link rel="stylesheet" href="great.css" type="text/css" />
    <title>Best Page Ever</title>
  </head>
  <body>
    <h1 class="heading">Top News</h1>
    <p style="font-size: 200%">start...</p>
    ###########
    <p id="txt" data_value="1" style="font-size: 16px">end...</p>
    <p>xxxxxxxxxx</p>
  </body>
</html>
"""

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

vip飞梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值