常用第三方模块
Python 内置模块已经挺丰富了,但真到实际开发里,很多脏活累活还是得靠第三方模块来干。好消息是 Python 生态特别繁荣,绝大多数工具都能在 PyPI 上找到,直接 pip install 就能用。这一章挑几个最常用的第三方模块来聊一聊,学会了能省不少事。
1. Pillow:图像处理
Pillow 的前身是大名鼎鼎的 PIL(Python Imaging Library),是 Python 里图像处理的事实标准库。PIL 只支持到 Python 2.7,后来社区基于它搞出了 Pillow,全面支持 Python 3,还加了不少新功能。
1.1 安装 Pillow
如果你用的是 Anaconda,Pillow 大概率已经装好了。没装的话用 pip:
pip install pillow1.2 打开、缩放和保存图片
Pillow 的基本用法非常直观,先打开一张图,拿到尺寸,然后缩放到想要的大小,最后保存。
from PIL import Image
# 打开当前目录下的图片
im = Image.open('test.jpg')
# 获取原始尺寸
w, h = im.size
print(f'原图尺寸: {w} x {h}')
# 缩放到原来的 50%
im.thumbnail((w // 2, h // 2))
print(f'缩放后尺寸: {w // 2} x {h // 2}')
# 保存为新文件
im.save('thumbnail.jpg', 'jpeg')thumbnail() 是原地修改的,调用之后 im 本身就已经是缩放后的图片了,保存的时候格式可以跟原图不一样。
1.3 应用滤镜
Pillow 内置了很多滤镜,比如模糊、锐化、边缘增强等,调用 filter() 就行。
from PIL import Image, ImageFilter
im = Image.open('test.jpg')
# 应用模糊滤镜
im_blur = im.filter(ImageFilter.BLUR)
im_blur.save('blur.jpg', 'jpeg')除了 BLUR,常用的还有 CONTOUR、DETAIL、EDGE_ENHANCE、SHARPEN 等,可以自己挨个试试效果。
1.4 绘制验证码图片
Pillow 的 ImageDraw 和 ImageFont 可以在图片上写字、画图形。下面这段代码生成一张简单的验证码图片:
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
def rnd_char():
"""随机生成一个大写字母"""
return chr(random.randint(65, 90))
def rnd_color():
"""随机背景色,范围比较亮"""
return (random.randint(64, 255),
random.randint(64, 255),
random.randint(64, 255))
def rnd_color2():
"""随机文字色,范围比较暗"""
return (random.randint(32, 127),
random.randint(32, 127),
random.randint(32, 127))
width = 240
height = 60
image = Image.new('RGB', (width, height), (255, 255, 255))
# 注意字体路径要根据系统调整,macOS 常见路径如 /Library/Fonts/Arial.ttf
font = ImageFont.truetype('Arial.ttf', 36)
draw = ImageDraw.Draw(image)
# 给每个像素随机上色,制造噪点背景
for x in range(width):
for y in range(height):
draw.point((x, y), fill=rnd_color())
# 画上 4 个随机字母
for i in range(4):
draw.text((60 * i + 10, 10), rnd_char(), font=font, fill=rnd_color2())
# 整体模糊一下
image = image.filter(ImageFilter.BLUR)
image.save('code.jpg', 'jpeg')如果运行时报 IOError: cannot open resource,说明 Pillow 找不到字体文件,把 Arial.ttf 换成绝对路径,比如 macOS 下的 /Library/Fonts/Arial.ttf 即可。
2. requests:优雅地发 HTTP 请求
Python 自带的 urllib 虽然也能访问网络资源,但写起来比较啰嗦。requests 把 HTTP 请求封装得特别顺手,是目前最流行的 HTTP 库之一。
2.1 安装 requests
pip install requests2.2 发送 GET 请求
最简单的用法,一行代码就能拿到网页内容:
import requests
r = requests.get('https://www.douban.com/')
print(r.status_code) # 200
print(r.text) # 页面 HTML 文本如果 URL 需要带查询参数,不用自己拼字符串,传一个字典给 params:
r = requests.get(
'https://www.douban.com/search',
params={'q': 'python', 'cat': '1001'}
)
print(r.url)
# https://www.douban.com/search?q=python&cat=10012.3 查看响应内容
requests 会自动猜测响应编码,通过 encoding 查看:
print(r.encoding) # utf-8响应内容有两种取法:
r.text:按猜测的编码返回字符串。r.content:返回原始bytes,适合处理图片、文件等二进制内容。
如果响应是 JSON,requests 还能直接帮你解析:
r = requests.get('https://api.example.com/data')
print(r.json())2.4 自定义请求头
很多网站会检查 User-Agent,我们可以传 headers 参数:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
r = requests.get('https://www.douban.com/', headers=headers)2.5 发送 POST 请求
POST 请求把 get 换成 post,用 data 传表单数据:
r = requests.post(
'https://accounts.douban.com/login',
data={'form_email': 'abc@example.com', 'form_password': '123456'}
)如果想传 JSON,直接写 json 参数:
payload = {'key': 'value'}
r = requests.post('https://api.example.com/upload', json=payload)上传文件也很简单,用 files 参数,注意文件要以二进制模式打开:
files = {'file': open('report.xls', 'rb')}
r = requests.post('https://api.example.com/upload', files=files)2.6 Cookie 与超时
requests 对 Cookie 的处理也很友好:
# 读取响应中的 Cookie
r = requests.get('https://www.douban.com/')
print(r.cookies['ts'])
# 发送请求时带上 Cookie
cs = {'token': '12345', 'status': 'working'}
r = requests.get('https://www.douban.com/', cookies=cs)设置超时防止请求卡住:
r = requests.get('https://www.douban.com/', timeout=2.5)3. chardet:自动检测编码
处理网络抓取或历史数据时,经常会遇到编码不明的 bytes。如果不知道编码就 decode(),很容易报 UnicodeDecodeError。chardet 就是用来猜测字节串编码的。
3.1 安装 chardet
pip install chardet3.2 检测编码
chardet.detect() 接收一个 bytes 对象,返回一个字典,包含三个字段:
encoding:推测的编码。confidence:可信度,范围 0 到 1。language:语言,比如'Chinese'、'Japanese'等。
import chardet
print(chardet.detect(b'Hello, world!'))
# {'encoding': 'ascii', 'confidence': 1.0, 'language': ''}中文的 GBK 编码:
data = '离离原上草,一岁一枯荣'.encode('gbk')
print(chardet.detect(data))
# {'encoding': 'GB2312', 'confidence': 0.74, 'language': 'Chinese'}GB2312 是 GBK 的子集,所以检测结果会显示为 GB2312,可信度不是 100%,这是正常的。
UTF-8 编码:
data = '离离原上草,一岁一枯荣'.encode('utf-8')
print(chardet.detect(data))
# {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}日文编码:
data = '最新の主要ニュース'.encode('euc-jp')
print(chardet.detect(data))
# {'encoding': 'EUC-JP', 'confidence': 0.99, 'language': 'Japanese'}拿到编码后,再用对应的编码去 decode() 就稳妥多了。
4. psutil:系统与进程监控
psutil 的名字来自 process and system utilities,用一两行代码就能获取 CPU、内存、磁盘、网络、进程等信息,而且支持跨平台,写运维脚本特别方便。
4.1 安装 psutil
pip install psutil4.2 CPU 信息
import psutil
# 逻辑 CPU 数量
print(psutil.cpu_count())
# 物理 CPU 核心数
print(psutil.cpu_count(logical=False))
# CPU 时间统计
print(psutil.cpu_times())想看实时 CPU 使用率,类似 top 命令的效果:
for _ in range(10):
# percpu=True 表示每个核心单独统计
print(psutil.cpu_percent(interval=1, percpu=True))4.3 内存信息
# 物理内存
print(psutil.virtual_memory())
# 交换分区
print(psutil.swap_memory())返回的是命名元组,里面 total、used、free、percent 等字段都很直观,percent 就是使用率百分比。
4.4 磁盘信息
# 磁盘分区
print(psutil.disk_partitions())
# 指定分区的使用情况
print(psutil.disk_usage('/'))
# 磁盘 IO 统计
print(psutil.disk_io_counters())4.5 网络信息
# 网卡 IO 统计
print(psutil.net_io_counters())
# 网卡地址信息
print(psutil.net_if_addrs())
# 网卡状态
print(psutil.net_if_stats())获取当前网络连接需要 root 权限,否则会报 AccessDenied:
print(psutil.net_connections())4.6 进程信息
# 所有进程 PID
print(psutil.pids())
# 查看指定进程
p = psutil.Process(1234)
print(p.name()) # 进程名
print(p.exe()) # 可执行文件路径
print(p.cwd()) # 工作目录
print(p.cmdline()) # 启动命令
print(p.status()) # 运行状态
print(p.memory_info())# 内存使用
print(p.num_threads())# 线程数psutil 还自带一个 test() 函数,可以模拟 ps 命令的效果:
psutil.test()相关信息
本章介绍的几个第三方模块都是日常开发里的高频选手:
- Pillow:图像打开、缩放、滤镜、保存、绘图一应俱全,是 Python 图像处理的首选。
- requests:HTTP 请求的优雅解决方案,GET/POST、参数、Cookie、文件上传都能轻松搞定。
- chardet:专门用来猜测字节串编码,处理乱码问题时非常省心。
- psutil:系统监控和进程管理的利器,跨平台、接口统一,写运维脚本必备。
除了这些,Python 还有海量的第三方库,遇到具体需求先去 PyPI 搜一搜,大概率有人已经造好轮子了。