lxml模块(应⽤xpath技术)
⼀、lxml介绍
  第三⽅库lxml是第⼀款表现出⾼性能特征的python xml库,天⽣⽀持Xpath1.0、XSLT1.0、定制元素类,甚⾄python风格的数据绑定接⼝。lxml是通过Cpython实现的,构建在两个C库上(libxml2和libxslt),为执⾏解析、序列化、转换等核⼼任务提供了主要动⼒,是爬⾍处理⽹页数据的⼀件利器。
  lxml对xml和html都有很好的⽀持,分别使⽤ 和 lxml.html 两个模块。
1、安装第三⽅lxml模块
# 通过pip直接下载安装
pip install lxml
# 通过git克隆源码进⾏下载安装
git clone github/lxml/lxml.git  lxml
2、lxml.html和模块
  lxml.html&这两个模块是最常⽤的HTML⽂档和XML⽂档解析模块。
  HTML(HyperText Markup Language)超⽂本标记语⾔。
  XML(Extensible Markup Language)可扩展标记语⾔。
3、lxml官⽅⽂档
⼆、Xpath语法
1、选取节点
  Xpath使⽤路径表达式在XML⽂档中选取节点。节点是通过沿着路径或者step来选取的。常⽤的路径表达式如下:
表达式描述
nodename选取此节点的所有⼦节点
/从根节点选取
//从匹配选择的当前节点选择⽂档的节点,⽽不考虑它们的位置
.选取当前节点
..选取当前节点的⽗节点
@选取属性
下⾯为⼀些路径表达式及表达式结果:
路径表达式结果
bookstore选取 bookstore 元素的所有⼦节点
/bookstore选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book选取属于 bookstore 的⼦元素的所有 book 元素
//book选取所有 book ⼦元素,⽽不管它们在⽂档中的位置。
bookstore//book选择属于 bookstore 元素的后代的所有 book 元素,⽽不管它们位于 bookstore 之下的什么位置。
//@lang选取名为 lang 的所有属性。
2、谓语(Predicates)
  谓语⽤来查某个特定的节点或者包含某个指定的值的节点。谓语被嵌在⽅括号中。
  下⾯为⼀些带有谓语的路径表达式,及表达式结果:
路径表达式结果
/bookstore/book[1]选取属于 bookstore ⼦元素的第⼀个 book 元素。
/bookstore/book[last()]选取属于 bookstore ⼦元素的最后⼀个 book 元素。
/bookstore/book[last()-1]选取属于 bookstore ⼦元素的倒数第⼆个 book 元素。
/bookstore/book[position()❤ ]选取最前⾯的两个属于 bookstore 元素的⼦元素的 book 元素。
//title[@lang]选取所有拥有名为 lang 的属性的 title 元素。
/bookstore/book[price>35.00]/title选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须⼤于 35.00。
路径表达式结果
3、选取未知节点
  XPath通配符可⽤来选取未知的XML元素。
通配符描述
*匹配任何元素节点
@*匹配任何属性节点
node()匹配任何类型的节点
  下⾯为⼀些带有通配符的路径表达式,及表达式结果:
