Python爬虫框架之PyQuery的使用

前言

Python之所以很适合写爬虫, 其中一个原因是拥有丰富的解析器Lib

HTML解析为例就有XPATHBeautiful SoupPyQuery等等

想用哪个用哪个

那么今天我们就来介绍其中PyQuery这个解析器的用法, PyQuery的语法和jquery大同小异, 如果你熟悉jquery的使用, 那么这款解析器绝对适合你

组件安装

1
pip install pyquery

组件引入

1
from pyquery import PyQuery as pq

三个小示例

假设我们有这么一个HTML文本:

1
2
3
4
5
6
7
8
<div id="wrap">
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>
</div>

如果我们要获取div标签下的所有内容(包含div标签), 那么我们可以这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pyquery import PyQuery as pq
html = '''
<div id="wrap">
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>
</div>
'''
doc = pq(html)
result=doc("#wrap")
print(result)

得到的结果为:

1
2
3
4
5
6
7
8
<div id="wrap">
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>
</div>

如果我们要获取div标签下的所有元素(不包含div标签),, 那么我们可以使用children()函数, 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pyquery import PyQuery as pq
html = '''
<div id="wrap">
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>
</div>
'''
doc = pq(html)
result=doc("#wrap").children()
print(result)

那么得到的结果为:

1
2
3
4
5
6
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>

如果我们要获取ul标签下的所有内容, 我们可以这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pyquery import PyQuery as pq
html = '''
<div id="wrap">
<ul class="s_from">
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>
</ul>
</div>
'''
doc = pq(html)
result=doc("ul").html()
print(result)

那么得到的结果为:

1
2
3
4
我是测试文本
<link href="http://aaa.com">aaa</link>
<link href="http://bbb.com">bbb</link>
<link href="http://ccc.com">ccc</link>

通过上面三个小例子示范我们大致感受了一下PyQuery的使用, 但是依然无法深入了解, 接下来我们对其用法进行总结

