python3解析库pyquery
pyquery是一个类似jquery的python库,它实现能够在xml文档中进行jQuery查询,pyquery使用lxml解析器进行快速在xml和html文档上操作,它提供了和jQuery类似的语法来解析HTML文档,支持CSS选择器,使用非常方便
1、pyquery安装
pip方式安装:
$pip install pyquery #它依赖cssselect和lxml包
pyquery==1.4.0
- cssselect [required: >0.7.9, installed: 1.0.3] #CSS选择器并将它转换为XPath表达式
- lxml [required: >=2.1, installed: 4.2.2] #处理xml和html解析库
验证安装:
In [1]: import pyquery In [2]: pyquery.text
Out[2]: <module 'pyquery.text' from '/root/pp1/.venv/lib/python3.6/site-packages/pyquery/text.py'>
2、pyquery对象初始化
pyquery首先需要传入HTML文本来初始化一个pyquery对象,它的初始化方式有多种,如直接传入字符串,传入URL或者传入文件名
(1)字符串初始化
from pyquery import PyQuery as pq html='''
<div id="wenzhangziti" class="article 389862">
<p>人生是一条没有尽头的路,不要留恋逝去的梦,把命运掌握在自己手中,让我们来掌握自己的命运,别让别人的干扰与诱惑,别让功名与利禄,来打翻我们这坛陈酿已久的命运之酒!</p>
</div>
'''
doc=pq(html) #初始化并创建pyquery对象
print(type(doc))
print(doc('p').text()) #
<class 'pyquery.pyquery.PyQuery'>
人生是一条没有尽头的路,不要留恋逝去的梦,把命运掌握在自己手中,让我们来掌握自己的命运,别让别人的干扰与诱惑,别让功名与利禄,来打翻我们这坛陈酿已久的命运之酒!
(2)URL初始化
from pyquery import PyQuery as pq doc=pq(url='https://www.cnblogs.com/zhangxinqi/p/9218395.html')
print(type(doc))
print(doc('title')) #
<class 'pyquery.pyquery.PyQuery'>
<title>python3解析库BeautifulSoup4 - Py.qi - 博客园</title>
PyQuery能够从url加载一个html文档,之际上是默认情况下调用python的urllib库去请求响应,如果requests已安装的话它将使用requests来请求响应,那我们就可以使用request的请求参数来构造请求了,实际请求如下:
from pyquery import PyQuery as pq
import requests doc=pq(requests.get(url='https://www.cnblogs.com/zhangxinqi/p/9218395.html').text)
print(type(doc))
print(doc('title')) #输出同上一样
<class 'pyquery.pyquery.PyQuery'>
<title>python3解析库BeautifulSoup4 - Py.qi - 博客园</title>
(3)通过文件初始化
通过本地的HTML文件来构造PyQuery对象
from pyquery import PyQuery as pq doc=pq(filename='demo.html',parser='html')
#doc=pq(open('demo.html','r',encoding='utf-8').read(),parser='html') #注意:在读取有中文的HTML文件时,请使用此方法,否则会报解码错误
print(type(doc))
print(doc('p'))
3、CSS选择器
在使用属性选择器中,使用属性选择特定的标签,标签和CSS标识必须引用为字符串,它会过滤筛选符合条件的节点打印输出,返回的是一个PyQuery类型对象
from pyquery import PyQuery as pq
import requests
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>
'''
doc=pq(html,parser='html')
print(doc('#container .list .item-0 a'))
print(doc('.list .item-1')) #
<a href="link3.html"><span class="bold">third item</span></a><a href="link5.html">fifth item</a>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-1 active"><a href="link4.html">fourth item</a></li>
4、查找节点
PyQuery使用查询函数来查询节点,同jQuery中的函数用法完全相同
(1)查找子节点和子孙节点
使用find()方法获取子孙节点,children()获取子节点,使用以上的HTML代码测试
from pyquery import PyQuery as pq
import requests doc=pq(html,parser='html')
print('find:',doc.find('a'))
print('children:',doc('li').children('a'))
(2)获取父节点和祖先节点
parent()方法获取父节点,parents()获取祖先节点
doc(.list).parent()
doc(.list).parents()
(3)获取兄弟节点
siblings()方法用来获取兄弟节点,可以嵌套使用,传入CSS选择器即可继续匹配
doc('.list .item-0 .active').siblings('.active')
5、遍历
对于pyquery的选择结果可能是多个字节,也可能是单个节点,类型都是PyQuery类型,它没有返回列表等形式,对于当个节点我们可指直接打印输出或者直接转换成字符串,而对于多个节点的结果,我们需要遍历来获取所有节点可以使用items()方法,它会返回一个生成器,循环得到的每个节点类型依然是PyQuery类型,所以我们可以继续方法来选择节点或属性,内容等
lis=doc('li').items()
for i in lis:
print(i('a')) #继续获取节点下的子节点
6、获取信息
attr()方法用来获取属性,如返回的结果有多个时可以调用items()方法来遍历获取
doc('.item-0.active a').attr('href') #多属性值中间不能有空格
text()方法用来获取文本内容,它只返回内部的文本信息不包括HTML文本内容,如果想返回包括HTML的文本内容可以使用html()方法,如果结果有多个,text()方法会方法所有节点的文本信息内容并将它们拼接用空格分开返回字符串内容,html()方法只会返回第一个节点的HTML文本,如果要获取所有就需要使用items()方法来遍历获取了
from pyquery import PyQuery as pq
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>
'''
doc=pq(html,parser='html')
print('text:',doc('li').text()) #获取li节点下的所有文本信息
lis=doc('li').items()
for i in lis:
print('html:',i.html()) #获取所有li节点下的HTML文本 #
text: first item second item third item fourth item fifth item
html: first item
html: <a href="link2.html">second item</a>
html: <a href="link3.html"><span class="bold">third item</span></a>
html: <a href="link4.html">fourth item</a>
html: <a href="link5.html">fifth item</a>
7、节点操作
pyquery提供了一系列方法来对节点进行动态修改,如添加一个class,移除某个节点,修改某个属性的值
addClass()增加Class,removeClass()删除Class
attr()增加属性和值,text()增加文本内容,html()增加HTML文本,remove()移除
from pyquery import PyQuery as pq
import requests
html='''
<div id="container">
<ul class="list">
<li id="1">first item</li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-2 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-3 active"><a href="link4.html">fourth item</a></li>
<li class="item-4"><a href="link5.html">fifth item</a></li>
</ul>
</div>
'''
doc=pq(html,parser='html')
print(doc('#1'))
print(doc('#1').add_class('myclass')) #增加Class
print(doc('.item-1').remove_class('item-1')) #删除Class
print(doc('#1').attr('name','link')) #添加属性name=link
print(doc('#1').text('hello world')) #添加文本
print(doc('#1').html('<span>changed item</span>')) #添加HTML文本
print(doc('.item-2.active a').remove('span')) #删除节点 #
<li id="">first item</li> <li id="" class="myclass">first item</li> <li class=""><a href="link2.html">second item</a></li> <li id="" class="myclass" name="link">first item</li> <li id="" class="myclass" name="link">hello world</li> <li id="" class="myclass" name="link"><span>changed item</span></li>
<a href="link3.html"/>
after()在节点后添加值
before()在节点之前插入值
append()将值添加到每个节点
contents()返回文本节点内容
empty()删除节点内容
remove_attr()删除属性
val()设置或获取属性值
另外还有很多节点操作方法,它们和jQuery的用法完全一致,详细请参考:http://pyquery.readthedocs.io/en/latest/api.html
8、伪类选择器
CSS选择器之所以强大,是因为它支持多种多样的伪类选择器,如:选择第一个节点,最后一个节点,奇偶数节点等。
#!/usr/bin/env python
#coding:utf-8
from pyquery import PyQuery as pq html='''
<div id="container">
<ul class="list">
<li id="1">first item</li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-2 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-3 active"><a href="link4.html">fourth item</a></li>
<li class="item-4"><a href="link5.html">fifth item</a></li>
</ul>
<div><input type="text" value="username"/></div>
</div>
'''
doc=pq(html,parser='html')
print('第一个li节点:',doc('li:first-child')) #第一个li节点
print('最后一个li节点:',doc('li:last_child')) #最后一个li节点
print('第二个li节点:',doc('li:nth-child(2)')) #第二个li节点
print('第三个之后的所有li节点:',doc('li:gt(2)')) #第三个之后的所有li节点
print('偶数的所有li节点:',doc('li:nth-child(2n)')) #偶数的所有li节点
print('包含文本内容的节点:',doc('li:contains(second)')) #包含文本内容的节点
print('索引第一个节点:',doc('li:eq(0)'))
print('奇数节点:',doc('li:even'))
print('偶数节点:',doc('li:odd')) #
第一个li节点: <li id="">first item</li> 最后一个li节点: <li class="item-4"><a href="link5.html">fifth item</a></li> 第二个li节点: <li class="item-1"><a href="link2.html">second item</a></li> 第三个之后的所有li节点: <li class="item-3 active"><a href="link4.html">fourth item</a></li>
<li class="item-4"><a href="link5.html">fifth item</a></li> 偶数的所有li节点: <li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-3 active"><a href="link4.html">fourth item</a></li> 包含文本内容的节点: <li class="item-1"><a href="link2.html">second item</a></li> 索引第一个节点: <li id="">first item</li> 奇数节点: <li id="">first item</li>
<li class="item-2 active"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-4"><a href="link5.html">fifth item</a></li> 偶数节点: <li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-3 active"><a href="link4.html">fourth item</a></li>
更多伪类参考:http://pyquery.readthedocs.io/en/latest/pseudo_classes.html
更多css选择器参考:http://www.w3school.com.cn/cssref/css_selectors.asp
9、实例应用
抓取http://www.mzitu.com网站美女图片12万张用时28分钟,总大小9G,主要受网络带宽影响,下载数据有点慢
#!/usr/bin/env python
#coding:utf-8
import requests
from requests.exceptions import RequestException
from pyquery import PyQuery as pq
from PIL import Image
from PIL import ImageFile
from io import BytesIO
import time
from multiprocessing import Pool,freeze_support
ImageFile.LOAD_TRUNCATED_IMAGES = True headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'
,'Referer':'http://www.mzitu.com'
} img_headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36'
,'Referer':'http://i.meizitu.net'
}
#保持会话请求
sesion=requests.Session() #获取首页所有URL并返回列表
def get_url(url):
list_url = []
try:
html=sesion.get(url,headers=headers).text
doc=pq(html,parser='html')
url_path=doc('#pins > li').children('a')
for i in url_path.items():
list_url.append(i.attr('href'))
except RequestException as e:
print('get_url_RequestException:',e)
except Exception as e:
print('get_url_Exception:',e)
return list_url #组合首页中每个地址的图片分页返回列表
def list_get_pages(list_url):
list_url_fen=[]
try:
for i in list_url:
doc_children = pq(sesion.get(i,headers=headers).text,parser='html')
img_number = doc_children('body > div.main > div.content > div.pagenavi > a:nth-last-child(2) > span').text()
number=int(img_number.strip())
for j in range(1,number+1):
list_url_fen.append(i+'/'+str(j))
except ValueError as e:
print('list_get_pages_ValueError:',e)
except RequestException as e:
print('list_get_pages_RequestException',e)
except Exception as e:
print('list_get_pages_Exception:',e)
return list_url_fen #获取image地址并下载图片
def get_image(url):
im_path=''
try:
html=sesion.get(url, headers=headers).text
doc=pq(html,parser='html')
im_path=doc('.main-image a img').attr('src')
image_names = ''.join(im_path.split('/')[-3:])
image_path = 'D:\images\\' + image_names
with open('img_url.txt','a') as f:
f.write(im_path + '\n')
r=requests.get(im_path,headers=img_headers)
b=BytesIO(r.content)
i=Image.open(b)
i.save(image_path)
b.close()
i.close()
#print('下载图片:{}成功!'.format(image_names))
except RequestException as e:
print('RequestException:',e)
except OSError as e:
print('OSError:',e)
except Exception as e: #必须捕获所有异常,运行中有一些链接地址不符合抓取规律,需要捕获异常使程序正常运行
print('Exception:',e)
return im_path #主调用函数
def main(item):
url1='http://www.mzitu.com/page/{}'.format(item) #分页地址
print('开始下载地址:{}'.format(url1))
获取首页链接地址
html=get_url(url1)
#获取分页链接地址
list_fenurl = list_get_pages(html)
#根据分页链接地址获取图片并下载
for i in list_fenurl:
get_image(i)
return len(list_fenurl) #统计下载数 if __name__ == '__main__':
freeze_support() #windows下进程调用时必须添加
pool=Pool() #创建进程池
start=time.time()
count=pool.map(main,[i for i in range(1,185)]) #多进程运行翻页主页
print(sum(count),count) #获取总的下载数
end=time.time()
data=time.strftime('%M:%S',time.localtime(end-start)) #获取程序运行时间
print('程序运行时间:{}分{}秒'.format(*data.split(':'))) #学习阶段,代码写得通用性很差,以后改进!
#运行结果
#注意:如果是固定IP网需要使用代理 开始下载地址:http://www.mzitu.com/page/137
OSError: image file is truncated (22 bytes not processed)
开始下载地址:http://www.mzitu.com/page/138
125571
程序运行时间:28分27秒 进程完成,退出码 0
pyquery相关链接:
GitHub:https://github.com/gawel/pyquery
PyPI:https://pypi.python.org/pypi/pyquery
官方文档:http://pyquery.readthedocs.io
python3解析库pyquery的更多相关文章
- 【转】python3解析库lxml
转自:http://www.cnblogs.com/zhangxinqi/p/9210211.html 阅读目录 1.python库lxml的安装 2.XPath常用规则 (1)读取文本解析节点 (2 ...
- python3解析库lxml
阅读目录 1.python库lxml的安装 2.XPath常用规则 (1)读取文本解析节点 (2)读取HTML文件进行解析 (3)获取所有节点 (4)获取子节点 (5)获取父节点 (6)属性匹配 (7 ...
- python3解析库BeautifulSoup4
Beautiful Soup是python的一个HTML或XML的解析库,我们可以用它来方便的从网页中提取数据,它拥有强大的API和多样的解析方式. Beautiful Soup的三个特点: Beau ...
- 小白学 Python 爬虫(23):解析库 pyquery 入门
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- Python的网页解析库-PyQuery
PyQuery库也是一个非常强大又灵活的网页解析库,如果你有前端开发经验的,都应该接触过jQuery,那么PyQuery就是你非常绝佳的选择,PyQuery 是 Python 仿照 jQuery 的严 ...
- Python3编写网络爬虫07-基本解析库pyquery的使用
三.pyquery 简介:同样是一个强大的网页解析工具 它提供了和jQuery类似的语法来解析HTML文档,支持CSS选择器,使用非常方便 安装: pip install pyquery 验证: im ...
- 爬虫之解析库pyquery
初始化 安装: pip install pyquery 字符串的形式初始化 html = """ <html lang="en"> < ...
- pyquery 的用法 --爬虫解析库
如果你对Web有所涉及,如果你比较喜欢用CSS选择器,如果你对jQuery有所了解,那么这里有一个更适合你的解析库--pyquery. 接下来,我们就来感受一下pyquery的强大之处. 1. 准备工 ...
- Python3 BeautifulSoup和Pyquery解析库随笔
BeautifuSoup和Pyquery解析库方法比较 1.对象初始化: BeautifySoup库: from bs4 import BeautifulSoup html = 'html strin ...
随机推荐
- JavaScript ES6中export及export default的区别以及import的用法
本文原创地址链接:http://blog.csdn.net/zhou_xiao_cheng/article/details/52759632,未经博主允许不得转载. 相信很多人都使用过export.e ...
- Vue---从后台获取数据vue-resource的使用方法
作为前端人员,在开发过程中,我们大多数情况都需要从后台请求数据,那么在vue中怎样从后台获取数据呢?接下来,我简单介绍一下vue-resource的使用方法,希望对大家有帮助. 一.下载vue-res ...
- 实体框架自定义代码优先约定(EF6以后)
仅限EF6仅向前 - 此页面中讨论的功能,API等在实体框架6中引入.如果您使用的是早期版本,则部分或全部信息不适用. 使用Code First时,您的模型是使用一组约定从您的类计算的.默认的Code ...
- 洛谷SP16549 QTREE6 - Query on a tree VI(LCT)
洛谷题目传送门 思路分析 题意就是要维护同色连通块大小.要用LCT维护子树大小就不说了,可以看看蒟蒻的LCT总结. 至于连通块如何维护,首先肯定可以想到一个很naive的做法:直接维护同色连通块,每次 ...
- Problem A: 道路建设 解题报告
一定存在一个最优解是一条链 否则可以接上去,不会更差 边权最小的边一定在这条链上 这个比较显然 可以把所有边都减去这个最后加上就行了 把链上的边按距离当前根的深度从小到大排列,设第一个零边位置为\(k ...
- luogu4155/bzoj4444 国旗计划 (倍增)
成环,把每个区间变成两个然后展开成链 一个人的下一个人肯定是在彼此相交的基础上,右端点越大越好 于是就把它连到相交的.右端点最大的点上,连成一棵树 于是每次只要从某个节点开始,一直在树上跳到覆盖了一个 ...
- bzoj1345 序列问题 (贪心)
考虑某个点产生的贡献: 如果i左边是一个比它小的数x,那有两种情况: 1.x的左边的数y大于i,肯定要把x合并到i,i的贡献++ 2.x的左边的数y小于i,那肯定要把x合并到y,而这时候递归地来考虑, ...
- 【poj3693】 Maximum repetition substring
http://poj.org/problem?id=3693 (题目链接) 题意 给定一个字符串,求重复次数最多的连续重复子串,若存在多组解,输出字典序最小的. Solution 后缀数组论文题,就是 ...
- Appium+python自动化环境搭建(小白适用)
写在前面: 没开始搭建前听好多人说,学习appium80%的人都死于环境搭建,所以一开始很紧张,在搭建环境中也确实遇到了好几个问题,由于之前本人使用app测试经验很少,所以相当于app小白,因此有的问 ...
- 【洛谷P1892】团伙
题目大意:维护 N 个人和 M 个关系,对每个人来说符合:我朋友的朋友也是我的朋友,我敌人的敌人也是我的朋友,求最多有多少个朋友构成的联通块. 题目大意:维护关系显然要用到并查集,这里是维护了两种关系 ...