Web爬虫|入门教程解析库pyquery

网络爬虫开发实战源码:https://github.com/MakerChen66/Python3Spider

原创不易,本文禁止抄袭、转载,多年爬虫实战开发经验总结,侵权必究!

一、pyquery引入

1.1 什么是pyquery?

在之前,我们介绍了Beautiful Soup的用法,它是一个非常强大的网页解析库,但有些时候你是否觉得它使用起来有点不适宜或者不方便?有没有觉得它的CSS选择器的功能没有那么强大呢?作为同样使用CSS选择器的解析库pyquery,除了包含很多属性方法、基本CSS选择器之外,还支持节点操作以及很多伪类选择器,故它的功能要比Beautiful Soup更加强大

1.2 安装pyquery

pip install pyquery -i https://pypi.doubanio.com/simple

也可指定其他镜像源

1.3 导入pyquery

from pyquery import PyQuery as pq



二、pyquery使用

2.1 初始化

pyquery的初始化方式有很多种,比如直接传入字符串、URL、文件名等等。下面我们来详细介绍一下

字符串初始化
我们用实例来感受一下

from pyquery import PyQuery as pq

html = '''
<div class="wrap">
<div id="container">
    <ul class="list">
         <li class="item-0">first item</li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
         <li class="item-1 active"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
     </ul>
 </div>
 </div>
'''

doc = pq(html)
print(doc('li'))

首先引入PyQuery这个对象,取名为pq,然后声明了一个HTML字符串,并将其当做参数传入PyQuery类,对象初始化就完成了。接着将初始化的对象传入CSS选择器,在这里我们传入的是li节点,这样就可以将所有的li节点选择出来了

输出结果如下:
在这里插入图片描述
URL初始化
初始化参数不仅可以传递字符串,还可以传递URL

from pyquery import PyQuery as pq

doc = pq(url='https://www.qiushibaike.com/hot/')
print(doc('title'))

PyQuery对象会先请求这个URL,然后用返回的HTML内容完成初始化,这其实就是相当于用网页的源代码以字符串的形式传递给PyQuery类来初始化

它与下面代码的功能是相同的

from pyquery import PyQuery as pq
import requests

doc = pq(requests.get('https://www.qiushibaike.com/hot/').text)
print(doc('title'))

输出结果如下:
在这里插入图片描述
文件初始化
当然,除了传递字符串、URL之外,还可以传递本地的文件名,此时需将参数指定为filename

from pyquery import PyQuery as pq

doc = pq(filename='demo.html')
print(doc('li'))

这里需要一个本地HTML文件demo.html,其内容就是待解析的HTML字符串

2.2 基本CSS选择器

用一个实例来感受一下pyquery的CSS选择器的用法:

from pyquery import PyQuery as pq

html = '''
<div class="wrap">
<div id="container">
    <ul class="list">
         <li class="item-0">first item</li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
         <li class="item-1 active"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
     </ul>
 </div>
 </div>
'''

doc = pq(html)
print(doc('#container .list li'))
print(type(doc('#container .list li')))

先初始化PyQuery对象之后,传入了一个CSS选择器#container .list li,意为先选取id为container的节点,然后再选取其内部的class为list的节点内部的所有li节点,然后将选取内容及其类型打印输出

输出结果如下:
在这里插入图片描述
可以看到,我们成功获取到了符合条件的节点,它的类型依然是PyQuery类型

2.3 查找节点

接下来介绍一些常用的查询函数,这些函数和jQuery中函数的用法完全相同

子节点
查找所有子孙节点需要用到find()方法,此时传入的参数是CSS选择器,为了避免代码冗余,我们以前面的HTML为例:

doc = pq(html)
items = doc('.list')
html = items.find('li')
print(html)
print(type(html))

我们选取了class为list的节点,然后再把该节点内部的所有子孙节点li选取出来

输出结果如下:
在这里插入图片描述
如果我们只是想查找子节点,那么可以用children()方法:

doc = pq(html)
items = doc('.list')
html = items.find('li')
print(html.children())
print(type(html.children()))

这里我们选取了class为list的节点,然后再把该节点内部的所有子孙节点li选取出来,最后再选取该节点的所有子节点

输出结果如下:
在这里插入图片描述
此外,children()方法还可以传入CSS选择器,如下:

items = doc('.list')
html = items.children('.active')
print(html)

输出结果如下:
在这里插入图片描述
父节点
我们可以用parent()方法来获取某个节点的直接父节点,示例如下:

from pyquery import PyQuery as pq

doc = pq(html)
items = doc('.list')
container = items.parent()
print(container)
print(type(container))

我们先选取class为list的节点,然后用parent()方法获取该节点的直接父节点,其类型依然是PyQuery

输出结果如下:
在这里插入图片描述
如果想要获取某个祖先节点,可以用parents()方法,如下:

from pyquery import PyQuery as pq

doc = pq(html)
items = doc('.list')
parents = items.parents()
print(parents)
print(type(parents))

同样parents()方法也可以传入CSS选择器,如下:

wrap = items.parents('.wrap')
print(wrap,type(wrap))

兄弟节点
想要获取兄弟节点,使用siblings()方法即可,如下:

doc = pq(html)
li = doc('.list .item-0.active')
print(li.siblings())

这里选取的是第三个li节点,它的兄弟节点有4个,第一、二、四、五个节点

输出结果如下:
在这里插入图片描述
同样siblings()方法也可以传入CSS选择器获取某个兄弟节点,如下:

doc = pq(html)
li = doc('.list .item-0.active')
print(li.siblings('.active'))

输出结果如下:
在这里插入图片描述

2.4 遍历

从上面我们可以观察到,pyquery的选择节点可能是单个节点,也有可能是多个节点,但类型都是PyQuery类型,并不是返回像Beautiful Soup那样的列表

对于单个节点而言,可以直接打印输出,也可以直接转换成字符串,如下:

doc = pq(html)
li = doc('.list .item-0.active')
print(li)
print(str(li))

输出结果如下:
在这里插入图片描述
对于多个节点的结果,就需要遍历来获取了,先用items()方法把类型转换成生成器类型,再遍历每个li节点,如下:

doc = pq(html)
lis = doc('li').items()
print(lis)
for li in lis:
  print(li,type(li))

调用items()后,会得到一个生成器,需要遍历才可以逐个得到li节点对象,其节点类型也是PyQuery类型

输出结果如下:
在这里插入图片描述
拓展:也可以使用enumerate()方法再遍历,这样就可以得到每个节点的序号:

doc = pq(html)
lis = doc('li').items()
print(lis)
for i,li in enumerate(lis):
  print(i,li,type(li))

输出结果如下:
在这里插入图片描述

2.5 获取信息

找到节点之后,我们最终的目的当然就是提取节点所包含的信息了,比较重要的信息包括属性及文本

获取属性
提取到某个PyQuery类型的节点后,就可以调用attr()方法来获取属性,如下:

doc = pq(html)
a = doc('.item-0.active a')
print(a,type(a))
print(a.attr('href'))

输出结果如下:
在这里插入图片描述
也可以通过调用attr属性来获取属性

print(a.attr.href)

这两种方法的结果完全一样
注意:当返回结果包含多个节点时,调用attr()方法,只会得到第一个节点的属性,要想获取节点的所有属性,就要用到前面所说的遍历

获取文本
调用text()方法就可以获取节点的内部文本,如下:

doc = pq(html)
a = doc('.item-0.active a')
print(a)
print(a.text())

输出结果如下:
在这里插入图片描述
如果想要获取这个节点内部的HTML文本,就要用html()方法,如下:

doc = pq(html)
li = doc('.item-0.active')
print(li)
print(li.html())

输出结果如下:
在这里插入图片描述


三、节点操作

pyquery提供了一系列方法来对节点进行动态修改,比如为某个节点添加或移除一个属性,移除某个节点等,这些操作有时候会为提取信息带来极大的遍历

addClass和removeClass
我们用实例来感受一下:

from pyquery import PyQuery as pq

doc = pq(html)
li = doc('.item-0.active')
print(li)
li.removeClass('active')
print(li)
li.addClass('active')
print(li)

输出结果如下:
在这里插入图片描述
所以说,addClass()和removeClass()这些方法可以动态改变节点的class属性

attr、text和html
除了操作class这个属性外,也可以用attr()方法对属性进行操作,还可以用text()和html()方法来改变节点内部的内容,示例如下:

html = '''
<ul class="list">
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
</ul>
'''
doc = pq(html)
li = doc('.item-0.active')
print(li)
li.attr('name','link')
print(li)
li.text('changed data')
print(li)
li.html('<span>changed data</span>')
print(li)

首先选中li节点,然后调用attr()方法来修改属性,该方法的第一个参数为属性名,第二个参数为属性值,接着调用text()方法和html()方法来改变节点内部的内容,分别打印出来

输出结果如下:
在这里插入图片描述
注意:如果attr()方法只传入第一个参数的属性名,则是获取这个属性值,如果再传入第二个参数则就可以用来修改属性值;text()方法和html()方法如果不传参数,则是获取节点内纯文本和HTML文本,反之则进行赋值

remove
使用remove()方法会移除某个节点,有时会为提取信息带来非常大的便利:

html = '''
  <div class="wrap">
    hello,world
    <p>this is a paragraph</p>
  </div>
'''
doc = pq(html)
wrap = doc('.wrap')
wrap('p').remove()
print(wrap.text())

输出结果如下:

hello,world



四、伪类选择器

CSS选择器之所以强大,还有一个很重要的原因,就是它支持多种多样的伪类选择器,比如选择第一个节点,最后一个节点、奇偶数节点、包含某一文本的节点等

from pyquery import PyQuery as pq

html = '''
<div class="wrap">
<div id="container">
    <ul class="list">
         <li class="item-0">first item</li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
         <li class="item-1 active"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a></li>
     </ul>
 </div>
 </div>
'''
doc = pq(html)
li = doc('li:first-child')
print(li)
li = doc('li:last-child')
print(li)
li = doc('li:nth-child(2)')
print(li)
li = doc('li:gt(2)')
print(li)
li = doc('li:nth-child(2n)')
print(li)
li = doc('li:contains(second)')
print(li)

这里使用了CSS3的伪类选择器,依次选择了第一个li节点、最后一个li节点、第二个li节点、第三个li之后的li节点、偶数位置的li节点、包含second文本的li节点

输出结果如下:
在这里插入图片描述
总结
到目前为止,pyquery的常用用法就介绍完了,它的功能非常强大,很多操作是lxml、Beautiful Soup等解析库所没有的

更多CSS选择器的用法可以参考链接:
https://www.w3school.com.cn/css/index.asp

更多pyquery解析库的用法可以参考链接:
https://pyquery.readthedocs.io

五、原文链接

本人原创公众号原文链接:点我阅读原文

原创不易,如果觉得有点用,希望可以随手点个赞,拜谢各位老铁!

六、作者Info

作者:小鸿的摸鱼日常,Goal:让编程更有趣!

原创微信公众号:『小鸿星空科技』,专注于算法、爬虫,网站,游戏开发,数据分析、自然语言处理,AI等,期待你的关注,让我们一起成长、一起Coding!

转载说明:本文禁止抄袭、转载 ,侵权必究!

猜你喜欢

转载自blog.csdn.net/qq_44000141/article/details/121568618