单页背景(单页背景怎么弄)
906
2022-05-30
lxml库
lxml是Python的一个解析库,专门用于解析XML与HTML,支持XPath解析方式。由于lxml库的底层是使用C语言编写的,所以其解析效率非常的高。
在我们后面讲解使用该库之前,我们需要安装该库。一般通过如下命令进行安装即可,代码如下:
pip install lxml
lxml基本用法
既然,lxml库支持解析XML以及HTML,那么肯定就需要学会这2种文档的解析方式。下面,我们来分别讲解。
解析XML文件
首先,我们需要使用lxml库解析XML文件,这里XML文件其实有很多种类,这里博主随便定义一个XML进行解析。
XML代码如下:
解析示例代码如下所示:
from lxml import etree tree = 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代码如下:
解析代码如下所示:
from lxml import etree parser = 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语法规则:
XPath实战
既然,我们已经了解XPath具体的语法结构,那么我们将一一实战这些语法,让读者更清晰,更快捷的掌握。
测试HTML文件如下所示:
选取某节点的所有子孙节点
假设我们需要获取上面HTML文件中
from lxml import etree parser = 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)
运行之后,效果如下:
双斜杠“//”代表获取当前节点下的子孙节点,也就是说,直接在根节点操作,就是获取根节点下面的所有该标签。
选取某节点的所有子节点
还是上面这个例子,我们如果使用单斜杠“/”获取所有的标签呢?
因为标签是
from lxml import etree parser = 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 etree parser = etree.HTMLParser() html = etree.parse('demo.html', parser) nodes = html.xpath("//a[@class='aaa']/../@class") print(nodes)
运行之后,效果如下:
除了通过/…获取父节点之外,我们还可以通过parent::*获取父节点。那么同样的转换语法也可以得到如上图所示的结果。(把…替换成即可)
多属性匹配
我们还是来获取那个有class的标签,这里使用多属性匹配原则。
也就是,我们匹配其父节点class等于li以及class等于aaa的标签。那么如何首先呢?示例如下:
from lxml import etree parser = etree.HTMLParser() html = etree.parse('demo.html', parser) nodes = html.xpath("//a[contains(@class,'aaa') and ../@class='li']") print(nodes[0].text)
运行之后,效果如下:
看看上面的输出图,是不是最后一个标签的文本内容?这里通过and进行多属性条件判断。
XPath运算符规则
不过,这里就涉及XPath运算符规则了。博主这里,也列出了一个专门的运算符规则的表格,方便读者查阅参考。
实战:爬取CSDN个人博文
我们先通过chrome,或者任意浏览器按F12打开查看CSDN个人主页的元素,可以看到,这里的div是整个主页内容的div。
然后,在一条一条的遍历子div获取里面的每篇博文信息即可。不过,我们首先需要获取网页的HTML文本,通过requests进行获取。
然后,我们再来看看其标题与链接到底在哪里?如下图所示:
可以看到,标题与链接都在每个div的
标签中,知道了这些,我们来获取主页的所有博文。
示例代码如下:
from lxml import etree import requests url = "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遍,其他的只遍历的一遍这是为什么呢?我们先来看一张图:
这里获取标签文本的时候,默认是获取了2个,一个是空,一个才是下面的标题。所以,这里每次获取标签文本标题时,都是一个空白,一个标题。
所以,我们在后续遍历的时候,应该去除掉空白字符串。只要标题。
XPath最简单的玩法
如果你是安装的Chrome,那么XPath语法,你可以不必学。因为这个浏览器可以直接生成XPath。
比如,我们获取上面的标签,那么如何获取呢?只要选中标签,然后按住右键选择Copy-Copy XPath即可。如下图所示:
不过,博主不建议这么做。因为这里Copy的XPath仅仅只是针对当前的标签,而我们上面获取的标签是一个有规则的标签列表。而你不学习的XPath语法的话,这要是有100个列表标签,你难道还复制XPath语法100次不成?而学习过XPath只需要一行代码,然后遍历即可。
HTML HTTP Python XML 爬虫
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。