目录

  • lxml库
    • lxml基本用法
      • 解析XML文件
      • 解析HTML文件
    • XPath
      • 什么是XPath
      • XPath语法
    • XPath实战
      • 选取某节点的所有子孙节点
      • 选取某节点的所有子节点
    • 通过属性选取某节点的父节点
    • 多属性匹配
    • XPath运算符规则
    • 实战:爬取CSDN个人博文
    • XPath最简单的玩法

lxml库

lxml是Python的一个解析库,专门用于解析XML与HTML,支持XPath解析方式。由于lxml库的底层是使用C语言编写的,所以其解析效率非常的高。

在我们后面讲解使用该库之前,我们需要安装该库。一般通过如下命令进行安装即可,代码如下:

pip install lxml

lxml基本用法

既然,lxml库支持解析XML以及HTML,那么肯定就需要学会这2种文档的解析方式。下面,我们来分别讲解。

解析XML文件

首先,我们需要使用lxml库解析XML文件,这里XML文件其实有很多种类,这里博主随便定义一个XML进行解析。

XML代码如下:

<?xml version="1.0" encoding="utf-8"?>
<people><zhangsan class="法外狂徒"><sex>男</sex><age>21</age></zhangsan><lisi class="法外狂徒的伙伴"><sex>男</sex><age>21</age></lisi>
</people>

解析示例代码如下所示:

from lxml import etreetree = etree.parse("lxml_xml.xml")
print(str(etree.tostring(tree, encoding='utf-8'), 'utf-8'))
root = tree.getroot()
print("根节点", root.tag)
children = root.getchildren()
for child in children:print("sex:", child[0].text)print("class :", child.get('class'))

运行之后,效果如下所示:

解析HTML文件

解析HTML比XML稍微复杂一点,它需要创建一个HTMLParser()对象传入到parser()方法中,因为其默认是解析XML的。

HTML代码如下:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>我是一个测试页面</title>
</head>
<body>
</body>
</html>

解析代码如下所示:

from lxml import etreeparser = etree.HTMLParser()
tree = etree.parse('demo.html', parser)
root = tree.getroot()
result = etree.tostring(root, encoding='UTF-8', pretty_print=True, method='html')
print(root.tag)
children = root.getchildren()
print("语言:", children[0].get('lang'))
print(root[0][1].text)

运行之后,效果如下所示:

XPath

估计细心的小伙伴,已经看出lxml库直接使用的弊端了。因为这是小编写的一个简单的HTML与XML,所以它的层级很低。

如果是真实的网页,那么可能层级会很多,如果还按数组这样一层一层往下查找,估计能搞出个十几维的数组。这样太复杂了。

所以,这里我们需要引入XPath进行辅助解析。

什么是XPath

XPath于1991年11月6日称为W3C标准,它被设计为可以在XSLT、XPointer以及其他XML解析软件中使用,其中文文档为:

https://www.w3school.com.cn/xpath/index.asp

XPath全称XML Path Language,中文叫XML路径语言,它是一种在XML文档中查询信息的语言。

最初虽然只支持XML文件,但是后来随着版本的迭代,已经可以支持HTML文件的解析与搜索,因为HTML与XML同源。

XPath语法

XPath语言的基本语法就是多级目录的层级结构,但比数组那种容易理解的多。下表是博主归纳总结的XPath语法规则:

语法 意义
nodename 选取此节点的所有子节点
/ 从当前节点选取直接子节点
// 从当前节点选取子孙节点
. 选取当前节点
选取当前节点的父亲节点
@ 选取属性

XPath实战

既然,我们已经了解XPath具体的语法结构,那么我们将一一实战这些语法,让读者更清晰,更快捷的掌握。

测试HTML文件如下所示:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>我是一个测试页面</title>
</head>
<body>
<ul><li><a href="https://liyuanjinglyj.blog.csdn.net/">我的主页</a></li><li><a href="https://www.csdn.net/">CSDN首页</a></li><li class="li"><a href="https://www.csdn.net/nav/python" class="aaa">Python板块</a></li>
</ul>
</body>
</html>

选取某节点的所有子孙节点

假设我们需要获取上面HTML文件中<ul>标签的所有<a>子节点的链接与文本。我们需要如果去操作呢?示例代码如下:

from lxml import etreeparser = etree.HTMLParser()
html = etree.parse('demo.html', parser)
nodes = html.xpath("//ul//a")
for index in range(0, len(nodes)):print("网址:", nodes[index].get('href'), "  文本:", nodes[index].text)

运行之后,效果如下:

双斜杠“//”代表获取当前节点下的子孙节点,也就是说,直接在根节点操作,就是获取根节点下面的所有该标签。

选取某节点的所有子节点

还是上面这个例子,我们如果使用单斜杠“/”获取所有的<a>标签呢?

因为<a>标签是<li>标签的子节点,所以我们需要获取<li>,再通过单斜杠"/"获取<a>标签。示例代码如下:

