前言
最近在处理网络爬虫下载的网页,使用到lxml模块。对于这个模块一直比较好奇,标准库中已经有xml模块了,为啥还有写一个三方的lxml模块?平常使用中常用作对HTML文件的解析与操作,还能干啥?等等,一大堆问题。特意花费一个下午,了解下它神秘面纱下到底隐藏这个什么。
提示:学习这个模块,建议大家先了解下W3C标准中的DOM对象,这对于大家去理解PAI比较有帮助。以下图片图,因为在学习中有一次让自己发散了,比较open,姑且记下来 ^V^-^V^:
一、lxml是什么?
lxml是python一个三方库,底层使用C实现,相较于python标准库中xml,具备更优越的性能,可以用来处理比较大的DOM对象(xml、html)。
二、使用步骤
1.安装lxml模块
pip install lxml
2.lxml模块完整分析
代码业务结构图:重点关注如下两个方法
- def HTML(text, parser) -> typing.Any 从字符串常量解析HTML文档
- def XML(text, parser) -> typing.Any 从字符串常量解析XML文档或片段
- def fromstring(text, parser)-> typing.Any 转换字符串为 DOM对象
- def parse(source, parser) -> typing.Any 解析文件为DOM对象
2.超文本标记语言中xpath表达式的介绍
符号 | 说明 | 适用方法 | 描述 |
nodename | 根据当前节点名称查询 | ele.xpath('head') | 查询当前节点下的所有head名称节点 |
/ | 从当前节点开始查询,路径 | ele.xpath('/html/body') | 查询当前节点下,/html/body所有节点 |
// | 查询所有节点,从root节点开始 | ele.xpath('//div') | 查询当前节点下所有div节点 |
. | 代表当前节点 | ele.xpath('.') | 返回当前节点 |
.. | 代表父节点 | ele.xpath('..') | 返回当前节点的父节点 |
@ | 返回某个属性的节点 | ele.xpath('//div[@class="cont"]') | 返回所有class=cont属性的div节点 |
* | 返回所有节点 | ele.xpath('*') | 返回当前节点下所有子节点 |
@* | 返回所有属性的节点 | ele.xpath('//div[@*]') | 返回所有具有属性的div节点 |
node() | 返回所有节点 | ele.xpath('node()') | 返回当前节点下的所有节点,包括换行符号 |
3.针对lxml基类 <class ‘lxml.etree._Element’>的API
描述 | api | 说明 |
节点增删 | def addnext(self, element) -> typing.Any | 将元素直接添加为该元素后面的兄弟元素。通常用于在文档的根节点之后设置处理指令或注释。注意,当在根级别添加时,tail文本将被自动丢弃。 |
def addprevious(self, element) -> typing.Any | 将元素直接添加为该元素前面的兄弟元素。 | |
def append(self, element) -> typing.Any | 将子元素添加到该元素的末尾 | |
def clear(self, keep_tail) -> typing.Any | 重置一个元素。这个函数删除所有子元素,清除所有属性,并将文本和尾部属性设置为None | |
def cssselect(self, expr) -> typing.Any | 在这个元素及其子元素上运行CSS表达式 | |
def extend(self, elements) -> typing.Any | 通过iterable中的元素扩展当前子元素 | |
def insert(self, index, element) -> typing.Any | 插入元素节点 | |
def remove(self, element) -> typing.Any | ||
def replace(self, old_element, new_element) -> typing.Any | ||
def set(self, key, value) -> typing.Any | ||
获取节点信息 | def tail(self) -> typing.Any【@property】 | 获取tail |
def text(self) -> typing.Any【@property】 | 获取text文字内容 | |
def xpath(self, _path, **_variables) -> typing.Any【@property】 | 返回当前元素的所有属性 | |
def xpath(self, _path, **_variables) -> typing.Any【@property】 | 元素的基本URI (xml:base或HTML基本URL) | |
def nsmap(self) -> typing.Any【@property】 | ||
def prefix(self) -> typing.Any【@property】 | ||
def sourceline(self) -> typing.Any【@property】 | ||
def tag(self) -> typing.Any【@property】 | ||
查找节点 | def xpath(self, _path, **_variables) -> typing.Any | 该方法使用xpath语法,最常用 |
def find(self, path, namespaces) -> typing.Any | 获取当前节点下第一个匹配节点 | |
def findall(self, path, namespaces) -> typing.Any | 获取当前节点下所有匹配元素 | |
def findtext(self, path, default, namespaces) -> typing.Any | 获取某个节点下的文本节点 | |
def getchildren(self) -> typing.Any | 获取当前节点下的所有子节点 | |
def getiterator(self, tag, *tags) -> typing.Any | 获取当前节点所有子节点,迭代器 | |
def getnext(self) -> typing.Any | 获取下一个节点 | |
def getparent(self) -> typing.Any | 获取父节点 | |
def getprevious(self) -> typing.Any | 返回该元素的前一个兄弟元素或None | |
def getroottree(self) -> typing.Any | 为文档的根节点返回一个ElementTree | |
def iter(self, tag, *tags) -> typing.Any | 查找元素,返回迭代器 | |
def iterancestors(self, tag, *tags) -> typing.Any | ||
def iterchildren(self, tag, *tags) -> typing.Any | ||
def iterdescendants(self, tag, *tags) -> typing.Any | ||
def iterfind(self, path, namespaces) -> typing.Any | ||
def itersiblings(self, tag, *tags) -> typing.Any | ||
def itertext(self, tag, *tags) -> typing.Any | ||
查找节点属性 | def items(self) -> typing.Any | 获取当前节点所有属性 |
def keys(self) -> typing.Any | ||
def get(self, key, default) -> typing.Any | ||
def index(self, child, start, stop) -> typing.Any | ||
def values(self) -> typing.Any | ||
4.源码Demo
# -*- coding:utf-8 -*-
import os, requests
from lxml import etree, html
from lxml.e