在本文中博主将介绍pyquery的知识点,如果你认为BeautifulSoup这个CSS选择器不是那么强大,来认识一下pyquery的强大吧,个人认为BeautifulSoup是一个比较的老的库,已经很久没有更新了,但是现在市面上大多都是BeautifulSoup的文章,所以小编将在这里介绍pyquery的用法。
首先下载解析库
打开PyCharm的右下角的终端,在PyCharm中安装是为了防止安装到别的版本的Python
如果你没有下载对应的汉化包,点击terminal即可
然后直接在终端 中输入命令 pip install pyquery
如果最后终端最后一行显示Successful .......就安装成功了,如果是因为链接的问题
换成以下命令即可 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyquery
这里博主就不讲解如何永久换成清华源了,如果需要可以在评论区回复一下
下面开始正式讲解pyquery的用法
我们解析将一直用以下HTML文本
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> '''
看一下代码
from pyquery import PyQuery as pq doc = pq(html) print(doc('li'))
首先导入PyQuery这个对象取别名为pq,接着将你要解析的HTML字符串传给PyQuery类做参数,这样就完成了初始化,接着向初始化对象中传入CSS选择器在本例中传入了li节点,就可以选择所有的li节点了。
结果如下
<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,这将自动对目标网址发送请求得到HTML字符串
pq(url = '*****************')
如果你要传入本地文件,操作也很简单
pq(filename=文件名)
查找结点
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> '''
from pyquery import PyQuery as pq doc = pq(html) print(doc('ul'))
选中了所有的ul节点,想要获取此节点下所有的子孙节点
list = doc.find('li')
即可获得所有的li子节点
如果只想要获取子节点
list = doc.children('li')
获取其兄弟节点
list = doc.siblings('对应的css选择器')
以上方法可以都不用记,直接用下面方法也可以
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> ''' from pyquery import PyQuery as pq doc = pq(html) ul = doc('ul') li = ul('li')
在找到ul节点之后在找li节点
遍历节点
注意pyquery选择的节点,无论时多个节点,还是单个节点,并没有像BeauyifulSoup那样返回一个列表,如果想要将其像列表一样遍历,使用items()方法获取一个生成器即可,代码如下
doc = pq(html) a = doc('li') for item in a.items(): print(item.attr('class'))
输出如下
item-0 item-1 item-0 active item-1 active item-0
但是如果你直接输出print(item)会出现换行符,因为每一个li节点完毕之后都会有一个换行符
结果如下
<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>
解决方法也很简单
str(item).replace('\n','')
因为通过pyqury提取出来的节点都是<class 'pyquery.pyquery.PyQuery'>类形的,所以需要转换成字符串
也可以通过正则来写正则表达式如下
re.sub('\n+','',str(item))
\n+的意思是匹配多个换行符。
获取其文本还有属性也很简单
获取节点文本
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> ''' from pyquery import PyQuery as pq doc = pq(html) a = doc('a') print(a.text())
即可获取全部所有a节点及其所以内部节点的文本内容
运行结果如下
second item third item fourth item fifth item
如果你选择的是li节点再使用li.text()结果如下
first item second item third item fourth item fifth item
获取节点属性
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> ''' from pyquery import PyQuery as pq doc = pq(html) a = doc('.item-0.active a') #调用attr方法在传入属性的名字即可获取对应的属性值 print(a.attr('href')) #也可以这样写 print(a.attr.href) #以上两种写法一致
注意看下面代码
from pyquery import PyQuery as pq doc = pq(html) a = doc('a') #调用attr方法在传入属性的名字即可获取对应的属性值 print(a.attr('href'))
运行结果如下
link2.html
结果中只有第一个节点的属性值
这是和text方法的区别,如果你想要获取全部节点的属性遍历即可
pyquery还有一个强大的功能是可以使用伪类选择器
代码如下
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> ''' from pyquery import PyQuery as pq doc = pq(html) # 获取li中的第一个节点 li = doc('li:first-child') print(li) # 获取li中的最后一个节点 li = doc('li:last-child') print(li) # 其中数字是几就获取第几个节点 li = doc('li:nth-child(2)') print(li) # 获取偶数节点 li = str(doc('li:nth-child(2n)')) print(li) # 获取带second文本的节点 li = doc('li:contains(second)') print(li)
其中的伪类写法常用的就这几种,各位在写的时候套用即可,其中的伪类选择器nth-child(n)非长的有用处,当你只想要在众多li标签的第一个或者第一个li就可以通过伪类选择器
如下例
<th>代理IP地址</th> <th>端口</th> <th>匿名度</th> <th>类型</th> <th>get/post支持</th> <th>位置</th> <th>响应速度</th> <th>最后验证时间</th>
我们在用代理ip的时候在提取ip和端口的号的时候可以直接通过nth-child(1),nth-child(2)获得
还有个BeautifulSoup没有的强大用法,可以对选中的节点进行操作
addClass 和 removeClass方法
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> ''' from pyquery import PyQuery as pq doc = pq(html) li = doc('.item-0.active') print(li) li.removeClass('active') print(li) li.addClass('active') print(li)
运行结果如下
<li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-0"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li>
另外attr和text方法也可以改变节点内容
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 class="item-0 active"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-0 active" name = "link"><a href="link3.html"><span class="bold">third item</span></a></li> <li class="item-0 active" name="link">change item</li>
注意事项
pyquery在找不到节点的时候并不会报错,只会打印一个空白行
例如
import requests from pyquery import PyQuery as pq ip_port = [] url = '*******************' doc = pq(requests.get(url).content.decode('gb2312')) print(doc('abc'))
在这段代码中最后的prinnt(doc('abc'))中一定能看出来我这里的CSS选择器是瞎写的吧但是
来看一下控制台的输出内容
就只打印了一个空白行,所以如果遇到空白行的时候一定要特别注意,是不是自己的CSS选择器写错了。
以上就是pyquery的基本用法,想要了解其更详细的内容请查阅官方文档
https://pyquery.readthedocs.io
早点了解官方文档的使用对技术的精进非常有好处
如果我的内容有错误请各位在评论中指出