from lxml import etreeparser = etree.HTMLParser()
html = etree.parse('demo.html', parser)
nodes = html.xpath("//li/a")
for index in range(0, len(nodes)):print("网址:", nodes[index].get('href'), "  文本:", nodes[index].text)

如上面代码所示,我们把xpath语法改成“//li/a”即可。运行之后,效果与上面一模一样。

通过属性选取某节点的父节点

对于当前节点来说,我们只需要通过其标签与属性确认,自然就可以获取当前节点。所以.这里就不赘述了。

我们直接介绍后两种语法,通过"@“查找属性,然后通过”.."查找其父节点。

实战,通过class等于aaa的节点获取父亲节点,然后获取其属性class的值。示例代码如下所示:

from lxml import etreeparser = etree.HTMLParser()
html = etree.parse('demo.html', parser)
nodes = html.xpath("//a[@class='aaa']/../@class")
print(nodes)

运行之后,效果如下:

除了通过/…获取父节点之外,我们还可以通过parent::*获取父节点。那么同样的转换语法也可以得到如上图所示的结果。(把…替换成即可)

多属性匹配

我们还是来获取那个有class的<a>标签,这里使用多属性匹配原则。

也就是,我们匹配其父节点class等于li以及class等于aaa的标签<a>。那么如何首先呢?示例如下:

from lxml import etreeparser = etree.HTMLParser()
html = etree.parse('demo.html', parser)
nodes = html.xpath("//a[contains(@class,'aaa') and ../@class='li']")
print(nodes[0].text)

运行之后,效果如下:

看看上面的输出图,是不是最后一个<a>标签的文本内容?这里通过and进行多属性条件判断。

XPath运算符规则

不过,这里就涉及XPath运算符规则了。博主这里,也列出了一个专门的运算符规则的表格,方便读者查阅参考。

运算符 描述 示例 意义
and class=‘name’ and href=‘www’ 如果class等于name并且href等于www,则返回true,否则false
mod 取余 10 mod 3 1
or class=‘name’ or class=‘www’ 如果class等于name或者www,则返回true,都不等于则返回false
div 除法 10 div 5 2
+ 加法 10+5 15
- 减法 10-5 5
* 乘法 10*5 50
= 等于 value=520 如果value等于520,返回true,否则返回false
!= 不等于 value!=520 如果value不等于520,返回true,否则返回false
< 小于 value<520 如果value小于520,返回true,否则返回false
> 大于 value>520 如果value大于520,返回true,否则返回false
<= 小于等于 value<=520 如果value小于等于520,返回true,否则返回fals
>= 大于等于 value>=520 如果value大于等于520,返回true,否则返回false

实战:爬取CSDN个人博文

我们先通过chrome,或者任意浏览器按F12打开查看CSDN个人主页的元素,可以看到,这里的div是整个主页内容的div。


同时,其下边的所有子div都是一篇篇作者的博文内容。那么我们就可以先通过class="article-list"找到主页博文列表。

然后,在一条一条的遍历子div获取里面的每篇博文信息即可。不过,我们首先需要获取网页的HTML文本,通过requests进行获取。

然后,我们再来看看其标题与链接到底在哪里?如下图所示:


可以看到,标题与链接都在每个div的<h4>标签中,而描述信息在class='content’的<p>标签中,知道了这些,我们来获取主页的所有博文。

示例代码如下:

from lxml import etree
import requestsurl = "https://blog.csdn.net/liyuanjinglyj"
session = requests.session()
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36','accept-encoding': 'gzip, deflate, br','accept-language': 'zh-CN,zh;q=0.9','cache-control': 'max-age=0','accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'
}
result = requests.get(url, headers=headers)
result.encoding = result.apparent_encoding
html = etree.HTML(result.text)
urlStr = html.xpath("//div[@class='article-list']//div/h4/a/@href")
titleStr = html.xpath("//div[@class='article-list']//div/h4/a/text()")
titleStr = [i for i in titleStr if i.strip() != '']
contentStr = html.xpath("//div[@class='article-list']//div/p[@class='content']/text()")
for url, title, content in zip(urlStr, titleStr, contentStr):print("博文链接:", url)print("博文标题:", title.strip())print("博文描述:", content.strip())

运行之后,效果如下:

这里有一个很奇怪的问题,相信大家也发现了,我们titleStr遍历了2遍,其他的只遍历的一遍这是为什么呢?我们先来看一张图:

这里获取<a>标签文本的时候,默认是获取了2个,一个是空,一个才是下面的标题。所以,这里每次获取<a>标签文本标题时,都是一个空白,一个标题。

所以,我们在后续遍历的时候,应该去除掉空白字符串。只要标题。

XPath最简单的玩法

如果你是安装的Chrome,那么XPath语法,你可以不必学。因为这个浏览器可以直接生成XPath。

比如,我们获取上面的<a>标签,那么如何获取呢?只要选中<a>标签,然后按住右键选择Copy-Copy XPath即可。如下图所示:

不过,博主不建议这么做。因为这里Copy的XPath仅仅只是针对当前的标签,而我们上面获取的标签是一个有规则的标签列表。而你不学习的XPath语法的话,这要是有100个列表标签,你难道还复制XPath语法100次不成?而学习过XPath只需要一行代码,然后遍历即可。

