python爬虫学习记录解析库的使用——pyquery

Posted 玛卡巴卡巴巴亚卡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python爬虫学习记录解析库的使用——pyquery相关的知识,希望对你有一定的参考价值。

一、简介

CSS选择器,jQuery

二、初始化

1、字符串初始化

from pyquery import PyQuery as pq

html = """
<div>
    <ul>
         <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>
"""
doc = pq(html)
print(doc('li'))

先引入pyQuery,再取别名为pq,声明html字符春,当做参数传给PyQuery,完成初始化,将初始化对象传给css选择器,获取li节点。

<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>

2、URL初始化

PyQuery指定参数是url即可。PyQuery会首先请求这个url,用得到的html内容完成初始化,相当于用网页源代码以字符串形式传递给PyQuery类来初始化。与用request.get('http://www.xxxxx.com').text传入PyQuery对象一样。

from pyquery import PyQuery as pq
doc = pq(url='http://cuiqingcai.com')
print(doc('title'))
<title> 静觅丨崔庆才的个人博客 </title>

3、文件初始化

可以传递本地文件,将参数指定为filename

from pyquery import PyQuery as pq
doc = pq(filename='demo.html')
print(doc('li'))

二、基本CSS选择器

初始化pyquery对象,传入css选择器#container .list li。可以获取所有符合条件的节点。

from pyquery import PyQuery as pq
html  =  ''' 
<div id="container"> 
    <ul class="list"> 
         <li class="item-0">第一项</li> 
         <li class="item-1"><a href ="link2.html">第二项</a></li> 
         <li class="item-0 active"><a href="link3.html"><span class="bold">第三项</ span></a></li> 
         <li class="item-1 active"><a href="link4.html">第四项</a></li> 
         <li class="item-0" ><a href="link5.html">第五项</a></li> 
     </ul> 
</div> 
'''
doc = pq(html)
print(doc('#container .list li'))

<li class="item-0">第一项</li>
         <li class="item-1"><a href="link2.html">第二项</a></li>
         <li class="item-0 active"><a href="link3.html"><span class="bold">第三项 span&gt;</span></a></li>
         <li class="item-1 active"><a href="link4.html">第四项</a></li>
         <li class="item-0"><a href="link5.html">第五项</a></li>

三、查找节点

使用find()方法,传入参数是css选择器。find查找范围是所有子孙节点。

from pyquery import PyQuery as pq
html  =  ''' 
<div id="container"> 
    <ul class="list"> 
         <li class="item-0">第一项</li> 
         <li class="item-1"><a href ="link2.html">第二项</a></li> 
         <li class="item-0 active"><a href="link3.html"><span class="bold">第三项</ span></a></li> 
         <li class="item-1 active"><a href="link4.html">第四项</a></li> 
         <li class="item-0" ><a href="link5.html">第五项</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'>
<ul class="list">
         <li class="item-0">第一项</li>
         <li class="item-1"><a href="link2.html">第二项</a></li>
         <li class="item-0 active"><a href="link3.html"><span class="bold">第三项 span&gt;</span></a></li>
         <li class="item-1 active"><a href="link4.html">第四项</a></li>
         <li class="item-0"><a href="link5.html">第五项</a></li>
     </ul>

<class 'pyquery.pyquery.PyQuery'>
<li class="item-0">第一项</li>
         <li class="item-1"><a href="link2.html">第二项</a></li>
         <li class="item-0 active"><a href="link3.html"><span class="bold">第三项 span&gt;</span></a></li>
         <li class="item-1 active"><a href="link4.html">第四项</a></li>
         <li class="item-0"><a href="link5.html">第五项</a></li>

如果只查找子节点,可以使用children()方法

from pyquery import PyQuery as pq
html  =  ''' 
<div id="container"> 
    <ul class="list"> 
         <li class="item-0">第一项</li> 
         <li class="item-1"><a href ="link2.html">第二项</a></li> 
         <li class="item-0 active"><a href="link3.html"><span class="bold">第三项</ span></a></li> 
         <li class="item-1 active"><a href="link4.html">第四项</a></li> 
         <li class="item-0" ><a href="link5.html">第五项</a></li> 
     </ul> 
</div> 
'''
doc = pq(html)
items = doc('.list')
lis = items.children()
print(lis)

<li class="item-0">第一项</li>
         <li class="item-1"><a href="link2.html">第二项</a></li>
         <li class="item-0 active"><a href="link3.html"><span class="bold">第三项 span&gt;</span></a></li>
         <li class="item-1 active"><a href="link4.html">第四项</a></li>
         <li class="item-0"><a href="link5.html">第五项</a></li>

要选择符合条件的节点,如向选出class节点中的active节点,可以向children方法中传入css选择器.active

lis = items.children('.active')
print(lis)

此外,父节点的获取使用parent()祖先节点使用parents()。这两个方法都是返回所有符合条件的父节点和祖先节点,这里可以使用css选择器,选中符合选择器的节点。

获取兄弟节点使用siblings()方法。

from pyquery import PyQuery as pq
html  =  ''' 
<div id="container"> 
    <ul class="list"> 
         <li class="item-0">第一项</li> 
         <li class="item-1"><a href ="link2.html">第二项</a></li> 
         <li class="item-0 active"><a href="link3.html"><span class="bold">第三项</ span></a></li> 
         <li class="item-1 active"><a href="link4.html">第四项</a></li> 
         <li class="item-0" ><a href="link5.html">第五项</a></li> 
     </ul> 
</div> 
'''
doc = pq(html)
li = doc('.list .item-0.active')#选择class为list的节点内部class为item-0.active的节点
print(li.siblings())

<li class="item-1"><a href="link2.html">第二项</a></li>
         <li class="item-0">第一项</li>
         <li class="item-1 active"><a href="link4.html">第四项</a></li>
         <li class="item-0"><a href="link5.html">第五项</a></li>

要筛选某个兄弟节点,我们依然可以向 siblings 方法传入 CSS 选择器,这样就会从所有兄弟节点中挑选出符合条件的节点。

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

四、遍历

pyquery选择结果可能是多个节点,也可能是单个几点,类型都是pyquery类型,没有bs那样的列表。

对当节点来说,可以直接打印输出,也可以直接转换成字符串。

from pyquery import PyQuery as pq
html  =  ''' 
<div id="container"> 
    <ul class="list"> 
         <li class="item-0">第一项</li> 
         <li class="item-1"><a href ="link2.html">第二项</a></li> 
         <li class="item-0 active"><a href="link3.html"><span class="bold">第三项</ span></a></li> 
         <li class="item-1 active"><a href="link4.html">第四项</a></li> 
         <li class="item-0" ><a href="link5.html">第五项</a></li> 
     </ul> 
</div> 
'''
doc = pq(html)
li = doc('.item-0.active')
print(li)
print(str(li))

对多个节点的获取需要遍历获取。

这把每个li节点遍历,需要调用items()方法

from pyquery import PyQuery as pq
html  =  ''' 
<div id="container"> 
    <ul class="list"> 
         <li class="item-0">第一项</li> 
         <li class="item-1"><a href ="link2.html">第二项</a></li> 
         <li class="item-0 active"><a href="link3.html"><span class="bold">第三项</ span></a></li> 
         <li class="item-1 active"><a href="link4.html">第四项</a></li> 
         <li class="item-0" ><a href="link5.html">第五项</a></li> 
     </ul> 
