三个Python进阶有趣项目详解 | 来自缤纷多彩的灰

三个Python进阶有趣项目详解 @ WHlcj | 2022-07-14T10:32:57+08:00 | 8 分钟阅读 | 更新于 2023-09-09T14:25:58+08:00

图片转字符画,生成随机验证码,qq群词云详解。代码可直接运行,小白也可直接上手

小序

本章中三个项目实例均采用我能找到的最简单并且有效的实现方法,相比网上容易找到的教程,少去了一些不必要的模块跟正则表达式等处理办法。在保证效率的同时使代码也更加整洁清晰。每个案例采取先给实现效果,然后给出完整源码和一些注释,最后分段详解。

一些说明:

  • 本教程针对三个项目分别给出代码及其详解,前两个示例代码均可直接使用,只需修改待处理的文件路径或参数,qq群词云需要先导入qq群消息。

  • 有python基础的同学可以根据本文档分别对三个项目代码做出自己的个性化修改,从而产生更符合你需求的插件。

  • 案例中涉及的模块,建议用vpn下载,不然下载很慢。

    Let’s go!

图片转字符画

很有意思的小玩意,适合装逼搞怪~

实现效果:

原理

字符画:一种由字母、标点、汉字或其他字符组成的图画,字符画通常利用占用不同数量像素的字符代替图画上不同明暗的点。
所以运用python将图片转化为字符画,其实质先将图片转换为灰度图,然后用定义好的字符集映射不同的灰度值。不多说,先上代码!

1.完整源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from PIL import Image

# 将一个灰度值转换成对应的字符
def GraytoChar(gray):
    allChar = """@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,"^`' """
    char = allChar[int(len(allChar)*gray/256)]                       
    return char

# 将真彩色图像转换成字符画,真彩色图像文件路径为path
def toCharImage(path):
    img = Image.open(path)
    ow, oh = img.size                                                       # 原始图像的宽和高,img.size返回的是一个元组
    w = 100                                                                 # 调整后的宽度(即字符画每行有w个字符)
    h = w * oh // ow                                                        # 高度也按比例调整(即字符画总共有h行)
    h = h // 2                                                              # 在文本中,行与行之间有间隔,要进一步缩小高度才能得到较好效果
    img = img.resize((w, h))                                                # 调整图片大小
    img = img.convert('L')                                                  # 将真彩色图像转换为灰度图
    charImg = ''                                                            # 用于存储字符画
    # 将img中的灰度值逐一转换成字符,每得到一个字符,添加到charImg最后,转换完一行要添加换行符
     for y in range(h):
         s = ''
         for x in range(w):
             gray = img.getpixel((x, y))                                   # 'L'模式下,传入图像中一个像素的坐标,返回像素的灰度值0-255,0为黑255为白
             char = GraytoChar(gray)
             s = s + char                                             
         charImg = charImg + s + '\n'                             
     return charImg

s = toCharImage('test1.jpg')
# with open("f1.txt", "w") as file:
#     file.write(s)
print(s)

本例中提供的源码主要由两个函数构成,最后29行为调用函数,32行终端输出字符画。你也可以取消注释掉的30,31行,同时生成字符画在相应的文件中。

这里用到的"test1.jpg"跟"f1.txt"都是工作区下的相对路径,你可以修改成你想输入的图片文件直接运行。注意若图片不在工作区需要输入绝对路径!

2.分段解析

pillow库

1
from PIL import Image

Python平台事实上的图像处理标准库是PIL库Python Imaging Library,PIL功能非常强大,但由于PIL仅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3,又加入了许多新特性,因此,我们可以直接安装使用Pillow。注意不能同时安装Pillow和PIL库。

在cmd上直接输入以下指令安装pillow库。

1
pip install pillow

函数GraytoChar(gray)

1
2
3
4
def GraytoChar(gray):
    allChar = """@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,"^`' """
    char = allChar[int(len(allChar)*gray/256)]                       
    return char

第2行: 定义字符集用来映射不同的灰度值。本例中使用三引号为了区别字符串中的单双引号,注意不要换行否则会在灰度转换时读入隐藏的换行符。 为了兼容更多的图片,取得更好的字符画效果我推荐allChar = “@%#*+=-:. “
第3行: 得到映射后的字符。其中除以256防止allChar索引溢出(这里你也可以在合适的范围内设定除以略微更大的数,比如260或者262等等),或者len(allChar)-1。

