一、前言
这是我的学习专栏:Python爬虫学习
前面我们学习了Beautiful Soup的使用,最后我们提到了CSS选择器,Beautiful Soup库在CSS选择器上并没有很强大,所以这次我们学习一个新的工具——今天的主角:pyquery。
让我们一起来学习有关pyquery的知识吧!
二、我的环境
- 电脑系统:Windows 11
- 语言版本:Python 3.10.4
- 编译器:VsCode
三、准备工作
1、下载安装
在cmd或者vscode终端输入如下命令:
pipinstallpyquery
2、初始化
pyquery解析HTML文本的时候有很多种初始化方法,比如字符串初始化,URL初始化,文件初始化等等,我所说的三种方法对应的就分别传入字符串、URL和文件来初始化的。
- 字符串初始化
直接使用HTML文本当作初始化参数:
frompyqueryimportPyQueryaspqhtml="""<div> <ul> <li class="item0">message</li> <li class="item1"><a href="link2.html">message2</a></li> <li class="item0 active"><a href="link3.html"><span class="bold">message3</span></a></li> <li class="item1 active"><a href="link4.html">meaasge4</a></li> <li class="item0"><a href="link5.html">message5</a></li> </ul></div>"""doc=pq(html) print(doc('li'))
- 他运行的结果是:
<liclass="item0">message</li><liclass="item1"><ahref="link2.html">message2</a></li><liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li>
- URL初始化
使用网页的URL来当作初始化参数
frompyqueryimportPyQueryaspqdoc=pq(url='https://baidu.com') print(doc('title'))
- 它运行的结果是:
<title>百度一下,你就知道</title>
- 也可以直接使用requests库来获取URL
frompyqueryimportPyQueryaspqimportrequestsdoc=pq(requests.get('https://baidu.com').text) print(doc('title'))
- 这个结果跟上面的一样,两个方法是等效的。
- 文件初始化
也就是通过传递本地文件作为参数来实现的。
frompyqueryimportPyQueryaspqdoc==pq(filename='test.html') print(doc('li'))
3、基本的CSS选择器
先举个例子:
frompyqueryimportPyQueryaspqhtml="""<div id="container"> <ul> <li class="item0">message</li> <li class="item1"><a href="link2.html">message2</a></li> <li class="item0 active"><a href="link3.html"><span class="bold">message3</span></a></li> <li class="item1 active"><a href="link4.html">meaasge4</a></li> <li class="item0"><a href="link5.html">message5</a></li> </ul></div>"""doc=pq(html) print(doc('#container .list li')) foritemindoc('#container .list li').itenms(): print(item.text)
它运行的结果是:
<liclass="item0">message</li><liclass="item1"><ahref="link2.html">message2</a></li><liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li>messagemessage2message3message4message5
这里的CSS选择器就是‘#container .list li’,它的意思是先选取id为container的节点,然后再选取该节点内部class为list的所有li节点,然后再使用for循环和text()方法获取节点内的文本信息。
四、pyquery库的基本用法
1、查找节点
- 查找子节点
frompyqueryimportPyQueryaspqhtml="""<div id="container"> <ul class="list"> <li class="item0">message</li> <li class="item1"><a href="link2.html">message2</a></li> <li class="item0 active"><a href="link3.html"><span class="bold">message3</span></a></li> <li class="item1 active"><a href="link4.html">meaasge4</a></li> <li class="item0"><a href="link5.html">message5</a></li> </ul></div>"""doc=pq(html) items=doc('.list') print(type(items)) print(items) lis=items.find('li') print(type(lis)) print(lis)
- 它允许的结果是:
<class'pyquery.pyquery.PyQuery'><ulclass="list"><liclass="item0">message</li><liclass="item1"><ahref="link2.html">message2</a></li><liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li></ul><class'pyquery.pyquery.PyQuery'><liclass="item0">message</li><liclass="item1"><ahref="link2.html">message2</a></li><liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li>
- find()方法跟之前的一样,会返回所有符合条件的节点,另外如果只想查找子节点,就可以直接使用children()方法,不传入选择器就默认选择全部子节点,传入的话就选择对应的子节点,例如我要寻找class为active的节点:
lis=items.children('.active') print(lis)
- 它运行的结果是:
<liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li>
- 查找父节点
frompyqueryimportPyQueryaspqhtml="""<div class="wrap"> <div id="container"> <ul class="list"> <li class="item0">message</li> <li class="item1"><a href="link2.html">message2</a></li> <li class="item0 active"><a href="link3.html"><span class="bold">message3</span></a></li> <li class="item1 active"><a href="link4.html">meaasge4</a></li> <li class="item0"><a href="link5.html">message5</a></li> </ul> </div></div>"""doc=pq(html) items=doc('.list') container=items.parent() print(container)
- 它运行的结果是:
<divid="container"><ulclass="list"><liclass="item0">message</li><liclass="item1"><ahref="link2.html">message2</a></li><liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li></ul></div>
- 使用parent()方法可以获得直接父节点,如果要获取祖先节点,就需要使用parents()方法:
parents=items.parents() print(parents)
- 它运行的结果是:
<divclass="wrap"><divid="container"><ulclass="list"><liclass="item0">message</li><liclass="item1"><ahref="link2.html">message2</a></li><liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li></ul></div></div><divid="container"><ulclass="list"><liclass="item0">message</li><liclass="item1"><ahref="link2.html">message2</a></li><liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li></ul></div>
- parents()方法会返回所有的祖先节点,如果需要返回选定的祖先节点,就需要传入CSS选择器进行选择返回,例如:
parent=items.parents(.wrap) print(parent)
- 它运行的结果是:
<divclass="wrap"><divid="container"><ulclass="list"><liclass="item0">message</li><liclass="item1"><ahref="link2.html">message2</a></li><liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li></ul></div></div>
- 查找兄弟节点
frompyqueryimportPyQueryaspqdoc=pq(html) items=doc('.list') li=doc('.list .item0.active') print(li.siblings())
- 它运行的结果是:
<liclass="item1"><ahref="link2.html">message2</a></li><liclass="item0">message</li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li>
- 如果要从兄弟节点内寻找特定的节点,直接往siblings()中传入选择器即可:
frompyqueryimportPyQueryaspqdoc=pq(html) items=doc('.list') li=doc('.list .item0.active') print(li.siblings('.active'))
- 它运行的结果是:
<liclass="item1 active"><ahref="link4.html">meaasge4</a></li>
2、遍历节点
pyquery返回的结果并不是列表,单个节点或者多个节点,单个节点可以直接打印出来,多个节点就需要一个一个遍历出来,使用items方法遍历:
frompyqueryimportPyQueryaspqdoc=pq(html) lis=doc('li').items() forliinlis: print(li)
它运行的结果是:
<liclass="item0">message</li><liclass="item1"><ahref="link2.html">message2</a></li><liclass=python"item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li>
- 获取属性
我们使用attr进行属性获取:
frompyqueryimportPyQueryaspqdoc=pq(html) a=doc('.item0.active a') print(a) print(a.attr('href'))
- 它运行的结果是:
<ahref="link3.html"><spanclass="bold">message3</span></a>link3.html
- a.attr(‘href’)也可以换成a.attr.href,两者是等效的。
但是如果选择的是多个元素的话,只使用attr是不行的,还需要加上遍历才行:
frompyqueryimportPyQueryaspqdoc=pq(html) a=doc('a') foritemina.items(): print(item.attr('href'))
- 它运行的结果是:
link2.htmllink3.htmllink4.htmllink5.html
- 获取文本
获取文本使用text()方法:
frompyqueryimportPyQueryaspqdoc=pq(html) a=doc('.item0.active a') print(a) print(a.text())
- 它运行的结果是:
<ahref="link3.html"><spanclass="bold">message3</span></a>message3
- 如果要获取节点内部的HTML文本就需要使用html方法:
frompyqueryimportPyQueryaspqdoc=pq(html) li=doc('.item0.active') print(li) print(li.html())
- 它运行的结果是:
<liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><ahref="link3.html"><spanclass="bold">message3</span></a>
- 如果获取多个节点的话,text和html方法会返回什么?
frompyqueryimportPyQueryaspqdoc=pq(html) li=doc('li') print(li.html()) print(type(li.html())) print(li.text()) print(type(li.text()))
- 它运行的结果是:
message<class'str'>messagemessage2message3meaasge4message5<class'str'>
- 可以看出,html返回了第一个li节点内的HTML文本,而text方法返回了所有li节点内部的纯文本,返回结果的类型都是字符串类型。
3、节点操作
pyquery提供了非常多能对节点进行动态修改的方法,下面我就总结其中几种常见的方法
- addClass和removeClass
frompyqueryimportPyQueryaspqhtml="""<div class="wrap"> <div id="container"> <ul class="list"> <li class="item0">message</li> <li class="item1"><a href="link2.html">message2</a></li> <li class="item0 active"><a href="link3.html"><span class="bold">message3</span></a></li> <li class="item1 active"><a href="link4.html">meaasge4</a></li> <li class="item0"><a href="link5.html">message5</a></li> </ul> </div></div>"""doc=pq(html) li=doc('.item0.active') print(li) li.removeClass('active') print(li) li.addClass('active') print(li)
- 它运行的结果是:
<liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item0"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item0 active"><ahref="link3.html"><spanclass="bold">message3</span></a></li>
- 显而易见,addClass方法是添加class属性,removeClass方法就是移除class方法。
- attr、text和html
frompyqueryimportPyQueryaspqhtml="""<ul class="list"> <li class="item0 active"><a href="link3.html"><span class="bold">message3</span></a></li></ul>"""doc=pq(html) li=doc('.item0.active') print(li) li.attr('name', 'link') print(li) li.text('changed item') print(li) li.html('<span>changed item</span') print(li)
- 它运行的结果是:
<liclass="item0 active"name="link"><ahref="link3.html"><spanclass="bold">message3</span></a></li><liclass="item0 active"name="link">changeditem</li><liclass="item0 active"name="link"><span>changeditem</span></li>
- 可以看出,attr方法可以修改属性并添加新属性,text方法可以改变li节点内部的文本,html方法也可以改变li节点内部的HTML本文。
- remove
frompyqueryimportPyQueryaspqhtml="""<div class="wrap"> Hello,World! <p>Hello,Python!</p></div>"""doc=pq(html) wrap=doc('.wrap') wrap.find('p').remove() print(wrap.text())
- 它运行的结果是:`
Hello,World!
- 这里首先选择p节点,然后调用remove方法将其移除,这个时候wrap内就只剩下一个文本了,再调用text方法即可获得。
4、伪类选择器
伪类选择器例如:选择第一个节点,选择最后一个节点,选择奇偶数节点、包含某一文本的节点等等。
frompyqueryimportPyQueryaspqhtml="""<div class="wrap"> <div id="container"> <ul class="list"> <li class="item0">message</li> <li class="item1"><a href="link2.html">message2</a></li> <li class="item0 active"><a href="link3.html"><span class="bold">message3</span></a></li> <li class="item1 active"><a href="link4.html">meaasge4</a></li> <li class="item0"><a href="link5.html">message5</a></li> </ul> </div></div>"""doc=pq(html) li=doc('li:first-child') print("选择第一个li节点:", li) li=doc('li:last-child') print("选择最后一个li节点:", li) li=doc('li:nth-child(2)') print("选择第二个li节点:", li) li=doc('li:gt(2)') print("选择第三个li节点之后的li节点:", li) li=doc('li:nth-child(2n)') print("选择偶数位置的li节点:", li) li=doc('li:contains(message2)') print("选择包含message2的li节点:", li)
它运行的结果是:
选择第一个li节点:<liclass="item0">message</li>选择最后一个li节点:<liclass="item0"><ahref="link5.html">message5</a></li>选择第二个li节点:<liclass="item1"><ahref="link2.html">message2</a></li>选择第三个li节点之后的li节点:<liclass="item1 active"><ahref="link4.html">meaasge4</a></li><liclass="item0"><ahref="link5.html">message5</a></li>选择偶数位置的li节点:<liclass="item1"><ahref="link2.html">message2</a></li><liclass="item1 active"><ahref="link4.html">meaasge4</a></li>选择包含message2的li节点:<liclass="item1"><ahref="link2.html">message2</a></li>
五、最后我想说
有关pyquery的基本学习就到这里了,但是pyquery中的方法还有很多,需要大家自行去官方文档去学习,篇幅有限,就不列举那么多了。
这篇博客是我使用我刚买的轻薄本来书写的,目前感觉还不错,后续如果是一些轻量的学习,我都会使用这个笔记本进行学习总结,大型项目或者需要高配置的,就会使用我另一个3070的笔记本。
来学校之后就没有在家时间那么多了,目前大三的我,正在学习有关大数据方面的专业课,所以更新慢请见谅,谢谢,后续我也会更新有关我专业课知识的博客,尽情期待,哈哈哈。
最后,文章如果出现错误之处,还请大家为我指出,谢谢!创造不易,期待得到你们的支持!