</div> 
'''
doc = pq(html)
lis = doc('li').items()#调用item后会得到一个生成器,遍历后就可逐个得到li节点对象
print(type(lis))
for li in lis:
    print(li)

<class 'generator'>
<li class="item-0">第一项</li>
         
<li class="item-1"><a href="link2.html">第二项</a></li>
         
<li class="item-0 active"><a href="link3.html"><span class="bold">第三项 span&gt;</span></a></li>
         
<li class="item-1 active"><a href="link4.html">第四项</a></li>
         
<li class="item-0"><a href="link5.html">第五项</a></li>

 五、获取信息

1、获取属性

获取某个pyquery类型节点后,可以调用attr()方法获取属性

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)
doc = pq(html)
a = doc('.item-0.active a')#选中class为item-0和active的li节点内的a节点
print(a,type(a))
print(a.attr('href'))

<a href="link3.html"><span class="bold">third item</span></a> <class 'pyquery.pyquery.PyQuery'>
link3.html

也可以使用,结果相同

print(a.attr.href)

当返回结果包含多个节点时,调用 attr 方法,只会得到第一个节点的属性。想获取所有的 a 节点的属性,就要用到前面所说的遍历了:

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)

a = doc('a')
for item in a.items():
    print(item.attr('href'))

link2.html
link3.html
link4.html
link5.html

2、获取文本

使用text()属性

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)

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

<a href="link3.html"><span class="bold">third item</span></a>
third item

但如果想要获取这个节点内部的 HTML 文本,就要用 html 方法。

如果得到的结果是多个节点,并且想要获取每个节点的内部 HTML 文本,则需要遍历每个节点。而 text() 方法不需要遍历就可以获取,它将所有节点取文本之后合并成一个字符串。

六、节点操作

pyquery可以为某个节点添加一个 class,移除某个节点等。

1、addClass 和 removeClass

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)

a = doc('.item-0.active')
print(a)
a.remove_class('active')
print(a)
a.add_class('active')
print(a)

<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
             
<li class="item-0"><a href="link3.html"><span class="bold">third item</span></a></li>
             
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>

2、attr、text、html

 attr 方法对属性进行操作,text 和 html 方法来改变节点内部的内容。

 attr 方法来修改属性,其中该方法的第一个参数为属性名,第二个参数为属性值。接着,调用 text 和 html 方法来改变节点内部的内容

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('.item-0.active')
print(li)
li.attr('name', 'link')
print(li)
li.text('changed item')
print(li)
li.html('<span>changed item</span>')
print(li)

<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
             
<li class="item-0 active" name="link"><a href="link3.html"><span class="bold">third item</span></a></li>
             
<li class="item-0 active" name="link">changed item</li>
             
<li class="item-0 active" name="link"><span>changed item</span></li>

调用 attr 方法后,li 节点多了一个原本不存在的属性 name,其值为 link。接着调用 text 方法,传入文本之后,li 节点内部的文本全被改为传入的字符串文本了。最后,调用 html 方法传入 HTML 文本后,li 节点内部又变为传入的 HTML 文本了。

所以说,如果 attr 方法只传入第一个参数的属性名,则是获取这个属性值;如果传入第二个参数,可以用来修改属性值。text 和 html 方法如果不传参数,则是获取节点内纯文本和 HTML 文本;如果传入参数,则进行赋值。

3、remove

from pyquery import PyQuery as pq
html  =  '''
<div class="wrap">
    Hello, World
    <p>This is a paragraph.</p>
 </div>
'''
doc = pq(html)
wrap = doc('.wrap')
wrap.find('p').remove()
print(wrap.text())

Hello, World

首先选中 p 节点,然后调用了 remove() 方法将其移除,然后这时 wrap 内部就只剩下 Hello, World 这句话了,然后再利用 text() 方法提取即可

七、伪类选择器

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)
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 节点

以上是关于python爬虫学习记录解析库的使用——pyquery的主要内容,如果未能解决你的问题,请参考以下文章

Python爬虫利器之解析库的使用

python爬虫之pyquery学习

值得收藏的Python第三方库

python爬虫学习记录基本库的使用——requests

python爬虫学习记录基本库的使用——urllib

python爬虫学习记录基本库的使用——正则表达式