使用总结

  1. 通过id获取html使用#

    1
    pq(html)("#xxx")
  2. 通过class获取html使用’.`

    1
    pq(html)(".xxx")
  3. 通过标签名获取html直接使用标签

    1
    pq(html)("div")
  4. 查找父元素使用parent()

    1
    pq(html)("#xxx").parent()
  5. 获取目标位置下包裹的所有的元素

    1
    pq(html)("#xxx").children()
  6. 获取目标位置下包裹的所有的html内容

    1
    pq(html)("#xxx").html()
  7. 获取目标位置下包裹的所有的文本内容

    1
    pq(html)("#xxx").text()

    注意: 我们要和html()children()进行区分, 我们用一个例子来解释:

    如果使用html():

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <link href="http://aaa.com">aaa</link>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("#wrap").html()
    print(result)

    得到的结果为:

    1
    2
    3
    4
    我是测试文本
    <link href="http://aaa.com"/><p>aaa</p>
    <link href="http://bbb.com"/>bbb
    <link href="http://ccc.com"/>ccc

    如果使用children():

    1
    2
    3
    doc = pq(html)
    result=doc(".s_from").children()
    print(result)

    得到结果为:

    1
    2
    3
    <link href="http://aaa.com"/><p>aaa</p>
    <link href="http://bbb.com"/>bbb
    <link href="http://ccc.com"/>ccc

    如果使用text():

    1
    2
    3
    doc = pq(html)
    result=doc(".s_from").text()
    print(result)

    得到结果为:

    1
    2
    3
    4
    我是测试文本
    aaa
    bbb
    ccc

    一目了然

  8. 查找兄弟元素使用siblings()

    1
    pq(html)("#xxx").siblings()
  9. 将所有获取到的元素组成数组items()

    1
    pq(html)("#xxx").items()

    比如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <link href="http://aaa.com">aaa</link>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("link")
    print(result)

    那么得到的结果为:

    1
    2
    3
    4
    <link href="http://aaa.com"/>aaa
    <link href="http://bbb.com"/>bbb
    <link href="http://ccc.com"/>ccc
    <link href="http://ddd.com"/>ccc

    如果我们想对其进行遍历获取其中某一个元素, 那么可以这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <link href="http://aaa.com">aaa</link>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("link").items()
    for i in result:
    print(i)
  10. 获取标签属性信息使用attr()

    还是上面的例子, 如果我们要获取link标签中href的值, 那么可以这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <link href="http://aaa.com">aaa</link>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("link").items()
    for i in result:
    print(i.attr('href'))
    #或者
    print(i.attr.href)
    # 上面两种获取href的方法任选其一
  11. 精确查找使用空格

    啥意思呢, 我们还是用一个例子来说明:

    如果我们要利用层级关系精确查找, 那么可以这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <link id="first" "href="http://aaa.com">111<p>aaa</p></link>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("#wrap .s_from #first")
    print(result)

    层级之间使用空格进行分隔, 得到的结果为:

    1
    <link id="first"/>111

    我们惊奇地发现, 查找到的内容有缺失,居然没有打印<p>aaa</p>, 如果我们将link标签改为a标签:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # coding:utf-8

    from pyquery import PyQuery as pq
    html = '''
    <div id="wrap">
    <ul class="s_from">
    我是测试文本
    <a id="first" "href="http://aaa.com">111<p>aaa</p></a>
    <link href="http://bbb.com">bbb</link>
    <link href="http://ccc.com">ccc</link>
    </ul>
    </div>
    <link href="http://ddd.com">ccc</link>
    </ul>
    '''
    doc = pq(html)
    result=doc("#wrap .s_from #first")
    print(result)

    则结果为:

    1
    <a id="first">111<p>aaa</p></a>

    你可能会说之前写的语法有问题 link标签怎么能又嵌套其他标签呢, 事实上, 你也难保会碰上诸如此类的情况, 毕竟前端鱼龙混杂, 当我们获取不到值的时候, 需要特殊注意一下

  1. 根据标签属性精确查找

    比如 我们要查找itemprop属性值为keywordsmeta标签, 可以这样写:

    1
    2
    doc = pq(html)
    doc('meta[itemprop="keywords"]')

    如果需要嵌套查找 比如查找itemprop属性值为authordiv标签下的itemprop属性值为namemeta标签 可以这样写:

    1
    2
    doc = pq(html)
    d('div[itemprop="author"]')('meta[itemprop="name"]')

    更多层级的嵌套也是类的写法

  2. 给元素添加class

    1
    pq(html)("#xxx").addClass('active')

    ​ 如果class已经存在, 则不重复添加

  3. 移除元素的class

    1
    pq(html)("#xxx").removeClass('active')
  4. 给元素添加css样式

    1
    pq(html)("#xxx").css('font-size','14px')
  5. 移除某个标签

    1
    pq(html)("#xxx").remove('ul')
  6. 伪类选择器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    from pyquery import PyQuery as pq
    html = '''
    <div href="wrap">
    hello nihao
    <ul class="s_from">
    asdasd
    <link class='active1 a123' href="http://asda.com"><a>helloasdadasdad12312</a></link>
    <link class='active2' href="http://asda1.com">asdadasdad12312</link>
    <link class='movie1' href="http://asda2.com">asdadasdad12312</link>
    </ul>
    </div>
    '''

    doc = pq(html)
    its=doc("link:first-child")
    print('第一个标签:%s'%its)
    its=doc("link:last-child")
    print('最后一个标签:%s'%its)
    its=doc("link:nth-child(2)")
    print('第二个标签:%s'%its)
    its=doc("link:gt(0)") #从零开始
    print("获取0以后的标签:%s"%its)
    its=doc("link:nth-child(2n-1)")
    print("获取奇数标签:%s"%its)
    its=doc("link:contains('hello')")
    print("获取文本包含hello的标签:%s"%its)
  7. 多选查找, 用逗号分隔

    1
    pq(html)("h1,h2") #表示查找h1和h2标签
  8. 过滤查找filter

    1
    pq(html).filter(".fisrt") #过滤出class为.fisrt的内容
  9. 使用find方法查找

    上面我们介绍的查找都是pq(html)("xxx") 列表形式, 除此之外我们还可以用使用调用函数的形式进行查找, 效果也是一样的:

    1
    2
    3
    pq(html)("#xxx") 
    #或者用
    pq(html).find("#xxx")

最后

以上只是该库的一部分使用方法, 一边用一边掌握, 我个人还是比较喜欢使用这一套解析库, 能解决大部分的应用场景

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

0%