函数GraytoChar(gray)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def toCharImage(path):
    img = Image.open(path)
    ow, oh = img.size                                                       # 原始图像的宽和高,img.size返回的是一个元组
    w = 100                                                                 # 调整后的宽度(即字符画每行有w个字符)
    h = w * oh // ow                                                        # 高度也按比例调整(即字符画总共有h行)
    h = h // 2                                                              # 在文本中,行与行之间有间隔,要进一步缩小高度才能得到较好效果
    img = img.resize((w, h))                                                # 调整图片大小
    img = img.convert('L')                                                  # 将真彩色图像转换为灰度图
    charImg = ''                                                            # 用于存储字符画
    # 将img中的灰度值逐一转换成字符,每得到一个字符,添加到charImg最后,转换完一行要添加换行符
     for y in range(h):
         s = ''
         for x in range(w):
             gray = img.getpixel((x, y))                                   # 'L'模式下,传入图像中一个像素的坐标,返回像素的灰度值0-255,0为黑255为白
             char = GraytoChar(gray)
             s = s + char                                             
         charImg = charImg + s + '\n'                             
     return charImg

关于这个函数旁白注释已经写得很清楚了,读者理解代码后可自己根据需要修改4-7行代码

生成随机验证码

开发中的小插件,上网冲浪时十分常见的东西,但也十分简单~

实现效果:

1.完整源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import random
from captcha.image import ImageCaptcha
from PIL import Image

def captcha():
    image = ImageCaptcha()
    allChar = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"          #验证码的随机字符集
    value = ""
    length = 5
    for i in range(length):                                   #范围[0,5)
        value += allChar[random.randint(0, len(allChar))]
    image.write(value, "captcha.jpg")                         #在当前文件夹(工作区)生成captcha.jpg的图片验证码(验证信息为:value)
    img = Image.open("captcha.jpg")
    img.show()                                                #展示验证码
    key = input(f"请输入验证码:\n")     
    i = (key.upper() == value)                                #统一大小并验证输入的验证码是否正确
    if i == False:
        print("验证码错误\n")
        captcha()
    else:
        print("验证通过!")
        return i

print("程序开始")
a = captcha()
print("程序结束")

2.分段解析

captcha库

1
from captcha.image import ImageCaptcha

captcha模块是专门用于生成图形验证码和语音验证码的Python三方库。本例只讲解图形验证码模块。

为了实现PIL库的部分功能。首先在cmd上直接输入以下指令安装captcha库

1
pip install captcha

函数captcha()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def captcha():
    image = ImageCaptcha()
    allChar = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"          #验证码的随机字符集
    value = ""
    length = 5
    for i in range(length):                                   #范围[0,5)
        value += allChar[random.randint(0, len(allChar))]
    image.write(value, "captcha.jpg")                         #在当前文件夹(工作区)生成captcha.jpg的图片验证码(验证信息为:value)
    img = Image.open("captcha.jpg")
    img.show()                                                #展示验证码
    key = input(f"请输入验证码:\n")     
    i = (key.upper() == value)                                #统一大小并验证输入的验证码是否正确
    if i == False:
        print("验证码错误\n")
        captcha()
    else:
        print("验证通过!")
        return i

整个函数可分为三个部分:
2~7行: 生成一个定义长度的随机字符串
8~10行: 生成基于随机字符串的验证码并展示
11~17行: 验证输入是否与验证码信息匹配

读者理解后可自行对其进行修改并将其做为插件运用于需要的地方。

qq群词云

词云本身使用场景很广,但对于初学者特别是学生来讲,qq群词云无疑是最有趣的词云运用之一,本例也由此展开。但是值得说明的一点是qq群消息本身内容很多也很难处理,因此qq群词云并不是最简单的入门词云项目。

实现效果:

(分别取自一个动漫群和一个机器人群,这里忘记设置最小字体了所以有点看不清出现频率低的词条)

完整源码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from PIL import Image
import wordcloud
import numpy as np  

