广州番禺Python爬虫小班周末班培训
第四期线下Python爬虫小班周末班已经开课了,授课详情请点击:http://chipscoco.com/?id=232
7.2.1 lxml简介
lxml是什么呢?打开官网来一观究竟:
lxml is the most feature-rich and easy-to-use library for processing XML and HTML in the Python language.
lxml的官网地址:https://lxml.de/
大意为:lxml是一个用Python语言实现的,包含多种特性、易于使用的库,用来处理XML和HTML。在7.1节的内容中,讲到了正则表达式,通过编写正则表达式可以对HTML进行解析。本文介绍的lxml不仅可以解析XML,还可以高效、快速地解析HTML。直接使用已封装好的,成熟稳定的库,可以让程序员对网页的解析处理变得更加简单。
7.2.2安装lxml
进入windows或Linux命令行,在命令行中执行pip install lxml,即可完成lxml的安装。安装完毕以后,进入Python交互模式,执行import lxml,如未抛出任何异常,说明安装成功。
lxml的安装依赖于libxml2等库,在Linux系统中安装出错时,读者可参考官网的这篇安装教程:https://lxml.de/installation.html
7.2.3 XPath语法
使用lxml解析HTML,需要熟悉XPath语法。XPath是XML路径语言,用来定位XML文档中的节点。XML与HTML在文档结构上是一致的,所以当然也可以使用XPath来定位HTML中的节点。那么什么是文档节点呢?请读者先看下面的HTML代码:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>薯条老师的官方教程:www.chipscoco.com</title> </head> <body> </body> </html>
在上面的代码中,最外层的节点是html,head与body是其子节点,这是一种父子节点的关系。父子节点关系是一种递归的概念,比如某一个子节点也可以是其它节点的父节点,例如在上面的代码中,head节点是html节点的子节点,同时也是meta和title的父节点。
父与子的节点关系很好理解,除了父子节点,还有一种兄弟节点。如果节点间是平级的关系,那么处于这种关系的节点被称为兄弟节点。例如meta节点与title节点就是兄弟节点。
厘清了节点间的关系以后,需要再学习XPath中的路径表达式,以下是XPath中常用的路径表达式符号:
特殊符号 | 描述 |
/ | 表示从根节点位置进行定位,例如/html,表示定位根节点html |
// | 以匹配的当前节点作为起始节点,例如//div,表示定位文档中的所有div节点 |
. | 匹配当前节点 |
.. | 匹配父节点 |
@ | 属性选择器,匹配包含某属性的节点,例如//a[@href='www.chipscoco.com'],表示定位文档中所有href属性为www.chipscoco.com的a节点 |
* | 通配符,用来匹配任何节点,例如//div/*,用来定位div节点下的所有节点 |
| | 连接符,用来连接路径表达式,例如//h1 | //p,用来定位所有h1节点以及所有p节点 |
and,or | 逻辑运算符,用来进行逻辑判断。例如a[@href='www.chipscoco.com' and @class='nav'],用来定位文档中所有href属性为www.chipscoco.com且class属性为nav的a节点 |
当需要对定位的节点进行更细粒度的筛选时,可以使用XPath中的谓语。谓语被定义在[]中,[]中可以输入位置索引,表示定位某一个具体位置的元素,例如//div/img[1],表示选择所有div节点下的第一个img节点。以下是常用的谓语:
谓语 | 描述 |
[位置索引] | 位置索引从0开始编号,表示第一个元素,例如//div/p[0],表示选择所有div节点下的第一个p节点。 也可以使用内置方法来获得指定位置的节点,比如last()用来获取最后一个元素,last()-1表示倒数第二个,以此类推。position方法则用来指定某一段范围,常与关系运算符结合使用,例如//div/p[position() < 2],用来选择所有div节点下的前2个p节点。 |
[属性选择] | 即在[]中使用属性选择器,例如//div/a[href]表示选择div节点下的包含href属性的所有a节点。//div/a[href='www.chipscoco.com'],表示选择文档中div节点下的href属性值为www.chipscoco.com的所有a节点。 |
[模糊匹配] | 使用contains,starswith等方法来进行模糊查找。contains表示选择属性包含某内容的节点,starswith则表示选择属性中以某关键字作为前缀的节点。例如//input[contains(@name,'se')],表示选择所有name属性中包含se的 input节点。 |
以上是常用的路径表达式符号及谓语,在实际使用中,会将各种路径符号和谓语组合成一个复杂的路径表达式,以对网页内容进行提取。定位到节点以后,再通过@符号来提取出属性值,通过text()方法来提取出标签文本。例如//div/a/@href,用来提取出所有div节点下的a节点的herf属性值。//div/a/text()用来提取出所有div节点下的a节点的文本。
7.2.4 解析HTML
熟悉了XPath的语法以后,现在通过lxml来对HTML进行解析。使用lxml对HTML进行解析,请读者按照以下3个步骤进行操作:
① 从lxml中导入etree模块
② 执行etree模块的HTML方法构建etree的Element对象
HTML方法的常用参数:HTML(text),text表示HTML文本。
③ 通过Element对象的xpath方法来解析HTML
代码实例1-解析所有title标签的文本:
from lxml import etree HTML= """ <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>薯条老师的官方教程:www.chipscoco.com</title> </head> <body> </body> </html> """ etree = etree.HTML(HTML) o = etree.xpath("//title/text()") print(o)
输出结果:
['薯条老师的官方教程:www.chipscoco.com']
代码实例2-解析所有div标签下的所有img标签的src属性:
from lxml import etree HTML= """ <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>薯条老师的官方教程:www.chipscoco.com</title> </head> <body> <div> <img src="/media/images/logo.png" /> <ul> <li><img src="http://justtest.com/one.jpg"/></li> </ul> </div> <ul> <li> <a href="www.chipscoco.com">薯条老师的官方教程</a></li> <li> <a href="www.chipscoco.cn">橙子在线编程</a></li> </ul> </body> </html> """ etree = etree.HTML(HTML) o = etree.xpath("//div//img/@src") print(o)
输出结果:
['/media/images/logo.png', 'http://justtest.com/one.jpg']
注意,以上代码中的路径表达式为//div//img,表示获取div节点下的所有img节点,包括所有后代节点。如果路径表达式为//div/img,那么只能匹配到div节点下的img子节点。读者可以将代码中的路径表达式改为//div/img/@src,那么输出的只是['/media/images/logo.png']。
代码实例3-解析ul节点下的li子节点的a:
from lxml import etree HTML= """ <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>薯条老师的官方教程:www.chipscoco.com</title> </head> <body> <ul> <li> <a href="www.chipscoco.com">薯条老师的官方教程</a></li> <li> <a href="www.chipscoco.cn">橙子在线编程</a></li> <li> <a href="www.shadows.com">侠影七三</a></li> <li> <img src="/media/images/cover.png" /></li> </ul> </body> </html> """ etree = etree.HTML(HTML) li_container = etree.xpath("//ul/li") for li in li_container: # 列表中的每一个元素均为Element对象 # xpath中的.表示当前节点 o = li.xpath("./a[contains(@href, 'chipscoco')]/@href") print(o) if o else _
输出结果:
['www.chipscoco.com']
['www.chipscoco.cn']
以上的实例代码演示的是比较基础的操作,更复杂的解析表达式无非是将XPath中的路径表达式进行组合。读者需要先熟练掌握最基础的操作,然后再根据不同的需求来进行灵活组合。HTML文档数据,读者可以根据第六章中学过的知识,调用requests等库来对指定页面进行请求。
7.2.5 高薪就业班
(1) Python后端工程师高薪就业班,月薪10K-15K,免费领取课程大纲
(2) Python爬虫工程师高薪就业班,年薪十五万,免费领取课程大纲
(3) Java后端开发工程师高薪就业班,月薪10K-20K, 免费领取课程大纲
(4) Python大数据工程师就业班,月薪12K-25K,免费领取课程大纲
扫码免费领取学习资料: