Python各种模块程序员

lxml 学习笔记

2017-10-20  本文已影响545人  Moscow1147
Hallstatt 哈尔施塔特

人生苦短,我用Python。

起初,这篇文章是打算来写 XPath 的,可是后来一想,我需要的仅是 XPath 的一部分,我仅仅是打算在写爬虫的时候,抓取特定数据的,并且这是需要结合 lxml 的,So ,索性就来写 lxml 来了。(lxml supports XPath 1.0, XSLT 1.0 and the EXSLT extensions through libxml2 and libxslt in a standards compliant way.这是教程上的一段话,但是XPath现在是有2.0版本的。)

关于教程方面官方网站上给出了三个教程:

lxml is the most feature-rich and easy-to-use library for processing XML and HTML in the Python language.

lxml 是提供了一个 Pythonic API ,并且她也是几乎完全兼容 ElementTree API 的。lxml 的开发团队也是力求减少开发者的学习成本,不过 lxml 的教程感觉一点都不友好。

在看官方教程的时候,发现了一些小疑惑:

lxml 模块并不仅仅是我们在网上搜到的 etree ,lxml 下面还有很多的模块,有 etree 、html 、cssselect 等众多模块。另外我也看到了 BeautifulSoup 。

lxml can make use of BeautifulSoup as a parser backend, just like BeautifulSoup can employ lxml as a parser.

lxml interfaces with BeautifulSoup through the lxml.html.soupparser module.

BeautifulSoup 可以将 lxml 作为解析器,这个我是知道的,但是 lmxl.html.soupparser 可以调用 BeautifulSoup 我就不明白了。刚开始以为理解错误,但是确实在源码中找到的证据,soupparser 模块中引入了 BeautifulSoup ,并且也调用了该函数。

两者之间可以相互调用,并且两者之间的函数也是很相似的,就连 css 选择器两个也都有。有意思了。难道 BeautifulSoup 是 lxml 的一部分?

BeautifulSoup 是在 2004 年发布的。lxml 大约是在 2005 年发布。

2008 年,lxml v2.0 发布,lxml.html 添加到库中;在 v2.0.3 版本中 lxml.html.soupparser 才出现。

直到 2012 年 bs4 发布,BeautifulSoup 才可以选择从内置解析器、html5lib 、lxml 这三个中选一个作为解析器,而之前版本使用的是却是另一个。

显然,这两个是两码事。可是两者之间的区别以及联系是什么(因为相似度有点高),特定的情况下又该做出何种选择?这个疑问先立在这里,容我以后回答。我所知道的是 BeautifulSoup 强大检测编码能力,并且能够以 utf-8 形式输出;lxml 具有速度飞起的文本解析力。

本篇文章的介绍顺序是 lxml.etreeXPathlxml.html

lxml.etree

作为一个强大的 xml 处理模块,该有的功能她都是有的。

若操作一个 XML ,首先要能读写,能将字符串或流读进来解析成 ElementTree ,又能将 ElementTree 转换为字符串或流。在这方面 lxml 提供了几个可用的函数:

剩下就是操作了,增删查改一样也不少,而查找是剩下三个的基础。

etree 对于每种元素都有一个创建函数,比如 Element() 、ElementTree() 、SubElement() 以及 Comment() 。基本所有的函数都是基于这些实例对象的,lxml 的 API 是比较 Pythonic 的,Element 的行为和 list 比较像可以使用 len() 函数切片等,Element 的 attrib 就是一个 dist ;其中 Element 实例拥有 41 个属性和方法,包含了所有:

append() insert()

clear() remove()

find*() get*() iter*() xpath()

set() 以及属性 .tag .attrib .text .tail等的操作

ElementTree 实例拥有的方法较少,常用的大概有 7 种,主要是查找find*() get*() xpath()

Element 的属性介绍:

Element 的方法介绍:

ElementTree 方法介绍:

没有介绍的方法,是前面的类似,或者已经介绍过。

XPath

XPath 是一门在 XML 文档中查找信息的路径语言,W3C 文档:XML Path Language (XPath), Version 1.0

所有的查找都是基于参考定位的,依靠两者之间存在的某种关系,或主从,或平级,这样一步一步的查到。

在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档节点(或称为根节点)。

XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。

下面列出了最有用的路径表达式:

表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。

XPath 通配符可用来选取未知的 XML 元素。

通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型的节点。

通过在路径表达式中使用“|”运算符,可以选取若干个路径,“|”两边的表达式是互相独立的,并非是一个表达式下。

除了上面介绍的还有两个概念需要知道:轴(Axes)谓语

通过以上介绍我们基本可以进行选取节点了,但是有可能选的节点有点多,那么这时候就需要用谓语了。谓语就是用来做过滤的,过滤条件均写在[]中。

这个过滤条件可写内容有很多:运算符表达式、数字、函数以及文字( Literal ,W3C 的英文介绍没仔细看,没太懂 Literal 说的是什么)。

w3school 给的一个例子,比较有代表性吧。

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

Xpath 的轴定于的是相对于当前节点具有某种相同特征的节点集。

轴名称 结果
ancestor 选取当前节点的所有先辈(父、祖父等)。
ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
attribute 选取当前节点的所有属性。
child 选取当前节点的所有子元素。
descendant 选取当前节点的所有后代元素(子、孙等)。
descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following 选取文档中当前节点的结束标签之后的所有节点。
namespace 选取当前节点的所有命名空间节点。
parent 选取当前节点的父节点。
preceding 选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling 选取当前节点之前的所有同级节点。
self 选取当前节点。

每一个step都是由轴名称::NodeTest[谓语]构成。比如:child::*/child::pricechild::*child::price都是一个step

lxml.html

Since version 2.0, lxml comes with a dedicated Python package for dealing with HTML: lxml.html. It is based on lxml's HTML parser, but provides a special Element API for HTML elements, as well as a number of utilities for common HTML processing tasks.

The main API is based on the lxml.etree API, and thus, on the ElementTree API.

lxml.html 是一个专门用来处理 HTML 文档的,虽然他依旧是基于 HTML parser 的,但是她提供了很多有针对性的 API 。这里只作一个简单介绍,深入了解,请查阅官方文档。

首先在解析 HTML 文本上增加了几个方法:

其次对于 HTML 元素,除了之前的方法之外又加了一些:

正如文章开头说的那个, lxml.html.soupparser 可以引入 BeautifulSoup ,甚至可以仅使用 BeautifulSoup 的编码检测模块 UnicodeDammit 。

最后就是可以使用 lxml.html.open_in_browser(lxml_doc) 直接在浏览器中显示文档,甚至可以对文档的表单进行提交操作。

以上都是据自己的理解而写,如有错误之处,欢迎交流。

上一篇 下一篇

猜你喜欢

热点阅读