zoukankan      html  css  js  c++  java
  • pyquery库

    虽然Beautiful Soup库的功能非常强大,但CSS选择器功能有些弱,至少相对于本章介绍的pyquery库弱。

    一.什么是pyquery

    pyquery在CSS选择器层面上较强。(待补)

    二.安装pyquery

    2.1pip 安装 pyquery

    pip install pyquery
    

    2.2离线安装

    在此网页上找到whl文件安装包,这网上的离线安装包好像都是最新的
    然后再

    pip install pyquery‑1.4.3‑py3‑none‑any.whl
    

    三.pyquery的基本用法

    pyquery包中有一个PyQuery类,使用pyquery要先导入该类,然后创建PyQuery类的实例。可以通过如下3种方法将HTML文档传入PyQuery对象:字符串、URL、文件
    PyQuery对象有很多API可以操作HTML文档,最简单的是直接获取某个节点
    本例创建PyQuery对象,并通过上述3种方式为PyQuery对象传入HTML文档,最后得到指定节点的内容

    import pyquery
    from pyquery import PyQuery as pq
    html = '''
    <div>
        <ul>
            <li class="item1" value1="1234" value2 = "hello world"><a href="https://geekori.com"> geekori.com</a></li>
            <li class="item"><a href="https://www.jd.com"> 京东商城</a></li>        
        </ul>
        <ul>
            <li class="item3"><a href="https://www.taobao.com">淘宝</a></li>
            <li class="item" ><a href="https://www.microsoft.com">微软</a></li>
            <li class="item2"><a href="https://www.google.com">谷歌</a></li>
        </ul>
    </div>
    
    '''
    
    doc = pq(html)
    for a in doc('a'):
        print(a.get('href'),a.text)
    
    doc = pq(url='https://www.jd.com')
    print(doc('title'))
    
    import requests
    doc = pq(requests.get('https://www.jd.com').text)
    print(doc('title'))
    
    # 下方打开文件报错
    # UnicodeDecodeError: 'gbk' codec can't decode byte 0xac in position 254: illegal multibyte sequence
    doc = pq(filename='demo.html') 
    print(doc('head'))
    

    三.CSS选择器

    创建一个CSS选择器需要创建一个PyQuery对象,PyQuery类的构造方法需要传入一个HTML文档
    由于PyQuery类重载了函数调用运算符(实现了__call__函数),所以可以向调用函数一样使用PyQuery的实例,函数参数就是CSS代码

    from pyquery import PyQuery as pq
    html = '''
    <div id="panel">
        <ul class="list1">
            <li class="item1" value1="1234" value2 = "hello world"><a href="https://geekori.com"> geekori.com</a></li>
            <li class="item"><a href="https://www.jd.com"> 京东商城</a></li>        
        </ul>
        <ul class="list2">
            <li class="item3"><a href="https://www.taobao.com">淘宝</a></li>
            <li class="item" ><a href="https://www.microsoft.com">微软</a></li>
            <li class="item2"><a href="https://www.google.com">谷歌</a></li>
        </ul>
    </div>
    
    '''
    # 创建PyQuery对象
    doc = pq(html)
    # 提取id属性值为panel,并在该节点中所有属性值为list1的所有节点
    result = doc('#panel .list1')
    # 输出result的类型,但仍然是PyQuery对象
    print(type(result))
    print(result)
    # 在result为根的基础上,提取其中class属性值为item的所有节点
    print(result('.item'))
    # 提取其中的第2个a节点的href属性值和文本内容
    print(result('a')[1].get('href'),result('a')[1].text)
    print()
    # 抓取京东商城导航条链接文本
    import requests
    # 请求京东商城首页,并将返回的HTML代码传入pq对象
    doc = pq(requests.get('https://www.jd.com').text
    # 提取第一个ul节点
    group1 = doc('#navitems-group1') # 我电脑编码有问题吧,这group1原理没有报错,扯蛋的vscode
    # 提取出前四个链接的文本
    print(group1('a')[0].text,group1('a')[1].text,group1('a')[2].text,group1('a')[3].text)
    group2 = doc('#navitems-group2')
    print(group2('a')[0].text,group2('a')[1].text,group2('a')[2].text,group2('a')[3].text)
    
    group3 = doc('#navitems-group3')
    print(group3('a')[0].text,group3('a')[1].text)
    
    

    四.查找节点

    本节介绍一些常用的查询函数,这些函数与JQuery中的函数用法完全相同,用于查找HTML文档中的节点

    4.1查找子节点

    本例使用find方法和children方法查找test.html文件中第一个ul节点的所有a子节点
    find查找子节点,连同非直接子节点<a>ok<a>都找出来了,而children方法并没有找到该子节点

    from pyquery import PyQuery as pq
    from lxml import etree
    
    # 分析test.html文件
    doc = pq(filename='test.html')
    # 查找所有class属性值为list1的节点,只有第一个ul节点满足条件
    result = doc('.list1')
    # 查找所有的a节点,包括子孙节点
    aList = result.find('a')
    print(type(aList))
    for a in aList:
        # 输出每一个查找到的a节点
        print(str(etree.tostring(a,pretty_print=True,encoding='utf-8'),'utf-8'))
    
    
    print('------------------')
    # 查找所有class属性值为item的所有节点
    result = doc('.item')
    aList = result.children('a')
    
    for a in aList:
        # 输出每一个查找到的a节点
        print(str(etree.tostring(a,pretty_print=True,encoding='utf-8'),'utf-8'))
    

    4.2查找父节点

    通过parent方法可以查找直接父节点,通过parents方法可以查找所有的父节点,这两个方法都可以传入CSS选择器

    from pyquery import PyQuery as pq
    
    
    doc = pq(filename='test.html')
    result = doc('.item')
    print(result.parent())
    print('------------')
    print('父节点数:',len(result.parents()))
    print(result.parents())
    print('父节点数:',len(result.parents('#panel')),'节点名:',result.parents('#panel')[0].tag)
    

    4.3查找兄弟节点

    使用siblings方法可以查询当前节点的所有兄弟节点,包括节点前面和后面的同级节点。如果要查询特定的兄弟节点,可以为siblings方法传递CSS选择器参数。

    from pyquery import PyQuery as pq
    
    
    doc = pq(filename='test.html')
    result = doc('.item')
    print(result.siblings())
    print('----------------')
    print(result.siblings('.item2'))
    

    4.4获取节点信息

    节点包括如下信息:节点名称、节点属性、节点文本、整个节点的HTML代码、节点内部的HTML代码

    from pyquery import PyQuery as pq
    html = '''
    <div id="panel">
        <ul class="list1">
            <li class="item" value1="1234" value2 = "hello world">
                Hello
                123
                <a href="https://geekori.com"> geekori.com</a>
                World
            </li>
            <li class="item1" >
            </li>
        </ul>
        <ul class="list2">
            <li class="item3"><a href="https://www.taobao.com">淘宝</a></li>
            <li class="item"  value1="4321" value2 = "世界你好" >
                <a href="https://www.microsoft.com">微软</a>
            </li>
            <li class="item2"><a href="https://www.google.com">谷歌</a></li>
        </ul>
    </div>
    '''
    
    doc = pq(html)
    result = doc('.item')
    print(type(result))
    
    print('-------获取节点名---------')
    print(type(result[0]))
    print(result[0].tag)
    print(result[1].tag)
    print('-------获取属性---------')
    print('value1:',result[0].get('value1'))
    
    print('value2:',result.attr('value2'))
    print('value2:',result.attr.value2)
    
    print('----------------')
    for li in result.items():
        print(type(li))
        print(li.attr.value2)
    
    for li in result:
        print(type(li))
        print(li.get('value2'))
    print('--------获取文本--------')
    # 获取文本
    print(result.text())
    print('result.text()的类型:',type(result.text()))
    from urllib.parse import quote,unquote
    
    for node in result:
        print(node.text)
    print('-------节点HTML代码--------')
    from lxml import etree
    for node in result:
        print(str(etree.tostring(node, pretty_print=True,encoding='utf-8'),'utf-8'))
    
    print('-------获取节点内部HTML代码---------')
    print(result.html())
    

    4.5修改节点

    pyquery提供了一系列方法对节点进行动态修改,例如,为某个节点添加一个class,移除某个节点等,在很多场景下这些操作会为获取信息带来极大的便利

    4.5.1添加和移除节点的样式(addClass和removeClass)

    阅读下面代码需注意:
    多个样式要首尾相连,中间不能有空格
    添加和删除样式时,样式名不能带点(.),否则会将带点(.)作为样式名的一部分添加到class属性中
    添加删除多个样式时,多个样式之间用空格分隔
    如果要操作的是多个节点,那么addClass方法和removeClass方法对所有的节点有效

    from pyquery import PyQuery as pq
    html = '''
    <div id="panel">
        <ul class="list1" >
            <li class="item1 item2 item3" >谷歌</li>
            <li class="item1 item2">微软</li>
        </ul>
    
    </div>
    '''
    
    doc = pq(html)
    li = doc('.item1.item2')# 多个样式要首尾相连,中间不能有空格
    
    print(li)
    li.addClass('myitem') # 添加和删除样式时,样式名不能带点(.),否则会将带点(.)作为样式名的一部分添加到class属性中
    print(li)
    li.removeClass('item1')
    print(li)
    li.removeClass('item2 item3') # 添加删除多个样式时,多个样式之间用空格分隔
    print(li)
    li.addClass('class1 class2')# 如果要操作的是多个节点,那么addClass方法和removeClass方法对所有的节点有效
    print(li)
    
    

    4.5.2修改节点属性和文本内容(attr、removeAttr、text和html)

    使用attr方法可以向节点添加新的属性,如果添加的属性已经存在,则会修改原来的属性值。
    removeAttr方法,该方法需要传入一个字符串类型的值,用于设置节点内容
    修改节点文本可以使用text和html。其中html方法用于设置节点中的HTML代码,text方法用来设置文本形式的节点内容。
    其中text方法和html方法的最大区别就是转码和解析。

    text方法会自动将文本中的HTML符号转换成可以显示在浏览器上的符号,如将"<"转换为“&gt”`。而如果设置普通的文本,text方法和html方法的功能相同,如果设置了HTML代码样式的文本,如"<aaa",text方法会将其转化("<"转换为“&gt”),而html方法会将其变成"<a/>",`自动补齐节点右边的部分。
    

    如果text方法不加参数,会获取所有节点中的文本,不同文本之间用空格分隔。html方法只会返回第一个节点中的文本内容。

    from pyquery import PyQuery as pq
    html = '''
    <div id="panel">
        <ul class="list1" >
            <li class="item1 item2 item3" >谷歌</li>
            <li class="item1 item2">微软</li>
        </ul>
    
    </div>
    '''
    
    doc = pq(html)
    
    li = doc('.item1.item2')
    
    print(li)
    print(li.text())
    print(li.html())
    print('------------------')
    li.attr('id','list')
    li.attr('class','myitem1,myitem2')
    print(li)
    li.removeAttr('id')
    li.removeAttr('class')
    print(li)
    
    li.text('列表')
    print(li)
    li.text('
    <a href="https://www.google.com"/>
    ')
    print(li)
    li.html('
    <a href="https://www.google.com"/>
    ')
    print(li)
    print(li.text())
    print(li.html())
    

    4.5.3删除节点(remove)

    使用remove方法可以删除节点,该方法接收一个字符串类型的参数,用于指定要删除的节点名,如果不指定参数,则删除当前节点。

    from pyquery import PyQuery as pq
    html = '''
    <div id="panel">
        <ul class="list1" >
            <li class="item1 item2" >谷歌<p>微软</p>Facebook</li>
           
        </ul>
    
    </div>
    '''
    
    doc = pq(html)
    li = doc('.item1.item2')
    print(li.text())
    print('---------<p>微软</p>已经被删除----------')
    li.remove('p')
    print(li.text())
    
    li = doc('.item1.item2')
    print(li.find('p').remove())
    print(li.text())
    

    更多操作节点的方法,如append、empty、prepend等,这些方法与JQuery相应API的方法完全一致
    详细的用法可以参考官方文档

    五.伪类选择器

    CSS选择器之所以这么强大,一个很重要的原因解释他支持多种多样的伪类选择器,例如,选择第一个节点、最后一个节点,索引为奇数的节点、索引为偶数的节点、包含某一个文本的节点等
    本例演示了常用的伪类选择器的用法

    import pyquery
    from pyquery import PyQuery as pq
    html = '''
    <div>
        <ul>
            <li class="item1" ><a href="https://geekori.com"> geekori.com</a></li>
            <li class="item"><a href="https://www.jd.com"> 京东商城(https://www.jd.com)</a></li>
            <li class="item3"><a href="https://www.taobao.com">淘宝</a></li>
            <li class="item" ><a href="https://www.microsoft.com">微软</a></li>
            <li class="item2"><a href="https://www.google.com">谷歌</a></li>              
    
        </ul>
    
    </div>
    
    '''
    
    doc = pq(html)
    # 选取第一个节点
    li = doc('li:first-child')
    print(li)
    # 选取最后一个节点
    li = doc('li:last-child')
    print(li)
    # 选取第三个节点
    li = doc('li:nth-child(3)')
    print(li)
    # 选取索引小于2的li节点(索引从0开始)
    li = doc('li:lt(2)')
    print(li)
    # 选取所有大于3的li节点
    li = doc('li:gt(3)')
    print(li)
    # 选取序号为奇数的li节点
    li = doc('li:nth-child(2n+1)')
    print(li)
    # 选取序号为偶数的li节点
    li = doc('li:nth-child(2n)')
    print(li)
    # 选取文本内容包含com的所有li节点
    li = doc('li:contains(com)')
    print(li)
    # 选取文本内容包含com的所有节点
    all = doc(':contains(com)')
    print(len(all))
    # 输出每一个选取结果的节点名
    for t in all:
        print(t.tag, end=' ')
    
    努力拼搏吧,不要害怕,不要去规划,不要迷茫。但你一定要在路上一直的走下去,尽管可能停滞不前,但也要走。
  • 相关阅读:
    python批量裁剪图片
    Theano 报错:No suitable SharedVariable constructor could be found. Are you sure all kwargs are supported? We do not support the parameter dtype or type
    清华镜像连接
    ubuntu16.04查看占用GPU的程序
    pycharm报错:ImportError: libcusolver.so.8.0: cannot open shared object file: No such file or directory
    PyMysql的基本操作
    关于爬虫解析页面时的一些有意思的坑
    关于爬虫解析页面时的一些有意思的坑
    python 的一些高级函数
    python 的一些高级函数
  • 原文地址:https://www.cnblogs.com/wkhzwmr/p/15232359.html
Copyright © 2011-2022 走看看