Python-lxml-etree

  1. xpath
    1. 简单例子
    2. xpath语法
    3. xpath例子
  2. 其他方法
    1. HTML
    2. tostring
    3. strip_elements
    4. 另外一种删除标签的方式

仅记录lxmletree,其中以xpath为重点,因为其他的我可能用得不多。

xpath

简单例子

import requests
from lxml import etree
 
url = 'https://dblp.org/pers/hd/p/Petersen:Karin'
html = requests.get(url)
html = etree.HTML(html.text) #初始化生成一个XPath解析对象
items = html.xpath('//div[contains(@class,"data")]/span//text()')
for i in items:
    print(i)

xpath语法

表达式 说明
/ 从当前节点选取直接子节点
// 从当前节点选取子孙节点
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性
* 通配符,选择所有元素节点与元素名
@* 选取所有属性
[@attrib] 选取具有给定属性的所有元素
[@attrib='value'] 选取给定属性具有给定值的所有元素
[tag] 选取所有具有指定元素的直接子节点
[tag='text'] 选取所有具有指定元素并且文本内容是text节点

xpath例子

html.xpath('//li')   #获取所有子孙节点的li节点
html.xpath('//li/a') #获取所有子孙节点的li节点下的所有直接a节点
result=html.xpath('//li[@class="item"]') 匹配class="item"的li
html.xpath('//a[@href="tab"]/../@class') 获取a的父节点的class值
html.xpath('//a[@href="tab"]/parent::*/@class')获取a的父节点的class值
html.xpath('//li[@class="item"]/a/text()') #获取a节点下的内容
html.xpath('//li[@class="item"]//text()') #获取li下所有子孙节点的内容
html.xpath('//li/a/@href')  #获取a的href属性
html.xpath('//li//@href')   #获取所有li子孙节点的href属性
# 按熟悉选择
html.xpath('//li[@class="aaa"]/a') 只能匹配class仅为'aaa'的节点
html.xpath('//li[contains(@class,"aaa")]/a') 匹配class有'aaa'的节点
#and or 的用法
html.xpath('//li[@class="aaa" and @name="fore"]/a/text()')
html.xpath('//li[contains(@class,"aaa") and @name="fore"]/a/text()')
# 按顺序选择
html.xpath('//li[1]/a/text()') #获取第一个li下a的内容
html.xpath('//li[last()]/a/text()') #获取最后一个li下a的内容
html.xpath('//li[position()>2 and position()<4]/a/text()') #获取大于2小于4的
html.xpath('//li[last()-2]/a/text()') #获取倒数第三个
# XPath提供了很多节点选择方法,包括获取子元素、兄弟元素、父元素、祖先元素等,示例如下:
html.xpath('//li[1]/ancestor::*')  #获取所有祖先节点
html.xpath('//li[1]/ancestor::div')  #获取div祖先节点
html.xpath('//li[1]/attribute::*')  #获取所有属性值
html.xpath('//li[1]/child::*')  #获取所有直接子节点
html.xpath('//li[1]/descendant::a')  #获取所有子孙节点的a节点
html.xpath('//li[1]/following::*')  #获取当前子节之后的所有节点
html.xpath('//li[1]/following-sibling::*')  #获取当前节点的所有同级节点

xpath的内容转载于这里

其他方法

HTML

构造了一个XPath解析对象并对HTML文本进行自动修正

参数是字符串

tostring

输出修正后的结果,类型是bytes,这是包括便签的
获取部分html
思路:

1 用xpath解析
2 tostring 转换为bytes
3 decode 转换字符串

from lxml import etree


text = '''
<div>
    <ul id="list">
         <li>1</li>
         <li>2</li>
         <li>3</li>
         <li>4</li>
         <li>5</li>
     </ul>
 </div>
'''
html = etree.HTML(text)

result = html.xpath("//ul[@id='list']")[0]

ul_ele = etree.tostring(result, method='html', encoding="utf8")
res = ul_ele.decode('utf8')
print(res)

strip_elements

删除子孙节点
etree.strip_elements(html, 'element_name', with_tag=True/False)
参数说明:

  • html: 经过etree.HTML()后的对象
  • element_name: 要删除哪一个标签
  • with_tag: 是否删除尾文本(看例子就知道什么意思了)
from lxml import etree

text = '''
<div>
    <ul id="list">
         <li>1<a href="#">1</a>尾巴1</li>
         <li>2</li>
         <li>3</li>
         <li>4</li>
         <li>5</li>
         <a href="#">6</a>尾巴2
     </ul>
 </div>
'''

html = etree.HTML(text)
etree.strip_elements(html, 'a', with_tail=True)

ul_ele = etree.tostring(html, method='html', encoding="utf8")
res = ul_ele.decode('utf8')

print(res)

结果:

<html><body><div>
    <ul id="list">
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </ul>
 </div>
 </body></html>

注意HTML方法会补全html,注意:a标签及其后面的文本不见了

假如是这样:

from lxml import etree

text = '''
<div>
  <ul id="list">
    <li>1<a href="#">1</a>尾巴1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <a href="#">6</a>尾巴2
  </ul>
 </div>
'''

html = etree.HTML(text)
etree.strip_elements(html, 'a', with_tail=False)

ul_ele = etree.tostring(html, method='html', encoding="utf8")
res = ul_ele.decode('utf8')

print(res)

其结果:

<html>
  <body>
    <div>
      <ul id="list">
        <li>1尾巴1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        尾巴2
      </ul>
    </div>
  </body>
</html>

尾文本被保留了下了

另外一种删除标签的方式

使用.remove()方法,删除子节点

前面的strip_elements是删除子孙都行,所以与remove有区别:要找到父节点

from lxml import etree

text = '''
<div>
    <ul id="list">
         <li>1<a href="#">1</a>尾巴1</li>
         <li>2</li>
         <li>3</li>
         <li>4</li>
         <li>5</li>
         <a href="#">6</a>尾巴2
     </ul>
 </div>
 '''

html = etree.HTML(text)
nodes = html.xpath("//a")

for node in nodes:
    parent = node.getparent()
    if parent is None: continue
    parent.remove(node)
ul_ele = etree.tostring(html, method='html', encoding="utf8")
res = ul_ele.decode('utf8')
print(res)

结果:

<html>
  <body>
    <div>
      <ul id="list">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
      </ul>
    </div>
  </body>
</html>

作者: 忞翛

出处: https://www.lczmx.top/Python/6162c6f5f5e7/

版权: 本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。

在线工具