大家好,我是Brook!
之前在爬虫解析数据的时候,自己几乎都是用正则表达式,Python中自带的re模块来解析数据。利用正则表达式解析数据的确很强大,但是表达式写起来很麻烦,有时候需要多次尝试;而且速度相对较慢。以后会专门写一篇关于Python正则的文章。
本文介绍的是如何快速入门另一种数据解析工具:Xpath。
XPath (XML Path)
是一门在 XML 文档中查找信息的语言。XPath
可用来在XML
文档中对元素和属性进行遍历。
XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。
快速入门网站:https://www.w3schools.com/xml/default.asp
MacOS中安装非常简单:
pip install lxml
Linux中的安装以Ubuntu为例:
sudo apt-get install python-lxml
Windows中的安装请自行百度,肯定会有教程的,就是过程相对会比较麻烦些。
如何检验安装是否成功?命令行中import lxml
没有报错,即表示安装成功!
如何实例化etree对象?
Xpath解析数据的时候有3个特别重要的符号:
下面是常见的Xpath路径表达式:
在Xpath表达式式中是直接支持运算符的:
因为Xpath解析数据基本上都是和HTML元素相关的结构化数据,所以下面介绍了非常基础的HTML知识。
HTML 元素指的是从开始标签(start tag)到结束标签(end tag)的所有代码。基本语法:
关于空元素的使用:在开始标签中添加斜杠,比如<br />
,是关闭空元素的正确方法,HTML、XHTML 和 XML 都接受这种方式。
属性
值
描述
class | classname | 规定元素的类名(classname) |
id | id | 规定元素的唯一 id |
style | style_definition | 规定元素的行内样式(inline style) |
title | text | 规定元素的额外信息(可在工具提示中显示) |
HTML中标题共有6级。
标题(Heading)是通过 <h1> - <h6>
等标签进行定义的。<h1>
定义最大的标题,<h6>
定义最小的标题。
使用Xpath解析数据之前,我们需要先导入库,同时实例化一个etree对象:
# 导入库
from lxml import etree
# 实例化解析对象
tree = etree.parse("test.html")
tree
下面是待解析的原数据test.html:
<html lang="en">
<head>
<meta charset="utf-8" />
<title>古代诗人及作品</title>
</head>
<body>
<div>
<p>诗人姓名</p>
</div>
<div class="name">
<p>李白</p>
<p>白居易</p>
<p>李清照</p>
<p>杜甫</p>
<p>王安石</p>
<a href="http://wwww.tang.com" target="_self" title="李世民">
<span> this is span </span>
古代诗人写的诗词真的非常棒</a>
<a class="du" href="">床前明月光,疑是地上霜</a>
<img alt="" src="http://www.baidu.com/tang.jpg" />
</div>
<div class="tang">
<ul>
<li><a href="http://www.baidu.com" title="百度">朝辞白帝彩云间,千里江陵一日还</a></li>
<li><a href="http://www.sougou.com" title="搜狗">清明时节雨纷纷,路上行人欲断魂</a></li>
<li><a alt="360" href="http://www.360.com">秦时明月汉时关,万里长征人未还</a></li>
<li><a href="http://www.sina.com" title="必应">君子赠人以言,庶人赠人以财</a></li>
<li><b>苏轼</b></li>
<li><i>苏洵</i></li>
<li><a href="http://www.google.cn" id="谷歌">欢迎使用谷歌浏览器</a></li>
</ul>
</div>
</body>
</html>
比如想获取title标签中的内容:古代诗人及作品
title = tree.xpath("/html/head/title")
title
通过上面的结果发现:每个Xpath解析的结果都是一个列表
如果想取得标签中的文本内容,使用text():
# 从列表中提取相应内容
title = tree.xpath("/html/head/title/text()")[0] # 索引0表示取得第一个元素值
title
比如我们想获取div标签的内容,原数据中有3对div标签,结果是列表中含有3个元素:
1、使用单斜线/:表示根节点html开始定位,表示的是一个层级
2、中间使用双斜线//:表示跳过中间的层级,表示的是多个层级
3、开头部位使用双斜线//:表示从任意位置开始
使用属性定位的时候直接在标签后面跟上[@属性名="属性值"]
:
name = tree.xpath('//div[@class="name"]') # 定位class属性,值为name
name
Xpath中索引是从1开始,和python中的索引从0开始是不同的。
比如想定位div标签下class属性(值为name)下的全部p标签:5对p标签,结果应该是5个元素
# 获取全部数据
index = tree.xpath('//div[@class="name"]/p')
index
如果我们想获取其中的第3个p标签:
# 获取单个指定数据:索引从1开始
index = tree.xpath('//div[@class="name"]/p[3]') # 索引从1开始
index
第一种方法:text()方法
1、获取具体某个标签下面的元素:
# 1、/:单个层级
class_text = tree.xpath('//div[@class="tang"]/ul/li/b/text()')
class_text
# 2、//:多个层级
class_text = tree.xpath('//div[@class="tang"]//b/text()')
class_text
2、某个标签下面的多个内容
比如想获取p标签下面的全部内容:
# 获取全部数据
p_text = tree.xpath('//div[@class="name"]/p/text()')
p_text
比如想获取第3个p标签下面的内容:
# 获取第3个标签内容
p_text = tree.xpath('//div[@class="name"]/p[3]/text()')
p_text
如果是先获取p标签中的全部内容,结果是列表,再使用python索引获取,注意索引为2:
非标签直系内容的获取:
标签直系内容的获取:结果为空,直系的li标签中没有任何内容
如果想获取li标签的全部内容,可以将下面的a、b、i标签合并起来,使用竖线|
# 同时获取li标签下面a/b/i标签的内容,相当于是li标签全部的内容
abi_text = tree.xpath('//div[@class="tang"]//li/a/text() | //div[@class="tang"]//li/b/text() | //div[@class="tang"]//li/i/text()')
abi_text
如果想获取属性的值,在最后的表达式中加上:@+属性名,即可取出相应属性的值
1、获取单个属性的值
2、获取属性的多个值
利用Xpath来获取某小说网站上古龙的全部小说名称(name)和URL地址(url),古龙简介:
本名熊耀华,江西人;中国台湾淡江英专(即淡江大学前身)毕业(一说肄业)。少年时期便嗜读古今武侠小说及西洋文学作品,一般多以为他是受到吉川英治、大小仲马、海明威、杰克伦敦、史坦贝克小说乃至尼采、沙特等西洋哲学的影响启迪。(古龙自己也说过“我喜欢从近代日本及西洋小说‘偷招’。”) 故能日新又新,後来居上,且别开武侠小说新境界。
爬取的信息在这个网站上:https://www.kanunu8.com/zj/10867.html,下图是全部的小说名称:
通过查看网页的源码,我们发现名称和URL地址全部在下面的标签中:
每个tr标签下面有3个td标签,代表3个小说,一个td包含地址和名称
当我们点击具体某个小说,比如“绝代双骄”就可以进去该小说的具体章节页面:
发送网页请求获取到源码
import requests
from lxml import etree
import pandas as pd
url = 'https://www.kanunu8.com/zj/10867.html'
headers = {'user-agent': '请求头'}
response = requests.get(url = url,headers = headers)
result = response.content.decode('gbk') # 该网页需要通过gbk编码来解析数据
result
1、获取每个小说的专属链接地址
tree = etree.HTML(result)
href_list = tree.xpath('//tbody/tr//a/@href') # 指定属性的信息
href_list[:5]
2、获取每个小说的名称
name_list = tree.xpath('//tbody/tr//a/text()') # 指定标签下面的全部内容
name_list[:5]
3、生成数据帧DataFrame
# 生成古龙小说的地址和名称
gulong = pd.DataFrame({
"name":name_list,
"url":href_list
})
gulong
4、完善URL地址
实际上每个小说的URL地址是有一个前缀的,比如绝代双骄的完整地址:https://www.kanunu8.com/book/4573/,我们在上面获取到的数据只是最后面的部分,给每个URL地址加上前缀:
gulong['url'] = 'https://www.kanunu8.com/book' + gulong['url'] # 加上公共前缀
gulong
# 导出为excel文件
gulong.to_excel("gulong.xlsx",index=False)
在这里对Xpath的使用总结下:
本文分享自 Python数据分析实例 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!