def cutTxt():
    with open("1.txt", "r+", encoding="utf-8") as file:     # 打开导出的聊天消息txt文件,我这里命名的是1.txt
        flag = 0
        newtext = []
        for word in file:
            if flag == 0:
                tmp = word[0:10]
                if (tmp != "2022-07-15"):                   # 过滤掉2022.7.15之前的聊天记录
                    continue
                else:
                    flag = 1
            if flag == 1:
                if word == "\n":
                    continue
                tmp = word[0:4]
                if (tmp == "2022"):
                    continue
                tmp = word[0:2]
                if (tmp[0] == '[' or tmp[0] == '/' or tmp[0] == '@'):  # 过滤掉单独或开头发的图片和表情,例如[图片],/滑稽xxxx
                    continue
                newtext.append(word)
# 将过滤后剩下的文字重新写入文件中去
    with open('2.txt', 'w', encoding='utf-8') as file:      #创立或复写2.txt
        for i in newtext:
            file.write(i)
    return "2.txt"

def draw(file):
    file = open(file, encoding="utf-8")                     # 打开处理后的txt文件夹
    text = file.read()
    img1 = Image.open('1.jpg')                              # 打开图片
    img_array = np.array(img1)                              # 将图片装换为数组
    sw = {"表情","图片"}                                     # 屏蔽词,本例这里针对的是语句中出现的表情或者图片

    wc = wordcloud.WordCloud(
        background_color="white",
        # width=500,                                        # 默认400
        # height=500,                                       # 默认200
        max_words=100,                                      # 要显示的词的最大个数,默认200
        # max_font_size=300,                                # 设置字体最大值,默认根据高度自动调节
        # min_font_size = 100,
        mask=img_array,                                     # 背景图片,默认长方形,python自动将图片非白色部分填充,且图片越清晰,运行速度越快
        stopwords=sw,                                       # 需要屏蔽的词
        font_path="C\\Windows\\simfang.ttf")                # 设置字体格式,默认不支持中文,字体在此路径自选

    wc = wc.generate(text)                                  # 生成词云对象
    img = wc.to_image()                                     # 将词云对象转换为图片
    img.show()                                              # 展示图片
    wc.to_file("1_wc.jpg")                                  # 保存图片为1_wc.jpg
    
draw(cutTxt())                                              # 调用函数

分段解析

worldclound

1
2
3
from PIL import Image
import wordcloud
import numpy as np  

wordcloud是优秀的词云展示第三方库,其中包含matplotlib模块和numpy模块

NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库一般在python中我们会对Numpy进行缩写: import numpy as np , 因此后续中的np均指numpy。

先在cmd中安装相关模块:

1
pip install wordcloud

def cutTxt()

此函数起获取需要的聊天消息范围的作用,过滤算法是本人基于文件读取是一行一行读取的原则写的,刻意没有使用网上千篇一律的正则表达式,目的是使代码简单易懂降低门槛。这里是把想要的消息记录写入到新创建的f2.txt中。怎么导出qq聊天消息,读者可自己网上查询。

其中1.txt,2.txt以及下文的1.jpg,1_wc.jpg读者都可自定义名字

def draw(file)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
wc = wordcloud.WordCloud(
        background_color="white",
        # width=500,                                        # 默认400
        # height=500,                                       # 默认200
        max_words=100,                                      # 要显示的词的最大个数,默认200
        # max_font_size=300,                                # 设置字体最大值,默认根据高度自动调节
        # min_font_size = 100,
        mask=img_array,                                     # 背景图片,默认长方形,python自动将图片非白色部分填充,且图片越清晰,运行速度越快
        stopwords=sw,                                       # 需要屏蔽的词
        font_path="C\\Windows\\simfang.ttf")                # 设置字体格式,默认不支持中文,字体在此路径自选

此函数则是把过滤后的txt文件提取并生成词云图片。这里对wordcloud.WordCloud需要说明的是其实这个函数可自定义的参数很多,这里只列举了几个常用的参数。

其中我这里使用的mask的1.jpg是一下这个♥:

其中font_path需要要的系统自带字体选择路径如下所示:

找到你想要的字体后,右键查看名称,复制下来就行。