注:来源于崔庆才<<python3爬虫实战开发2>>本人学习并分享,略有补充。
本文主要分为四个部分,首先是将网页内容转为pyquery解析对象,然后通过该对象进行节点的选择以及文本和属性的提取。并且可以通过一些方法可以更改节点的信息,以便更容易筛选得到想要的节点。
pip install pyquery
解析成pyquery有三种方式,分别是字符串、URL、文件三种,传入不同的参数就是不同的初始化了。
传入字符串来进行初始化pyquery对象
from pyquery import PyQuery as pq
html = """
<div>
<ul>
<li class="item-0">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><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(type(doc))
print(doc('li'))
上面我们直接传入html字符串,得到解析对象pyquery.pyquery.PyQuery
,然后通过css
选择器选择了li
节点,并打印了出来
传入URL参数来得到pyquery对象
from pyquery import PyQuery as pq
doc = pq(url="https://blog.iheng.xyz")
print(type(doc))
print(doc('title'))
上面我们往url
这个参数传入了链接地址,但考虑到网络的问题,获取的信息会较慢,得到的结果会较慢。
传入文件地址来进行初始化
from pyquery import PyQuery as pq
doc = pq(filename='test.html')
print(type(doc))
print(doc('li'))
这里我们创建一个test.html
文件,并将上面的内容复制进去,然后往filename
传入参数即可
直接往pyquery
对象中传入CSS选择器即可选择相对应的节点。具体的CSS选择器可以参考菜鸟教程的CSS选择器
from pyquery import PyQuery as pq
html = """
<div id="container">
<ul class="list">
<li class="item-0">first item</a></li>
<li class="item-1 active"><a href="link2.html">second item</a></li>
<li class="item-0 active"><a href="link3.html">third item</a></li>
<li class="item-1"><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('#container .list li'))
print(type(doc('#contain .list li')))
上面我们传入了CSS选择器,并打印了选择后的对象类型,发现依旧是pyquery.pyquery.PyQuery
,那么说明我们可以进行嵌套选择。
html = """
<div id="container">
<ul class="list">
<li class="item-0">first item</a></li>
<li class="item-1 active"><a href="link2.html">second item</a></li>
<li class="item-0 active"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
"""
在前面我们发现传入CSS选择器以后返回的依旧是pyquery.pyquery.PyQuery
类型的对象,那么我们依旧可以直接传入CSS选择器来得到目标节点。
doc = pq(html)
result = doc('#container .list li')
print(type(result))
print(result('a'))
上面我们先是选择了li
节点,然后在此基础上又选择了a
节点并打印了出来。
find()
方法我们也可以通过find()
方法来获取子节点,当然也可以是子孙节点,只要往里面传入CSS选择器即可。例子如下:
print(result.find('a'))
上面打印出来的结果与前面的嵌套选择一致
children()
方法该方法与find()
方法一致,但查找范围局限于子节点,并不能查找到子孙节点。下面这个例子可以对比:
doc = pq(html)
result = doc('#container .list')
print('find方法:',result.find('a'))
print('children方法:',result.children('a'))
find方法: <a href="link2.html">second item</a><a href="link3.html">third item</a><a href="link4.html">fourth item</a><a href="link5.html">fifth item</a>
children方法:
结果是一个能够返回a
节点,而另一个返回为空,但依旧是pyquery.pyquery.PyQuery
类型。
这里我们传入字符串html,然后依次使用parent()
与parents()
方法获取父节点、祖先节点,向方法中传入CSS选择器就可进行筛选。
html = """
<div id="container">
<ul class="list">
<li class="item-0">first item</a></li>
<li class="item-1 active"><a href="link2.html">second item</a></li>
<li class="item-0 active"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
"""
parent()
doc = pq(html)
items = doc('.list')
container = items.parent()
print(type(container))
print(container)
上面我们先是选择了类为llist
的节点,然后用parent()
方法得到了该节点的父节点,并打印了它的类型(pyquery.pyquery.PyQuery
),并将得到的节点打印出。
parents()
doc = pq(html)
items = doc('.list')
container = items.parents('#container')
print(type(container))
print(container)
这里我们利用了parents()
方法,得到的是全部节点,但我们往里面传入了#container
CSS选择器,得到了相应id的祖先节点。
doc = pq(html)
li = doc('.list .item-0.active')
print(li.siblings('.active'))
上面我们调用了siblings()
方法,并往里面传入了CSS选择器,最后得到相应的兄弟节点。
当我们获得的节点并不是一个的时候,需要items()
将节点转为生成器,并从生成器中获取内部需要的节点。
doc = pq(html)
li = doc('.list .item-0.active').siblings()
print(type(li.items()))
for i in li.items():
print(i)
上面我们打印了由items()
方法返回的对象类型,打印出来是一个生成器,我们可以用for
循环打印出内部的各个节点。
伪类选择器只是选择器特殊的一种,通过相对的位置或属性进行选择,具体可以参考菜鸟教程
html = """
<div id="container">
<ul class="list">
<li class="item-0">first item</a></li>
<li class="item-1 active"><a href="link2.html">second item</a></li>
<li class="item-0 active"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
"""
from pyquery import PyQuery as pq
doc = pq(html)
li = doc('li:first-child')
print(li)
li = doc('li:last-child')
print(li)
doc = pq(html)
a = doc('.item-0.active a')
print(a,type(a))
print(a.attr('href'))
我们利用attr('属性名')
方法获得节点的属性,不向attr()
传入属性名会报错。当然也可以利用attr
属性来获取,方法如下:
print(a.attr.href)
text()
doc = pq(html)
a = doc('.item-0.active a')
print(a.text())
上面我们用text()
方法直接获得了a节点的内容,倘若获取是的多节点,那么得到是所有的li节点内部的纯文本,各节点内容中间用一个空格分隔开,即返回结果是一个字符串。
html()
doc = pq(html)
a = doc('.item-0.active')
print(a.html())
上面我们选择了li
节点,li
节点内部包括a
节点,如果使用text()
方法获取的话,得到是a
节点内部的内容,而html()
方法则返回了包含a
节点的文本,结果如下:
<a href="link3.html">third item</a>
如果获取的是多个节点,如果用此方法得到的是第一个节点的内容
addClass
和removeClass
这两个方法都是对节点的class
进行修改。一个是增加class
,另一个是减少。
html = """
<div class="wrap">
<div id="container">
<ul class="list">
<li class="item-0">first item</a></li>
<li class="item-1 active"><a href="link2.html">second item</a></li>
<li class="item-0 active"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
</div>
"""
from pyquery import PyQuery as pq
doc = pq(html)
li = doc('.item-0.active')
print(li)
li.remove_class('active')
print(li)
li.add_class('active')
print(li)
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>
'''
from pyquery import PyQuery as pq
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)
上面的操作分别在获取节点内容的基础上传入了参数,第一个先是选择了对应的name
属性,但节点并没有该属性,然后就添加了进去。
后面的text()
、html()
也传入了响应的参数使得原内容得到了修改。