笔记-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. POS开发问题 - 多个弹出框的实现

    业务场景如下图: 页面出现提示框:    点击确定,隐藏上面的弹出框, 继续弹出提示:  点击确定隐藏上面的弹出框,继续弹出下面提示: 点击确定隐藏上面的弹出框,继续弹出下面提示: 点击确定,跳转页面 ...

  2. 在使用angular和swiper插件中的一些问题

    在使用angular获取swiper图片的时候swiper就不会轮播. 解决方法: 1.使用计时器的方法,不是最优 settimeOut(function(){ mySwiper = new Swip ...

  3. Chrome浏览器安装vue-devtools插件

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

  4. Windows环境下搭建Linux虚拟机

    下载VMware workstation 和 CentOs 或者 redHat .Ubuntu

  5. Ubuntu 如何将桌面上的Home中的文件夹除去

    安装Ubuntu后, 由于无法用Terminal(终端)进入带中文的文件夹,会引起很多操作不便.很多朋友想到了将它们都改成中文,但是当再次开机重启使却会发现,原本光洁的桌面现在竟然出现了一堆文件夹?? ...

  6. 触发transition的几种方式--转

    鼠标单击 获取焦点 或元素发生任何改变,怎么说呢,目前的理解是,元素发生了什么改变,使得它跟以前不一样了.比如同样是p元素,先有一个样式.后来这个p被hover了.被focus了.或者通过另外一条途径 ...

  7. java 通过接口在后台管理器中生成数据

    需求:测试人员在后台批量添加数据很麻烦,特别是针对一款商品配置了英语,还需要手动添加法语.俄语.阿拉伯语,很麻烦,但是因为没有项目组配合,做个小工具批量生成数据就只有自己去研究了 第一步:通过抓包工具 ...

  8. php curl使用总结(一)

    今天和第三方支付做对接的时候,在本地用wamp(php版本5.4.14)运行他们的支付demo的时候,报了一个错误.loadXML函数中不能传空值.排查代码的时候,发现他们用了curl,我以前也接触过 ...

  9. cudaMalloc和cudaMallocPitch

    原文链接 偶有兴趣测试了一下题目中提到的这两个函数,为了满足对齐访问数据,咱们平时可能会用到cudamallocPitch,以为它会带来更高的效率.呵呵,这里给出一段测试程序,大家可以在自己的机器上跑 ...

  10. 前端HTML之表单

    1.列表标签 1.1无序列表<ul>,当中每一层都是<li>    <ul> <li>张三</li> <li>李四</li ...