爬虫学习:pyquery的使用

爬虫学习:pyquery的使用

一、前言

刚开学没几天,比较忙,所以有一段时间没有更新博客了,上学前几天,没有写博客,是因为我当时正在研究人工智能,目前还在整理,后续我会把它总结发出来的。

这是我的学习专栏:Python爬虫学习

前面我们学习了Beautiful Soup的使用,最后我们提到了CSS选择器,Beautiful Soup库在CSS选择器上并没有很强大,所以这次我们学习一个新的工具——今天的主角:pyquery。

让我们一起来学习有关pyquery的知识吧!

二、我的环境

  • 电脑系统:Windows 11
  • 语言版本:Python 3.10.4
  • 编译器:VsCode

三、准备工作

1、下载安装

在cmd或者vscode终端输入如下命令:

pip install pyquery

2、初始化

pyquery解析HTML文本的时候有很多种初始化方法,比如字符串初始化,URL初始化,文件初始化等等,我所说的三种方法对应的就分别传入字符串、URL和文件来初始化的。

  • 字符串初始化

    直接使用HTML文本当作初始化参数:

    from pyquery import PyQuery as pq
    
    html = """
    <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'))
    

    他运行的结果是:

    <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>
    
  • URL初始化

    使用网页的URL来当作初始化参数

    from pyquery import PyQuery as pq
    
    doc = pq(url='https://baidu.com')
    print(doc('title'))
    

    它运行的结果是:

    <title>百度一下,你就知道</title>
    

    也可以直接使用requests库来获取URL

    from pyquery import PyQuery as pq
    import requests
    
    doc = pq(requests.get('https://baidu.com').text)
    print(doc('title'))
    

    这个结果跟上面的一样,两个方法是等效的。

  • 文件初始化

    也就是通过传递本地文件作为参数来实现的。

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

3、基本的CSS选择器

先举个例子:

from pyquery import PyQuery as pq

html = """
<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'))
for item in doc('#container .list li').itenms():
    print(item.text)

它运行的结果是:

<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>
message
message2
message3
message4
message5

这里的CSS选择器就是‘#container .list li’,它的意思是先选取id为container的节点,然后再选取该节点内部class为list的所有li节点,然后再使用for循环和text()方法获取节点内的文本信息。

四、pyquery库的基本用法

1、查找节点

  • 查找子节点

    from pyquery import PyQuery as pq
    
    html = """
    <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'>
    <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>
    
    
    <class 'pyquery.pyquery.PyQuery'>
    <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>
    

    find()方法跟之前的一样,会返回所有符合条件的节点,另外如果只想查找子节点,就可以直接使用children()方法,不传入选择器就默认选择全部子节点,传入的话就选择对应的子节点,例如我要寻找class为active的节点:

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

    它运行的结果是:

    <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>
    
  • 查找父节点

    from pyquery import PyQuery as pq
    
    html = """
    <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)
    

    它运行的结果是:

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

    使用parent()方法可以获得直接父节点,如果要获取祖先节点,就需要使用parents()方法:

    parents = items.parents()
    print(parents)
    

    它运行的结果是:

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

    parents()方法会返回所有的祖先节点,如果需要返回选定的祖先节点,就需要传入CSS选择器进行选择返回,例如:

    parent = items.parents(.wrap)
    print(parent)
    

    它运行的结果是:

    <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>
    
  • 查找兄弟节点

    from pyquery import PyQuery as pq
    
    doc = pq(html)
    items = doc('.list')
    li = doc('.list .item0.active')
    print(li.siblings())
    

    它运行的结果是:

    <li class="item1"><a href="link2.html">message2</a></li>
    <li class="item0">message</li>
    <li class="item1 active"><a href="link4.html">meaasge4</a></li>
    <li class="item0"><a href="link5.html">message5</a></li>
    

    如果要从兄弟节点内寻找特定的节点,直接往siblings()中传入选择器即可:

    from pyquery import PyQuery as pq
    
    doc = pq(html)
    items = doc('.list')
    li = doc('.list .item0.active')
    print(li.siblings('.active'))
    

    它运行的结果是:

    <li class="item1 active"><a href="link4.html">meaasge4</a></li>
    

2、遍历节点

pyquery返回的结果并不是列表,单个节点或者多个节点,单个节点可以直接打印出来,多个节点就需要一个一个遍历出来,使用items方法遍历:

from pyquery import PyQuery as pq

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

它运行的结果是:

