笔记-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. Chrome浏览器安装vue-devtools插件

    插件功能:方便在浏览器调试vue代码 插件git地址:https://github.com/vuejs/vue-devtools 因为chrome要FQ,打不开,所以不能直接进去安装拓展程序,只能选择 ...

  2. Android基础Activity篇——销毁活动

    销毁活动只需要添加 finish(); 这个方法即可.相当于back键.

  3. Android SQLite数据库之事务的学习

    SQLite是Android系统内置的一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百K的内存就足够了.SQLite不仅支持标准的SQL语法,还遵循了数据库的ACID事务. ...

  4. mysql5.1安装图解教程

    mysql5.1安装图解教程 曾经为了要搭建模拟平台,从内地网站学习到台湾网站,其中必不可少的一项就是MySQL,那时候正好普遍用5.1,所以也很习惯用MySQL5.1版本! 下面就以MySQL5.1 ...

  5. Spring Cloud学习路线

    学习本学习路线学习完,大家将会对微服务.Spring Cloud.Docker.Kubernetes有一个系统.全面的认识.通过学习,将能掌握相关的知识体系,并能够投入到项目实战中去. 本学习路线采用 ...

  6. zabbix3.0问题及解决方法

    一.问题:Zabbix agent on T2 is unreachable for 5 minutes         解决:1.进入zabbix service端 vim /etc/zabbix/ ...

  7. ubuntu 安装 deb 软件包

    参考链接地址 blog.csdn.net/kevinhg/article/details/5934462 sudo dpkg -i xxxx.deb 安装一个 Debian 软件包,如你手动下载的文件

  8. Excel公式巧用-将新值替换旧值,新值为空保留原值

    使用excel时候遇到 将新值替换旧值,新值为空保留原值的问题,简单使用Excel的函数即可以实现.

  9. .net core 2.0 WIndows IIS下发布(WIN 10环境)

    最近在做练习,发布.net core webapi在本机IIS上,使用.net core的文件系统发布到IIS后,出现错误 500.19 观察了下页面如下 查阅资料才知道是少安装了一个DotNetCo ...

  10. 【转】关于Eclipse创建Android项目时,会多出一个appcompat_v7的问题

    问题描述: 使用eclipse创建一个Android项目时,发现project列表中会多创建出一个appcompat_v7项目,再创建一个Android项目时,又会再多出一个appcompat_v7_ ...