路径表达式结果
/bookstore/*选取 bookstore 元素的所有⼦元素。
//*选取⽂档中的所有元素。
/
/title[@*]选取⽂档中的所有元素。
4、选取若⼲路径
  通过在路径表达式中使⽤“|”运算符,您可以选取若⼲个路径。
下⾯为⼀些带有"|"运算符的路径表达式,及表达式结果:
路径表达式结果
//book/title//book/price
//title//price
/bookstore/book/title//price
5、Xpath运算符
  下⾯列出了可⽤再XPath表达式中运算符:
运算符描述实例返回值
计算两个节点集//book
+加法  6 + 410
–减法  6 – 42
*乘法  6 * 424
div除法8 div 42
=等于price=9.80如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。
!=不等于price!=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
<⼩于price<9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
<=⼩于或等于price<=9.80如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
>⼤于price>9.80如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
>=⼤于或等于price>=9.80如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。
or或price=9.80 or price=9.70如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。
and与price>9.00 and price<9.90如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。
mod计算除法的余数5 mod 21
6、参考⽂档
三、爬⾍中运⽤XPath
1、XPath在爬⾍中的使⽤流程
1. 下载:pip install lxml
2. 导包:from lxml import etree
3. 创建etree对象进⾏指定数据的解析
本地:
etree=etree.parse('本地⽂件路径')
etree.xpath('xpath表达式')
etree=etree.HTML('⽹络请求到的页⾯数据')
etree.xpath('xpath表达式')
2、常⽤的Xpath表达式
属性定位:
#到class属性值为song的div标签
//div[@class="song"]
层级&索引定位:
#到class属性值为tang的div的直系⼦标签ul下的第⼆个⼦标签li下的直系⼦标签a
//div[@class="tang"]/ul/li[2]/a
逻辑运算:
#到href属性值为空且class属性值为du的a标签
xpath语法 python
//a[@href="" and @class="du"]
模糊匹配:
//div[contains(@class, "ng")]
//div[starts-with(@class, "ta")]
取⽂本:
# /表⽰获取某个标签下的⽂本内容
# //表⽰获取某个标签下的⽂本内容和所有⼦标签下的⽂本内容
//div[@class="song"]/p[1]/text()
//div[@class="tang"]//text()
取属性:
/
/div[@class="tang"]//li[2]/a/@href
3、使⽤⽰例
  创建本地html⽂件来测试Xpath数据解析。
(1)test.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>测试bs4</title>
</head>
<body>
<div>
<p>百⾥守约</p>
</div>
<div class="song">
<p>李清照</p>
<p>王安⽯</p>
<p>苏轼</p>
<p>柳宗元</p>
<a href="www.song/" title="赵匡胤" target="_self">
<span>this is span</span>
宋朝是最强⼤的王朝,不是军队的强⼤,⽽是经济很强⼤,国民都很有钱</a>
<a href="" class="du">总为浮云能蔽⽇,长安不见使⼈愁</a>
<img src="www.baidu/meinv.jpg" alt="" />
</div>
<div class="tang">
<ul>
<li><a href="www.baidu" title="qing">清明时节⾬纷纷,路上⾏⼈欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>  <li><a href="www.163" title="qin">秦时明⽉汉时关,万⾥长征⼈未还,但使龙城飞将在,不教胡马度阴⼭</a></li>  <li><a href="www.126" alt="qi">岐王宅⾥寻常见,崔九堂前⼏度闻,正是江南好风景,落花时节⼜逢君</a></li>
<li><a href="www.sina" class="du">杜甫</a></li>
<li><a href="www.dudu" class="du">杜牧</a></li>
<li><b>杜⼩⽉</b></li>
<li><i>度蜜⽉</i></li>
<li><a href="www.haha" id="feng">凤凰台上凤凰游,凤去台空江⾃流,吴宫花草埋幽径,晋代⾐冠成古丘</a></li>  </ul>
</div>
</body>
(2)爬⾍脚本⽂件test.py
from lxml import etree
# 创建etree对象进⾏制定数据解析
tree = etree.parse('./test.html')    # 解析本地⽂件
# 属性定位:根据指定的属性定位到指定的节点标签
# tree.xpath('//div[@class="song"]')
"""
[<Element div at 0x10dbead88>]
"""
# 层级&索引定位
# tree.xpath('//div[@class="tang"]/ul/li[2]/a')  # 定位到第⼆个li中的a标签"""
[<Element a at 0x10e30ab48>]
"""
# 逻辑定位  //a:整个源码下的a标签
# [@href="" and @class="du"] href为空,class属性为du
# tree.xpath('//a[@href="" and @class="du"]')
"""
[<Element a at 0x10e2a8e88>]
"""
# 模糊匹配
# tree.xpath('//div[contains(@class, "ng")]')
# tree.xpath('//div[starts-with(@class, "ta")]')
"""
[<Element div at 0x10dbea548>, <Element div at 0x10e392348>]
[<Element div at 0x10dabd688>]
"""
# 取⽂本
# /text()获取当前标签中直系存储的⽂本数据
# tree.xpath('//div[@class="song"]/p[1]/text()')    # song的div下的第⼀个p⼦标签# 输出:['李清照']
# //text()获取tang这个div标签下所有⼦标签中存储的⽂本数据
# tree.xpath('//div[@class="tang"]//text()')
"""
['\n\t\t',
'\n\t\t\t',
'清明时节⾬纷纷,路上⾏⼈欲断魂,借问酒家何处有,牧童遥指杏花村',
'\n\t\t\t',
'秦时明⽉汉时关,万⾥长征⼈未还,但使龙城飞将在,不教胡马度阴⼭',
'\n\t\t\t',
'岐王宅⾥寻常见,崔九堂前⼏度闻,正是江南好风景,落花时节⼜逢君',
'\n\t\t\t',
'杜甫',
'\n\t\t\t',
'杜牧',
'\n\t\t\t',
'杜⼩⽉',
'\n\t\t\t',
'度蜜⽉',
'\n\t\t\t',
'凤凰台上凤凰游,凤去台空江⾃流,吴宫花草埋幽径,晋代⾐冠成古丘',
'\n\t\t',
'\n\t']
"""
"""
['www.163']
"""
四、XPath插件
  xpath插件的作⽤:可以直接将xpath表达式作⽤于浏览器的⽹页当中。
1、chrome安装xpath插件
(1)更多⼯具-》扩展程序-》开启右上⾓开发者模式
(2)将xpath插件拖动到⾕歌浏览器拓展程序(更多⼯具)中,安装成功
2、插件使⽤
  开启和关闭xpath插件的快捷键:Ctrl-Shift-X (or Control-Shift-X on OS X), or click the XPath Helper button in the toolbar, to open the XPath Helper console。
  以糗事百科为例使⽤插件:
  右边⽅框输出的是xpath表达式输出的结果,这⾥输出的是div对应的数据值。
  使⽤完再次点击Control-Shift-X来关闭xpath插件。未来在程序中设计好xpath表达式之后,⼀定要⽤xpath插件做⼀下表达式的验证。
五、xpath项⽬演练
  需求:使⽤xpath对段⼦⽹中的段⼦内容和标题进⾏解析,持久化存储。
1、先⽤xpath插件验证xpath表达式
  可⽤如下xpath表达式获取所有的li标签,段⼦内容和标题都被包含在li标签中。
2、爬⾍代码实现
import requests
from lxml import etree
# 1.指定url
url = 'ishuo/joke'
# 2.发起请求
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
}
response = (url=url, headers=headers)
# 3.获取页⾯内容
page_text =
# 4.数据解析
tree = etree.HTML(page_text)
# 获取所有的li标签(已经经过了xpath插件验证)
li_list = tree.xpath('//div[@id="list"]/ul/li')
# print(li_list)
'''
[<Element li at 0x10e32c248>, <Element li at 0x10e30ae88>,...,<Element li at 0x10ef5bfc8>]
# 注意:Element类型的对象可以继续调⽤xpath函数,对该对象表⽰的局部内容进⾏指定内容的解析
'''

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。