python简单易懂的lxml读取HTML节点及常用操作方法

13,319次阅读
没有评论

共计 4532 个字符,预计需要花费 12 分钟才能阅读完成。

python 简单易懂的 lxml 读取 HTML 节点及常用操作方法

1. 初始化和基本概念

  • lxml 是一个强大的 pyth 库,用于处理 XML 和 HTML 文档。
  • 它提供了类似 BeautifulSoup 的功能,但性能更高。
  • 在使用 lxml 时,通常会先解析 HTML 或 XML 文档,得到一个 ElementTree 对象。
pip install lxml

2. 解析 HTML 文档

  • 使用 lxml.html.fromstring(html) 来从字符串中创建一个 ElementTree 对象。

  • 示例:

    from lxml import html
    html_content = '

    Hello world!

    '
    tree = html.fromstring(html_content)

    或者使用 etree.HTML(rhtml_content)来创建 ElementTree 对象:

from lxml import etree
html_content = '

Hello world!

'
tree = etree.HTML(html_content)

3. XPath 选择器

  • XPath 是一种用于在 XML 文档中查找信息的语言。

  • lxml支持 XPath 选择器,可以用来定位文档中的元素。

  • 示例:

    
    paragraphs = tree.xpath('//p')
    

4. 遍历节点

5. 获取节点属性

  • 使用 .attrib 属性来获取节点的所有属性。

  • 示例:

    class_name = node.attrib.get('class', '')
    

在使用 lxml 处理 HTML 或 XML 文档时,获取节点的属性和属性值是非常常见的需求。下面详细解释如何获取标签的全部属性以及如何分别获取单个属性和属性值。

1. 获取标签的全部属性

lxml 中,你可以通过访问节点的 attrib 属性来获取所有属性。attrib是一个字典,键是属性名,值是属性值。

示例代码:
from lxml import html

html_content = '''

Hello, world!

'''
tree = html.fromstring(html_content) div_node = tree.xpath('//div')[0] all_attributes = div_node.attrib print("All attributes:", all_attributes)
2. 分别获取单个属性和属性值

如果你只需要获取某个特定属性的值,可以直接通过键访问字典中的值。如果属性不存在,则可以使用 get 方法提供一个默认值。

示例代码:

id_attribute = div_node.attrib.get('id', 'default-id')
print("ID attribute:", id_attribute)

class_attribute = div_node.attrib.get('class', 'default-class')
print("Class attribute:", class_attribute)




3. 获取属性值

如果属性名已知,可以直接通过键访问字典中的值。如果属性名未知或需要处理多个属性,可以遍历 attrib 字典来获取所有属性及其值。

示例代码:

for attr_name, attr_value in div_node.attrib.items():
    print(f"Attribute: {attr_name}, Value: {attr_value}")




4. 处理特殊情况

在某些情况下,属性可能包含空格分隔的多个值(例如 class 属性),这时你可以使用 split 方法来分割字符串。

示例代码:

class_values = div_node.attrib.get('class', '').split()
print("Class values:", class_values)



5. 综合示例

下面是一个综合示例,展示了如何获取节点的所有属性、单个属性以及如何处理特殊情况下的属性值。

from lxml import html

html_content = '''

Hello, world!

'''
tree = html.fromstring(html_content) div_node = tree.xpath('//div')[0] all_attributes = div_node.attrib print("All attributes:", all_attributes) id_attribute = div_node.attrib.get('id', 'default-id') print("ID attribute:", id_attribute) class_attribute = div_node.attrib.get('class', 'default-class') print("Class attribute:", class_attribute) for attr_name, attr_value in div_node.attrib.items(): print(f"Attribute: {attr_name}, Value: {attr_value}") class_values = div_node.attrib.get('class', '').split() print("Class values:", class_values)

6. 获取节点文本

或者如果下面还有子节点的话,最好是用:


link_name = ''.join(child.itertext()).strip().replace('n', '').strip()

link_name = re.sub(r's+', '', link_name ).strip()

7. 获取节点路径

1. 获取最末尾节点路径
               
                last_element = path.split('/')[-1] if '/' in path else path

8. 检查节点类型(标签名)

9. 子节点操作

  • 使用 .getchildren() 来获取节点的所有子节点,node.getparent()获取节点的所有父节点。

  • 示例:

    children = node.getchildren()
    

10. 提取属性值

11. 节点转换为字符串 HTML

  • 使用 etree.tostring(node) 来将节点转换为字符串形式。

  • 示例:

    node_html = etree.tostring(node, pretty_print=True, encoding='unicode')
    

12. 计算文本密度

  • 文本密度是指文本相对于其他非文本内容(如图片、链接)的比例。

  • 通过计算节点中的文本长度与节点总长度的比例来估算文本密度。

  • 示例:

    text_density = len(node.text_content()) / len(etree.tostring(node))
    

13. 处理列表页面

  • 在处理列表页面时,有时候需要检查是否有特定的类名来进行对应操作,如'list'

  • 示例:

    if 'list' in a_element[0].get('class', '').lower():
        
        pass
    

扩展

构建包含属性的 XPath 路径

流程:

1. 获取子节点的 XPath 路径

首先,我们遍历一个节点的所有子节点,并获取每个子节点的 XPath 路径。

for child in node.getchildren():
    xpath_path = '/' + node.getroottree().getpath(child)
2. 获取子节点的所有属性

对于每个子节点,我们获取其所有属性:

attributes = child.attrib
3. 构建包含属性的 XPath 路径

接下来,我们根据子节点的属性构建一个完整的 XPath 路径。如果子节点有属性,我们会在 XPath 路径后面加上属性条件。

3.1 属性存在时

如果子节点有属性,我们构建一个包含所有属性的 XPath 路径:

if attributes:
    xpath_with_attributes = xpath_path + "["
    for i, (key, value) in enumerate(attributes.items()):
        xpath_with_attributes += f"@{key}='{value}'"
        if i  len(attributes) - 1:
            xpath_with_attributes += "and"
    xpath_with_attributes += "]"
  • attributes.items() 返回一个迭代器,其中包含了属性的键值对。
  • enumerate(attributes.items()) 为每个属性分配一个索引。
  • f"@{key}='{value}'" 构建一个 XPath 条件,表示属性 key 的值为 value
  • 如果不是最后一个属性,则添加 "and" 以连接多个条件。
  • 最后添加 "]" 来结束 XPath 条件。
3.2 属性不存在时

如果子节点没有属性,我们直接使用原始的 XPath 路径:

else:
    xpath_with_attributes = xpath_path
综合示例

下面是一个完整的示例代码,展示了如何遍历节点的子节点并构建包含属性的 XPath 路径:

from lxml import html

html_content = '''

Hello, world!

Example Link
'''
tree = html.fromstring(html_content) root_node = tree.xpath('//div[@id="container"]')[0] for child in root_node.getchildren(): xpath_path = '/' + root_node.getroottree().getpath(child) attributes = child.attrib if attributes: xpath_with_attributes = xpath_path + "[" for i, (key, value) in enumerate(attributes.items()): xpath_with_attributes += f"@{key}='{value}'" if i len(attributes) - 1: xpath_with_attributes += "and" xpath_with_attributes += "]" else: xpath_with_attributes = xpath_path print(f"XPath Path: {xpath_path}") print(f"XPath with Attributes: {xpath_with_attributes}") print("Attributes:", attributes) print("")
详细解释
  1. 获取子节点的 XPath 路径

    • node.getchildren() 返回节点的所有子节点。
    • node.getroottree().getpath(child) 获取子节点的 XPath 路径。
    • 我们在路径前加上 / 来确保路径格式正确。
  2. 获取子节点的所有属性

    • child.attrib 返回子节点的所有属性及其值。
  3. 构建包含属性的 XPath 路径

    • 如果子节点有属性,我们构建一个包含所有属性的 XPath 路径。
    • 使用 enumerate 来为每个属性分配一个索引,以便在多个属性之间添加 and
    • 如果子节点没有属性,我们直接使用原始的 XPath 路径。

原文地址: python 简单易懂的 lxml 读取 HTML 节点及常用操作方法

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-10-14发表,共计4532字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)