Python爬虫:通过爬取CSDN博客信息,学习lxml库与XPath语法相关推荐

  1. python爬虫爬取csdn博客专家所有博客内容

    python爬虫爬取csdn博客专家所有博客内容: 全部过程采取自动识别与抓取,抓取结果是将一个博主的所有 文章存放在以其名字命名的文件内,代码如下 #coding:utf-8import urlli ...

  2. 【爬虫+数据可视化】Python爬取CSDN博客访问量数据并绘制成柱状图

    以下内容为本人原创,欢迎大家观看学习,禁止用于商业及非法用途,谢谢合作! ·作者:@Yhen ·原文网站:CSDN ·原文链接:https://blog.csdn.net/Yhen1/article/ ...

  3. 大屏监控系统实战(6)-爬虫初探:爬取CSDN博客之星年度总评选投票统计数据

    一.介绍 我们先来做个简单的,我们的目标是爬取CSDN博客之星年度总评选的首页信息. 首页的地址:http://m234140.nofollow.ax.mvote.cn/wxvote/43ced329 ...

  4. python爬虫--小白爬取csdn页面题目与链接

    爬取csdn页面题目与链接 前言 随着人工智能的不断发展,爬虫这门技术越来越重要-哈哈哈,太过官方.新手小白,过程较曲折,代码较不专业,欢迎批评与指教! 进入正题:本文主要爬取csdn博客某专栏下的题 ...

  5. Python爬虫项目--爬取某宝男装信息

    本次爬取用到的知识点有: 1. selenium 2. pymysql 3  pyquery ''' 文章:Python爬虫项目--爬取某宝男装信息 作者:Star_Zhao 源自:https://w ...

  6. Python爬虫小实践:使用BeautifulSoup+Request爬取CSDN博客的个人基本信息

    好久都没有动Python了,自从在网上买了<Python网络数据采集>这本书之后一直没有时间写自己的小的Demo,今天再网络上无意中看见 http://www.cnblogs.com/mf ...

  7. python爬虫之--爬取当当网商品信息

                                    python爬虫之--爬取当当网图商品信息                                               ...

  8. python实战系列之爬取CSDN博客之星2020年度排名情况(附源码)

    前言 CSDN2020年度博客之星马上就要收尾了,你知道自己关注的博主排名实时变化吗?谁是你心目中的博客之星,让我们爬取各位博主的排名及各位博主的一些个人信息. 代码 直接上代码 # -*- codi ...

  9. C/C++ | Qt 实现爬虫功能,爬取CSDN博客文章

    话不多说,先看程序运行截图: 注意: 本人没有看过爬虫相关的书籍,第一次写这种程序,这个程序是半屌子的,原理很简单,没有学习过爬虫的朋友,也可以写. 程序思路如下: 1.下载要爬网站的页面. 2.用正 ...

最新文章

  1. tomcat苹果版安装步骤_Mac系统安装和配置tomcat步骤详解
  2. Python3判断自身脚本是不是在运行
  3. VC学习笔记---ATL MFC CLR三个库的区别
  4. Boost Asio总结(3)异步通信
  5. 听说Attention与Softmax更配哦~
  6. python观察日志(part13)--any和all
  7. 动画演示 Delphi 2007 IDE 功能[3] - 修改属性
  8. 已管理员身份从cmd框进入mysql,及常用的简单操作!
  9. 数字信号处理1:卷积
  10. 使django与数据库保持长连接
  11. PADS2007教程(二)——PCB封装
  12. Kaggle Tabular Playground Series - Jan 2022 学习笔记2(使用时间序列的线性回归)
  13. codeblocks下载安装教程(完整详细)
  14. win10升级助手_不想使用一键重装软件?微软win10升级助手来了
  15. 跨专业转行数据分析真的可行吗?
  16. 使用proteus仿真验证基尔霍夫定律
  17. 树莓派机器人小车(创乐博)修炼指南(一)
  18. 计算机网络知识点全面总结(一篇全懂)
  19. 三维点云拼接 标记点拼接 SVD分解法
  20. mysql注入时的注释处理

热门文章

  1. amd ryzen7 1700 linux,AMD 锐龙 7
  2. [Delphi] - WebBrowser内核版本修改D7
  3. java 开发双十一大屏幕_2019最赞的大屏可视化,一定是这款双十一的酷屏
  4. 组策略自动安装证书(from gnaw0725)
  5. 苹果home键在哪里设置_苹果手机Home键失灵指纹无法录入,一招搞定,录入指纹更灵敏...
  6. STM32学习笔记 通用定时器TIM3~TIM5 13
  7. 失败至少不会在一棵树上吊死
  8. Android A4尺寸 canvas,【报Bug】canvas绘制尺寸比较大的图片时,会出现绘制不出来的问题...
  9. linux脚本除号,Linux Shell 脚本:基本操作符
  10. 金山办公的WPS AI将引入大模型能力(LLM)到表格、文字、演示和PDF四大组件