笔记-python-lib-lxml

1.      lxml简介

lxml是一个实现解析网页文件的库,python中自带有解析库,但没有lxml方便好用。

The lxml XML toolkit is a Pythonic binding for the C libraries libxml2 and libxslt.

它将这些库的高效与python API的易用结合起来了。

1.1.    安装

pip install lxml

2.      网页解析

2.1.    实例化

lxml提供如下方式输入文本进行实例化:

fromstring():解析字符串

HTML():解析HTML对象

XML():解析XML对象

parse():解析文件类型对象

一般使用HTML或XML;

案例代码:

import lxml.etree

etree_page = etree.HTML(page_data)

page_data为网页源代码,字符串格式;

type(etree_page)

<class 'lxml.etree._Element'>

2.2.    查找

查找常用的有find,findall,xpath,都支持XPATH语法。

find():返回第一个匹配对象,并且xpath语法只能使用相对路径(以’.//’开头);

findall():返回一个标签对象的列表,并且xpath语法只能使用相对路径(以’.//’开头);

xpath():返回一个标签对象的列表,并且xpath语法的相对路径和绝对路径。

返回的元素都是lxml.etree._Element类型;

案例代码:

page_etree = etree.HTML(page_data)

resonse_div = page_etree.findall(‘.//img[@src]’)

2.3.    属性读取和输出

下例代码中et 是一个返回的lxml.etree._Element类对象;

  1. 获取属性:

et.get(‘attribute name’)

et.get(‘src’)

  1. 获取全部属性:

et.attrib

et.attrib[‘src’] 等效于et.get(‘src’)

  1. 获取文本:

et.text

  1. 标签名:

et.tag

  1. 其它:

et.getparent()

et.getchild()

etree.tostring(object)

3.      xpath

lxml etree支持ElementTree和Elements上的find,findall,findtext方法,除此之外作为一个特定的功能扩展,提供了xpath()方法,该方法完全支持XPATH语法。

xpath()方法非常强大,下面是一些常用获取属性的案例,关于更多xpath表达式语法查看xpath文档:

# 得到根节点

>>> root = etree.fromstring(xml)  

>>> print root

<Element bookstore at 0x2c9cc88>

# 选取所有book子元素

>>> root.xpath('book')  

[<Element book at 0x2d88878>, <Element book at 0x2d888c8>]

# 选取根节点bookstore

>>> root.xpath('/bookstore')  

[<Element bookstore at 0x2c9cc88>]

# 选取所有book子元素的title子元素

>>> root.xpath('book/title')  

[<Element title at 0x2d88878>, <Element title at 0x2d888c8>]

# 以根节点为始祖,选取其后代中的title元素

>>> root.xpath('//title')

[<Element title at 0x2d88878>, <Element title at 0x2d888c8>]

# 以book子元素为始祖,选取后代中的price元素

>>> root.xpath('book//price')  

[<Element price at 0x2ca20a8>, <Element price at 0x2d88738>]

# 以根节点为始祖,选取其后代中的lang属性值

>>> root.xpath('//@lang')    

['eng', 'eng']

3.1.    预判(Predicates)

预判是用来查找某个特定的节点或者符合某种条件的节点,预判表达式位于方括号中。

# 选取bookstore的第一个book子元素

>>> root.xpath('/bookstore/book[1]')          

[<Element book at 0x2ca20a8>]

# 选取bookstore的最后一个book子元素

>>> root.xpath('/bookstore/book[last()]')        

[<Element book at 0x2d88878>]

# 选取bookstore的倒数第二个book子元素

>>> root.xpath('/bookstore/book[last()-1]')      

[<Element book at 0x2ca20a8>]

# 选取bookstore的前两个book子元素

>>> root.xpath('/bookstore/book[position()<3]')    

[<Element book at 0x2ca20a8>, <Element book at 0x2d88878>]

# 以根节点为始祖,选取其后代中含有lang属性的title元素

>>> root.xpath('//title[@lang]')     

[<Element title at 0x2d888c8>, <Element title at 0x2d88738>]

# 以根节点为始祖,选取其后代中含有lang属性并且值为eng的title元素

>>> root.xpath("//title[@lang='eng']")

[<Element title at 0x2d888c8>, <Element title at 0x2d88738>]

# 选取bookstore子元素book,条件是book的price子元素要大于35

>>> root.xpath("/bookstore/book[price>35.00]")

[<Element book at 0x2ca20a8>]

# 选取bookstore子元素book的子元素title,条件是book的price子元素要大于35

>>> root.xpath("/bookstore/book[price>35.00]/title")

[<Element title at 0x2d888c8>]

3.2.  通配符

通配符  描述

*   匹配任何元素。

@*  匹配任何属性。

node() 匹配任何类型的节点。

# 选取 bookstore 所有子元素

>>> root.xpath('/bookstore/*')

[<Element book at 0x2d888c8>, <Element book at 0x2ca20a8>]

# 选取根节点的所有后代元素

>>> root.xpath('//*')  

[<Element bookstore at 0x2c9cc88>, <Element book at 0x2d888c8>, <Element title at 0x2d88738>, <Element price at 0x2d88878>, <Element book at 0x2ca20a8>, <Element title at 0x2d88940>, <Element price at 0x2d88a08>]

# 选取根节点的所有具有属性节点的title元素

>>> root.xpath('//title[@*]')  

[<Element title at 0x2d88738>, <Element title at 0x2d88940>]

# 选取当前节点下所有节点。'\n    ' 是文本节点。

>>> root.xpath('node()')

['\n    ', <Element book at 0x2d888c8>, '\n    ', <Element book at 0x2d88878>, '\n']

# 选取根节点所有后代节点,包括元素、属性、文本。

>>> root.xpath('//node()')

[<Element bookstore at 0x2c9cc88>, '\n    ', <Element book at 0x2d888c8>, '\n        ', <Element title at 0x2d88738>, 'Harry Potter', '\n        ', <Element price at 0x2d88940>, '29.99', '\n    ', '\n    ', <Element book at 0x2d88878>, '\n        ', <Element title at 0x2ca20a8>, 'Learning XML', '\n        ', <Element price at 0x2d88a08>, '39.95', '\n    ', '\n']

或条件选取

使用 “|” 运算符,你可以选取符合“或”条件的若干路径。

# 选取所有book的title元素或者price元素

>>> root.xpath('//book/title|//book/price')  

[<Element title at 0x2d88738>, <Element price at 0x2d88940>, <Element title at 0x2ca20a8>, <Element price at 0x2d88a08>]

# 选择所有title或者price元素

>>> root.xpath('//title|//price')  

[<Element title at 0x2d88738>, <Element price at 0x2d88940>, <Element title at 0x2ca20a8>, <Element price at 0x2d88a08>]

# 选择book子元素title或者全部的price元素

>>> root.xpath('/bookstore/book/title|//price')

[<Element title at 0x2d88738>, <Element price at 0x2d88940>, <Element title at 0x2ca20a8>, <Element price at 0x2d88a08>]

3.3.  XPath 坐标轴

坐标轴用于定义当对当前节点的节点集合。

坐标轴名称 含义

ancestor   选取当前节点的所有先辈元素及根节点。

ancestor-or-self  选取当前节点的所有先辈以及当前节点本身。

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

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

descendant 选取当前节点的所有后代元素。

descendant-or-self   选取当前节点的所有后代元素以及当前节点本身。

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

following-sibling 选取当前节点之后的所有同级节点

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

parent 选取当前节点的父节点。

preceding  选取当前节点的开始标签之前的所有节点。

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

self   选取当前节点。

位置路径表达式

位置路径可以是绝对路径,也可以是相对路径。绝对路径以 “/” 开头。每条路径包括一个或多个步,每步之间以 “/” 分隔。

绝对路径:/step/step/…

相对路径:step/step/…

每步根据当前节点集合中的节点计算。

步(step)包括三部分:

坐标轴(axis):定义所选节点与当前节点之间的关系。

节点测试(node-test):识别某个坐标轴内部的节点。

预判(predicate):提出预判条件对节点集合进行筛选。

步的语法:坐标轴::节点测试[预判]

# child::nodename 选取所有属于当前节点的 book 子元素,等价于 './nodename'

>>> root.xpath('child::book')

[<Element book at 0x2d888c8>, <Element book at 0x2d88878>]

>>> root.xpath('./book')

[<Element book at 0x2d888c8>, <Element book at 0x2d88878>]

# attribute::lang 选取当前节点的 lang 属性,等价于 './@lang'

>>> root.xpath('//*[@lang]')[0].xpath('attribute::lang')

['eng']

>>> root.xpath('//*[@lang]')[0].xpath('@lang')

['eng']

# child::* 选取当前节点的所有子元素,等价于 './*'

>>> root.xpath('child::*')

[<Element book at 0x2d88878>, <Element book at 0x2d88738>]

>>> root.xpath('./*')

[<Element book at 0x2d88878>, <Element book at 0x2d88738>]

# attribute::* 选取当前节点的所有属性,等价于 './@*'

>>> root.xpath('//*[@*]')[0].xpath('attribute::*')

['eng']

>>> root.xpath('//*[@*]')[0].xpath('@*')

['eng']

# child::text() 选取当前节点的所有文本子节点,等价于 './text()'

>>> root.xpath('child::text()')

['\n    ', '\n    ', '\n']

>>> root.xpath('./text()')

['\n    ', '\n    ', '\n']

# child::node() 选取当前节点所有子节点,等价于 './node()'

>>> root.xpath('child::node()')

['\n    ', <Element book at 0x2d88878>, '\n    ', <Element book at 0x2d88738>, '\n']

>>> root.xpath('./node()')

['\n    ', <Element book at 0x2d88878>, '\n    ', <Element book at 0x2d88738>, '\n']

# descendant::book 选取当前节点所有 book 后代,等价于 './/book'

>>> root.xpath('descendant::book')

[<Element book at 0x2d88878>, <Element book at 0x2d88738>]

>>> root.xpath('.//book')

[<Element book at 0x2d88878>, <Element book at 0x2d88738>]

# ancestor::book 选取当前节点所有 book 先辈

>>> root.xpath('.//title')[0].xpath('ancestor::book')

[<Element book at 0x2d88878>]

# ancestor-or-self::book 选取当前节点的所有 book 先辈以及如果当前节点是 book 的话也要选取

>>> root.xpath('.//title')[0].xpath('ancestor-or-self::book')

[<Element book at 0x2d88878>]

>>> root.xpath('.//book')[0].xpath('ancestor-or-self::book')

[<Element book at 0x2d88878>]

>>> root.xpath('.//book')[0].xpath('ancestor::book')

[]

# child::*/child::price 选取当前节点的所有 price 孙节点,等价于 './*/price'

>>> root.xpath('child::*/child::price')

[<Element price at 0x2d88878>, <Element price at 0x2d88738>]

>>> root.xpath('./*/price')

[<Element price at 0x2d88878>, <Element price at 0x2d88738>]

4. 附录:

4.1.    正则,lxml与beautifulsoup4

在解析网页时常用的库有正则,lxml,beautifulsoup4,三者各有优劣:

  1. 正则:最原始的字符串解析,写起来麻烦一些;
  2. lxml:c实现底层,效率较高;
  3. beautifulsoup4:python原生库,使用简单,但效率较低,也容易出现解析错误。从效率上来讲,lxml 确实比 BeautifulSoup 高效得多,每次分步调试时,soup 对象的生成有很明显的延迟,而 lxml.etree.HTML(html) 方式则在 step over 的一瞬间便构建成功了一个可执行 xpath 操作的对象,速度惊人。原理上来讲,bs4 是用 python 写的,lxml 是 c 语言实现的,而且 BeautifulSoup 是基于 DOM 的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多。而lxml只会进行局部遍历。

笔记-python-lib-lxml的更多相关文章

  1. 笔记-python -asynio

    笔记-python -asynio 1.      简介 asyncio是做什么的? asyncio is a library to write concurrent code using the a ...

  2. Windows下Python安装lxml

    1.下载easy_install的安装包,下载地址:https://pypi.Python.org/pypi/setuptools 我是Windows7,所以直接下载Windows(Simplify) ...

  3. 笔记-python操作mysql

    笔记-python操作mysql 1.      开始 1.1.    环境准备-mysql create database db_python; use db_python; create tabl ...

  4. 笔记-python异常信息输出

    笔记-python异常信息输出 1.      异常信息输出 python异常捕获使用try-except-else-finally语句: 在except 语句中可以使用except as e,然后通 ...

  5. 笔记-python lib-pymongo

    笔记-python lib-pymongo 1.      开始 pymongo是python版的连接库,最新版为3.7.2. 文档地址:https://pypi.org/project/pymong ...

  6. 笔记-python tutorial-9.classes

    笔记-python tutorial-9.classes 1.      Classes 1.1.    scopes and namespaces namespace: A namespace is ...

  7. MongoDB学习笔记:Python 操作MongoDB

    MongoDB学习笔记:Python 操作MongoDB   Pymongo 安装 安装pymongopip install pymongoPyMongo是驱动程序,使python程序能够使用Mong ...

  8. 在MacOS下Python安装lxml报错xmlversion.h not found 报错的解决方案

    最近在看一个自动化测试框架的问题,需要用到Lxml库,下载lxml总是报错. 1,使用pip安装lxml pip install lxml 2,然后报错了,报错内容是: In file include ...

  9. 【python】python安装lxml报错【2】

    cl : Command line warning D9025 : overriding '/W3' with '/w' lxml.etree.c c:\docume~\admini~.chi\loc ...

  10. 机器学习实战笔记(Python实现)-08-线性回归

    --------------------------------------------------------------------------------------- 本系列文章为<机器 ...

随机推荐

  1. pm2的的常用命令及用法

    使用pm2启动静态文件服务器的方法如下: pm2 serve path port pm2 serve . 9001 这样就可以把当前文件夹下的静态文件跑起来了,而且端口号是9001, 同样也支持进阶的 ...

  2. 绘图之Canvas学习

    一  Canvas的用法   博客:http://blog.taorenjia.com/?p=237    1.drawCircle(float cx, float cy, float radius, ...

  3. BarCode条形码生成库

    一.Barcode生成条形码的类库 二.示例 新建mvc空项目,添加Nuget引用 主要代码 // // GET: /Home/ public FileContentResult Index() { ...

  4. JavaScript基础:逻辑运算符——&&和||(短路判断)和!

    一.&&:所有条件都为true,返回true:只要有一个是false,返回false:不一定返回boolean类型值 1.可以操作任意类型的数据,不只是布尔型:(除了null.unde ...

  5. JavaScript 编写随机四位数验证码(大小写字母和数字)

    1.JavaScript编写随机四位数验证码,用到的知识点为: a.Math对象的随机数:Math.random() b.Math对象的取整    :Math.floor() c.处理所需要的下标个数 ...

  6. iOS自动化打包发布(fastlane)

    一.FastLane介绍 1.1 FastLane是什么? FastLane是一种配置iOS和Android自动化Beta部署和发布的最简单的方法之一.它可以简化一些乏味.单调.重复的工作,像截图.代 ...

  7. IOS 拼接按钮文字

    NSMutableString *tempAnswerTitle=[[NSMutableString alloc]init]; for(UIButton *answerBtn in self.answ ...

  8. python 面向对象(一)--类(class)和实例(Instance)

    面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可 ...

  9. C语言中volatile关键字的作用[转]

    一.前言 1.编译器优化介绍: 由于内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问.另外在现代CPU中指令的执行并不一定严格按照顺序执行,没 ...

  10. 控制元素的div属性

    1.需求分析 改变元素的宽.高.颜色.显示.重置等属性. 2.技术分析 基础的css.html.js 3.详细分析 如图,单击按钮,改变元素属性: 3.1 HTML部分 根据视图不难发现,内容分两大不 ...