<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>
  • 获取属性

    我们使用attr进行属性获取:

    from pyquery import PyQuery as pq
    
    doc = pq(html)
    a = doc('.item0.active a')
    print(a)
    print(a.attr('href'))
    

    它运行的结果是:

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

    a.attr(‘href’)也可以换成a.attr.href,两者是等效的。

    但是如果选择的是多个元素的话,只使用attr是不行的,还需要加上遍历才行:

    from pyquery import PyQuery as pq
    
    doc = pq(html)
    a = doc('a')
    for item in a.items():
        print(item.attr('href'))
    

    它运行的结果是:

    link2.html
    link3.html
    link4.html
    link5.html
    
  • 获取文本

    获取文本使用text()方法:

    from pyquery import PyQuery as pq
    
    doc = pq(html)
    a = doc('.item0.active a')
    print(a)
    print(a.text())
    

    它运行的结果是:

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

    如果要获取节点内部的HTML文本就需要使用html方法:

    from pyquery import PyQuery as pq
    
    doc = pq(html)
    li = doc('.item0.active')
    print(li)
    print(li.html())
    

    它运行的结果是:

    <li class="item0 active"><a href="link3.html"><span class="bold">message3</span></a></li>
    
    <a href="link3.html"><span class="bold">message3</span></a>
    

    如果获取多个节点的话,text和html方法会返回什么?

    from pyquery import PyQuery as pq
    
    doc = pq(html)
    li = doc('li')
    print(li.html())
    print(type(li.html()))
    print(li.text())
    print(type(li.text()))
    

    它运行的结果是:

    message
    <class 'str'>
    message message2 message3 meaasge4 message5
    <class 'str'>
    

    可以看出,html返回了第一个li节点内的HTML文本,而text方法返回了所有li节点内部的纯文本,返回结果的类型都是字符串类型。

3、节点操作

pyquery提供了非常多能对节点进行动态修改的方法,下面我就总结其中几种常见的方法

  • addClass和removeClass

    from pyquery import PyQuery as pq
    
    html = """
    <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)  
    

    它运行的结果是:

    <li class="item0 active"><a href="link3.html"><span class="bold">message3</span></a></li>
    
    <li class="item0"><a href="link3.html"><span class="bold">message3</span></a></li>
    
    <li class="item0 active"><a href="link3.html"><span class="bold">message3</span></a></li>
    

    显而易见,addClass方法是添加class属性,removeClass方法就是移除class方法。

  • attr、text和html

    from pyquery import PyQuery as pq
    
    html = """
    <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)
    

    它运行的结果是:

    <li class="item0 active" name="link"><a href="link3.html"><span class="bold">message3</span></a></li>
    
    <li class="item0 active" name="link">changed item</li>
    
    <li class="item0 active" name="link"><span>changed item</span></li>
    

    可以看出,attr方法可以修改属性并添加新属性,text方法可以改变li节点内部的文本,html方法也可以改变li节点内部的HTML本文。

  • remove

    from pyquery import PyQuery as pq
    
    html = """
    <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、伪类选择器

伪类选择器例如:选择第一个节点,选择最后一个节点,选择奇偶数节点、包含某一文本的节点等等。

from pyquery import PyQuery as pq

html = """
<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节点: <li class="item0">message</li>

选择最后一个li节点: <li class="item0"><a href="link5.html">message5</a></li>

选择第二个li节点: <li class="item1"><a href="link2.html">message2</a></li>

选择第三个li节点之后的li节点: <li class="item1 active"><a href="link4.html">meaasge4</a></li>
<li class="item0"><a href="link5.html">message5</a></li>

选择偶数位置的li节点: <li class="item1"><a href="link2.html">message2</a></li>
<li class="item1 active"><a href="link4.html">meaasge4</a></li>

选择包含message2的li节点: <li class="item1"><a href="link2.html">message2</a></li>

五、最后我想说

有关pyquery的基本学习就到这里了,但是pyquery中的方法还有很多,需要大家自行去官方文档去学习,篇幅有限,就不列举那么多了。

这篇博客是我使用我刚买的轻薄本来书写的,目前感觉还不错,后续如果是一些轻量的学习,我都会使用这个笔记本进行学习总结,大型项目或者需要高配置的,就会使用我另一个3070的笔记本。

来学校之后就没有在家时间那么多了,目前大三的我,正在学习有关大数据方面的专业课,所以更新慢请见谅,谢谢,后续我也会更新有关我专业课知识的博客,尽情期待,哈哈哈。

来学校之后我会规划一下写博客的时间,以及我会尽快更新我提到的AI语言助手的博客。

最后,文章如果出现错误之处,还请大家为我指出,谢谢!创造不易,期待得到你们的支持!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-北天-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值