目录
1. 前言
2. Pillow
3. requests
4. chardet
5. psutil
1. 前言
除了内建的模块外,Python还有大量的第三方模块。
基本上,所有的第三方模块都会在PyPI - the Python Package Index上注册,只要找到对应的模块名字,即可用pip安装。
此外,在安装第三方模块一节中,我们强烈推荐安装Anaconda,安装后,数十个常用的第三方模块就已经就绪,不用pip手动安装。
本篇博客介绍常用的第三方模块。
2. Pillow
PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。
由于PIL仅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3.x,又加入了许多新特性,因此,我们可以直接安装使用Pillow。
- 安装Pillow
如果安装了Anaconda,Pillow就已经可用了。否则,需要在命令行下通过pip安装:
pip install pillow
如果遇到Permission denied安装失败,请加上sudo重试。
- 操作图像
来看看最常见的图像缩放操作,只需三四行代码:
from PIL import Image
im = Image.open('/Users/apple/Desktop/timg.jpg')
w,h = im.size
print('Original image size: %sx%s' % (w, h))
# 缩放到50%:
im.thumbnail((w//2,h//2))
print('Resize image to: %sx%s' % (w//2, h//2))
# 把缩放后的图像用jpeg格式保存:
im.save('thumbnail.jpg','jpeg')
其他功能如切片、旋转、滤镜、输出文字、调色板等一应俱全。
比如,模糊效果也只需几行代码:
from PIL import Image, ImageFilter
# 打开一个jpg图像文件
im = Image.open('/Users/apple/Desktop/timg.jpg')
# 应用模糊滤镜:
im2 = im.filter(ImageFilter.BLUR)
im2.save('blur.jpg', 'jpeg')
PIL的ImageDraw提供了一系列绘图方法,让我们可以直接绘图。比如要生成字母验证码图片:
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
# 随机字母:
def rndChar():
return chr(random.randint(65, 90))
# 随机颜色1:
def rndColor():
return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))
# 随机颜色2:
def rndColor2():
return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))
# 240 x 60:
width = 60 * 4
height = 60
image = Image.new('RGB', (width, height), (255, 255, 255))
# 创建Font对象:
font = ImageFont.truetype('Arial.ttf', 36) #设置字体类型和位置
# 创建Draw对象:
draw = ImageDraw.Draw(image)
# 填充每个像素:
for x in range(width):
for y in range(height):
draw.point((x, y), fill=rndColor())
# 输出文字:
for t in range(4):
draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())
# 模糊:
image = image.filter(ImageFilter.BLUR)
image.save('code.jpg', 'jpeg')
我们用随机颜色填充背景,再画上文字,最后对图像进行模糊,得到验证码图片如下:
如果运行的时候报错:
IOError: cannot open resource
这是因为PIL无法定位到字体文件的位置,可以根据操作系统提供绝对路径,比如:
'/Library/Fonts/Arial.ttf'
要详细了解PIL的强大功能,请请参考Pillow官方文档:
https://pillow.readthedocs.org/
- 小结
PIL提供了操作图像的强大功能,可以通过简单的代码完成复杂的图像处理。
3. requests
我们已经讲解了Python内置的urllib模块,用于访问网络资源。但是,它用起来比较麻烦,而且,缺少很多实用的高级功能。
更好的方案是使用requests。它是一个Python第三方库,处理URL资源特别方便。
- 安装requests
如果安装了Anaconda,requests就已经可用了。否则,需要在命令行下通过pip安装:
pip install requests
- 使用requests
要通过GET访问一个页面,只需要几行代码:
import requests
response = requests.get('https://www.douban.com')
print(response.statu s_code)
print(response.text)
对于带参数的URL,传入一个dict作为params参数:
response = requests.get('https://www.douban.com/search',params={'q':'python','cat':'1001'})
response.url
requests自动检测编码,可以使用encoding属性查看:
response.encoding
无论响应是文本还是二进制内容,我们都可以用content属性获得bytes对象:
response.content
requests的方便之处还在于,对于特定类型的响应,例如JSON,可以直接获取:
r = requests.get('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20%3D%202151330&format=json')
r.json()
需要传入HTTP Header时,我们传入一个dict作为headers参数:
import requests
headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}
response = requests.get('https://www.douban.com',headers=headers)
response.text
要发送POST请求,只需要把get()方法变成post(),然后传入data参数作为POST请求的数据:
r = requests.post('https://accounts.douban.com/login', data={'form_email': 'abc@example.com', 'form_password': '123456'})
requests默认使用application/x-www-form-urlencoded对POST数据编码。如果要传递JSON数据,可以直接传入json参数:
params = {'key': 'value'}
r = requests.post(url, json=params) # 内部自动序列化为JSON
类似的,上传文件需要更复杂的编码格式,但是requests把它简化成files参数:
upload_files = {'file': open('report.xls', 'rb')}
r = requests.post(url,files=upload_files)
在读取文件时,注意务必使用'rb'即二进制模式读取,这样获取的bytes长度才是文件的长度。
把post()方法替换为put(),delete()等,就可以以PUT或DELETE方式请求资源。
除了能轻松获取响应内容外,requests对获取HTTP响应的其他信息也非常简单。例如,获取响应头:
response = requests.get('https://www.baidu.com')
print(response.headers)
print(response.headers['Content-Type'])
requests对Cookie做了特殊处理,使得我们不必解析Cookie就可以轻松获取指定的Cookie:
print(response.cookies)
要在请求中传入Cookie,只需准备一个dict传入cookies参数:
cs = {'token': '12345', 'status': 'working'}
response = requests.get(url,cookies=cs)
最后,要指定超时,传入以秒为单位的timeout参数:
response = requests.get(url,timeout=2.5) #2.5s后未响应 则超时
- 小结
用requests获取URL资源,就是这么简单!
4. chardet
字符串编码一直是令人非常头疼的问题,尤其是我们在处理一些不规范的第三方网页的时候。虽然Python提供了Unicode表示的str和bytes两种数据类型,并且可以通过encode()和decode()方法转换,但是,在不知道编码的情况下,对bytes做decode()不好做。
对于未知编码的bytes,要把它转换成str,需要先“猜测”编码。猜测的方式是先收集各种编码的特征字符,根据特征字符判断,就能有很大概率“猜对”。
当然,我们肯定不能从头自己写这个检测编码的功能,这样做费时费力。chardet这个第三方库正好就派上了用场。用它来检测编码,简单易用。
- 安装chardet
如果安装了Anaconda,chardet就已经可用了。否则,需要在命令行下通过pip安装:
pip install chardet
- 使用chardet
当我们拿到一个bytes时,就可以对其检测编码。用chardet检测编码,只需要一行代码:
import chardet
chardet.detect(b'Hello World!')
检测出的编码是ascii,注意到还有个confidence字段,表示检测的概率是1.0(即100%)。
我们来试试检测GBK编码的中文:
data = '离离原上草,一岁一枯荣'.encode('gbk')
chardet.detect(data)
检测的编码是GB2312,注意到GBK是GB2312的超集,两者是同一种编码,检测正确的概率是74%,language字段指出的语言是'Chinese'。
对UTF-8编码进行检测:
data = '离离原上草,一岁一枯荣'.encode('utf-8')
chardet.detect(data)
我们再试试对日文进行检测:
data = '最新の主要ニュース'.encode('euc-jp')
chardet.detect(data)
可见,用chardet检测编码,使用简单。获取到编码后,再转换为str,就可以方便后续处理。
chardet支持检测的编码列表请参考官方文档Supported encodings。
- 小结
使用chardet检测编码非常容易,chardet支持检测中文、日文、韩文等多种语言。
5. psutil
用Python来编写脚本简化日常的运维工作是Python的一个重要用途。在Linux下,有许多系统命令可以让我们时刻监控系统运行的状态,如ps,top,free等等。要获取这些系统信息,Python可以通过subprocess模块调用并获取结果。但这样做显得很麻烦,尤其是要写很多解析代码。
在Python中获取系统信息的另一个好办法是使用psutil这个第三方模块。顾名思义,psutil = process and system utilities,它不仅可以通过一两行代码实现系统监控,还可以跨平台使用,支持Linux/UNIX/OSX/Windows等,是系统管理员和运维小伙伴不可或缺的必备模块。
- 安装psutil
如果安装了Anaconda,psutil就已经可用了。否则,需要在命令行下通过pip安装:
pip install psutil
- 获取CPU信息
import psutil
print(psutil.cpu_count()) #cpu逻辑数量
print(psutil.cpu_count(logical=False)) #cpu物理核心
# 4说明是4核超线程, 8则是8核非超线程
统计CPU的用户/系统/空闲时间:
psutil.cpu_times()
再实现类似top命令的CPU使用率,每秒刷新一次,累计10次:
for x in range(10):
print(psutil.cpu_percent(interval=1,percpu=True))
- 获取内存信息
使用psutil获取物理内存和交换内存信息,分别使用:
print(psutil.virtual_memory())
print(psutil.swap_memory())
返回的是字节为单位的整数,可以看到,总内存大小是17179869184 = 16 GB,已用7501750272 = 6.7 GB,使用了50.3%。
而交换区大小是2147483648 = 2 GB。
- 获取磁盘信息
可以通过psutil获取磁盘分区、磁盘使用率和磁盘IO信息:
print(psutil.disk_partitions()) #磁盘分区信息
print(psutil.disk_usage('/')) #磁盘使用信息
print(psutil.disk_io_counters())#磁盘IO
可以看到,磁盘'/'的总容量是250790436864 = 256 GB,使用了31.5%。文件格式是apfs,opts中包含rw表示可读写,journaled表示支持日志。
- 获取网络信息
psutil可以获取网络接口和网络连接信息:
print(psutil.net_io_counters()) # 获取网络读写字节/包的个数
print(psutil.net_if_addrs()) #获取网络接口信息
print(psutil.net_if_stats()) # 获取网络接口状态
要获取当前网络连接信息,使用net_connections():
psutil.net_connections()
你可能会得到一个AccessDenied错误,原因是psutil获取信息也是要走系统接口,而获取网络连接信息需要root权限,这种情况下,可以退出Python交互环境,用sudo重新启动:
- 获取进程信息
通过psutil可以获取到所有进程的详细信息:
print(psutil.pids()) # 所有进程ID
p = psutil.Process(3776) # 获取指定进程ID=3776,其实就是当前Python交互环境
print(p.name())# 进程名称
print(p.exe()) #进程exe路径
print(p.cwd()) #进程工作目录
print(p.cmdline()) # 进程启动的命令行
print(p.ppid()) # 父进程ID
print(p.parent()) # 父进程
print(p.children()) # 子进程列表
print(p.status())# 进程状态
print(p.username())# 进程用户名
print(p.create_time()) # 进程创建时间
print(p.terminal())# 进程终端
print(p.cpu_times()) # 进程使用的CPU时间
print(p.memory_info()) # 进程使用的内存
print(p.open_files()) # 进程打开的文件
print(p.connections()) # 进程相关网络连接
print(p.num_threads()) # 进程的线程数量
print(p.threads())# 所有线程信息
print(p.environ()) # 进程环境变量
print(p.terminate()) # 结束进程
和获取网络连接类似,获取一个root用户的进程需要root权限,启动Python交互环境或者.py文件时,需要sudo权限.
psutil还提供了一个test()函数,可以模拟出ps命令的效果:
- 小结
psutil使得Python程序获取系统信息变得易如反掌。
psutil还可以获取用户信息、Windows服务等很多有用的系统信息,具体请参考psutil的官网:https://github.com/giampaolo/psutil