自从有了pyquery,我手里的xpath瞬间他就不香了
![](https://tva1.sinaimg.cn/large/006xl9pBly1gxi5fffszwj30p00an453.jpg)
📢 大家好,我是小菜狗同学,一名大一的后端爱好者
📢 这篇文章将讲解爬虫中解析pysquery的用法
📢 非常感谢你的阅读,不对的地方欢迎指正 😘😘
📢 愿你忠于自己,热爱生活,生活中不仅要有技术,更有诗和远方。
📢本文内容参考 崔庆才<网络爬虫开发实战第二版>
1.如何安装pyquery
pip install pyquery
更加详细的安装可以参考崔庆才大佬,https://cuiqingcai.com/5186.htm
2. 为何选择使用pyquery
我们知道目前主流的爬虫解析库:
- PyQuery
- Beautifulsoup
- Scrapy Selectors
- 正则表达式
- xpath
PyQuery和scrapy Selectors都是基于lxml模块,xlml和正则是基于C写的,只有Beautifulsoup是用纯python写的,所以解析速度,毫无疑问Beautifulsoup比其它解析满了五倍以上。而正则表达式比较复杂 容易出错,pyquery相较于xpath更简洁。你信不信当你看完,你会觉得你手里的这些他都不香了
![](https://tva1.sinaimg.cn/large/006xl9pBly1gxi5klkpdkj310m0rg1cs.jpg)
不信?下面来用一个实例感受一下
# 引入对象 取别名
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)
# 传入li节点 这样就可以选取所有li节点了
print(doc('li'))
out: <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>
URL初始化
初始化的参数除了可以用字符串还可以使用url的方式传递,只需要指定Pyquery的对象参数为url即可
doc = pq(url='https://cuiqingcai.com')
print(doc('title'))
out:/ <title>静觅丨崔庆才的个人站点<\title>
这段代码是什么意思呢?首先Pyquery对象会去请求这个url,然后得到URL返回的内容初始化给pq类
文件初始化
doc = pq(filename='demo.html')
print(doc('li'))
这样它会先读取本地的文件内容,然后将文件内容以字符串的形式传递给 pyquery 类来初始化。
基本CSS选择器
html = '''
<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>
'''
from pyquery import PyQuery as pq
doc = pq(html)
print(doc('#container .list li'))
print(type(doc('#container .list li')))
out: <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>
这里我们初始化后,给doc传入了一个CSS选择器#container .list li 意思是先选取id为container的节点,再选取其内部class为list的所有li节点
下面,我们直接遍历这些节点,然后调用 text 方法,就可以获取节点的文本内容
doc = pq(html)
lis = doc('#container .list li')
for item in lis.items():
# 提取li节点的所有文本内容
print(item.text())
查找子节点
doc = pq(html)
# 选取class为list的节点
items = doc('.list')
print(items)
lis = items.find('li')
print(type(lis))
print(lis)
find 的查找范围是节点的所有子孙节点,而如果我们只想查找子节点,那可以用 children 方法:
lis = items.children()
print(type(lis))
print(lis)
如果要筛选所有子节点中符合条件的节点,比如想筛选出子节点中 class 为 active 的节点,可以向 children 方法传入 CSS 选择器 .active,代码如下:
doc = pq(html)
items = doc('.list')
a = items.children('.item-1')
print(a)
我们看到输出的结果已经做了筛选,留下了 class 为 .item-1 的节点。
父节点
items.parent()方法 返回所有的 父辈节点 如果需要筛选 在其中传入CSS选择器
如果想返回祖先节点 ites.parents()即可*
兄弟节点
doc = pq(html)
# 这里需要注意 这两种是截然不同的意义
#在这个例子中我们首先选择 class 为 list 的节点,内部 class 为 item-0 和 active 的节点,也就是第 3 个 li 节点。很明显,它的兄弟节点有 4 个,那就是第 1、2、4、5 个 li 节点。
li = doc('.list .item-0.active')
# 这个写法表明首先取class为list的节点,内部class为item-0的节点,之后再选取其内部为active的节点
li = doc('.list .item-0 .active')
# 对兄弟节点再做筛选
print(li.siblings('.active'))
print(li.siblings())
遍历
pyquery 的选择结果既可能是多个节点,也可能是单个节点,类型都是 pyquery 类型,并没有返回列表。
对于单个节点来说,可以直接打印输出,也可以直接转成字符串
from pyquery import PyQuery as pq
doc = pq(html)
li = doc('.item-0.active')
print(li)
print(str(li))
对于有多个节点的结果,我们就需要用遍历来获取了。例如,如果要把每一个 li 节点进行遍历,需要调用 items 方法:
lis = doc('li').items()
调用 items 方法后,会得到一个生成器,遍历一下,就可以逐个得到 li 节点对象了,每个对象非常灵活,可以继续使用如上的方法。
doc = pq(html)
lis = doc("li").items()
for i in lis:
print(i.text())
获取信息
-
获取属性
-
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, type(a)) print(a.attr('href')) # link3.html
当返回结果包含多个节点时,调用 attr 方法,只会得到第 1 个节点的属性。
-
获取文本
很简单
print(a.text())
但如果你想要获取这个节点内部的 HTML 文本,就要用 html 方法了:
print(a.html())
text 方法不需要遍历就可以获取,它将所有节点取文本之后合并成一个字符串。
html 需要遍历获取 不然只能返回一个
remove
remove 方法就是移除
html = '''
<div class="wrap">
Hello, World
<p>This is a paragraph.</p>
</div>
'''
from pyquery import PyQuery as pq
doc = pq(html)
wrap = doc('.wrap')
print(wrap.text())
我们如果此时只想要Hello world怎么办,直接使用text()全部提取了
这时 remove 方法就可以派上用场了
wrap.remove('p') # 选中p节点 remove移除即可
伪类选择器
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)') #包含文本second的节点
print(li)
THE LAST
关于 CSS 选择器的更多用法,可以参考:http://pyquery.readthedocs.io/en/latest/api.html。
怎么样 是不是感觉手里的xpath瞬间他就不香了
求👍求💗
![](https://tva1.sinaimg.cn/large/006xl9pBly1gxi5mjrptaj30j60j610a.jpg)