我的儿子叫派森,用python程序化取名字,他管这叫爹?

真就是因为不开学闲的,我又开始第二个项目,这个项目是用python爬取唐诗三百首然后诗意取名,特别fash,里面涉及到很多知识点,我觉得看完这个,你至少会了python半边江山,比如网络爬虫,程序化设计,中文分词等等----


许久不见的老同学生了宝宝,取名张三??我很不解的问他原因,告诉我说孩子是三点生的,纳尼,那我的孩子是不是得叫派森啊,因为我喜欢python,之后,我就开始了这个项目,目的是为了利用古诗生成一些好听的名字,等我以后取名的时候或许还有用咧,就避免满大街的张三李四张伟王大了,汗颜无比,开始我们的项目吧。

在这里插入图片描述

来,给我们的儿子取一个名字吧!


项目预览:

gif预览:


在这里插入图片描述


页面预览:

在这里插入图片描述


项目技术:

  • 网络爬虫 : requests库 , xpath语法
  • 正则 : re库
  • 随机库 : random库
  • 中文分词 : jieba库
  • GUI界面 :tkinter库
  • 图片处理 : PIL库
  • 程序打包: pyinstaller库

项目思路:

这个项目的思路大致如下:通过爬虫获取唐诗三百首的所有文本,然后经过中文分词,筛选出想要的,然后组成名字,最后写入GUi界面中,喜欢的也可以打包程序,在哪都能用到了。


本次项目也遇到一些bug,筛选词汇的特殊符号,以及筛选过程的误区,使用GUI界面定义按钮的假死状态,这些我都克服了,在下面的讲解中我会详细说说。


项目流程:

爬取唐诗得到文本:


网页链接如下:
http://www.shicimingju.com/shicimark/tangshisanbaishou_1_0__0.html
http://www.shicimingju.com/shicimark/tangshisanbaishou_2_0__0.html
http://www.shicimingju.com/shicimark/tangshisanbaishou_3_0__0.html

那么从这个就能看到每个网页的特性了,就是1,2,3,实现一个循环就能遍历所有的页面,下面看图文源代码:

首先我们得确定这个网页是静态的还是动态的,我从源代码里面找到了网页的文本信息,所有我大致确定是静态的网页,没用很多花哨东西。

在这里插入图片描述

文本内容都在我指的哪个div标签里面,这个如果不会写xpath的,可以去xpath helper 插件,这个能帮助一下吧,我个人不是很习惯用这个,有利有弊,限制自己的思路。

代码如下:

Tang_poems = []   #   诗歌列表
def get_text(page):
    url = 'http://www.shicimingju.com/shicimark/tangshisanbaishou_' + page + '_0__0.html'  # 拼接网址
    r = requests.get(url)
    if r.status_code == 200:
        return r.text


def get_page_poems(text):
    html = etree.HTML(text)  # 形成xpath对象
    html = etree.tostring(html)  # 修改类型 成 bytes类型
    html = etree.fromstring(html)  # 修改编码
    # 诗歌
    poems = html.xpath(r'//*[@id="main_left"]/div[2]//div/div[@class="shici_list_main"]//text()')
    for i, j in enumerate(poems):  # 处理诗句 去掉空格 和 提示信息
        poems[i] = j.replace('\n                    ', '')
        poems[i] = re.sub('展开全文|收起|\n                ', '', poems[i])
        poems[i] = re.sub('《|》|\n            ', '', poems[i])
    for i in poems:
        if len(i) < 2:
            continue
        else:
            Tang_poems.append(i)

这里需要注意的,一定得先去掉明显的特殊符号,不然后面分词处理起来很麻烦,使用正则能很好的帮助我们。

取文本而后中文分词:


这里使用到jieba库中的lcut, 分词好了就放入单个列表,比如我就放了三个列表,分别对应一个字的, 二个字的,三个字的。

代码如下:

def cut_page_poems():
    name = jieba.lcut(''.join(Tang_poems))
    one_name, two_name, three_name = [], [], []  # 构建名字长度列表
    excludes = {',', '。', ' ', '?', '(', ')', ';', '!', '?', '/ ', '/', ': ', ':', '·', '· '}  # 去掉一些特殊符号 留下牛逼名字
    for i in name:
        if len(i) == 1 and i not in excludes:
            one_name.append(i)
        elif len(i) == 2 and i not in excludes:
            two_name.append(i)
        elif len(i) == 3 and i not in excludes:
            three_name.append(i)
        #  不考虑四个名字的,因为带上姓就很长了
    return one_name, two_name, three_name

这里返回的one_name里面就是存放分词后的长度,其他类推

书写GUI界面:


这里我们简单的使用了tkinter库,因为我之前也学过这个GUI库,我觉得这个有点丑,但是最简单的函数库了,其他的你们也可以尝试,如果很赞,记得评论告诉我哈,我就转库了。

代码如下:

def root():  # 生成窗口控件
    my_windows = Tk()  # 初始窗口
    my_windows.title('取唐诗三百首而后取名')  # 标题
    width = 800
    height = 600
    # 获取屏幕尺寸以计算布局参数,让窗口位于屏幕中央
    screenwidth = my_windows.winfo_screenwidth()
    screenheight = my_windows.winfo_screenheight()
    align_str = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)

    my_windows.geometry(align_str)  # 设置窗口大小

    my_windows.resizable(width=True, height=True)
    # 设置窗口是否可变长、宽,True:可变,False:不可变

    photo = PIL.Image.open('D://ps素材//鲸鱼.jpg')
    photo = photo.resize((1000, 600))  # 这里控制大小
    photo = PIL.ImageTk.PhotoImage(photo)  # 使用其他库
    # 默认的PhotoImage 只能使用git格式 其他格式使用PIL
    p_label = Label(my_windows, text='北冥有鱼\n其名为鲲',
                    fg='white', font=('华文行楷', 25),
                    justify=LEFT,  # 对其方式
                    image=photo,
                    compound=CENTER)  # 字体显示位置
    p_label.pack()
    # 定义第一个输入框
    inp1 = Entry(my_windows)
    inp1.place(relx=0.4, rely=0.2)
    # 定义第二个输入框
    inp2 = Entry(my_windows)
    inp2.place(relx=0.4, rely=0.3)
    # 定义第一个提示框
    inp_label1 = Label(my_windows, text='输入姓氏:',
                       font=('宋体', 12), fg='Tan')
    inp_label1.place(relx=0.3, rely=0.2)
    # 定义第二个提示框
    inp_label2 = Label(my_windows, text='名字长度:',
                       font=('宋体', 12), fg='Tan')
    inp_label2.place(relx=0.3, rely=0.3)

    # 定义一个显示文本

    txt = Text(my_windows, bg='#d3fbfb')
    txt.place(rely=0.6, relwidth=1.0)

    # 定义一个确定按钮 传入二个参数
    btn1 = Button(my_windows, text='确定', fg='red',
                  command=lambda: form_name(inp1.get(), inp2.get(), txt))
    btn1.place(relx=0.4, rely=0.4)
    # 定义一个关闭按钮
    btn2 = Button(my_windows, text='关闭', fg='red', command=my_windows.destroy)
    btn2.place(relx=0.5, rely=0.4)
    # 先定义提示信息
    helps = '------------They maybe can help you !---------------\n\n\n' \
            '当你输入单姓的时候 ---------->  名字长度为(2-4)\n\n\n' \
            '当你输入复姓的时候 ---------->  名字长度为(3-4)\n\n\n'
    txt.insert(END, helps)
    my_windows.mainloop()

这里使用图片的时候一定得注意库,因为tk库里面也有Image类的使用,但是这个image类只能使用gif格式的图片,所以我想上jpg就得用PIL的image类,这样就起了库名冲突,所以我这样导入PIL :

import PIL.Image
import PIL.ImageTk

这样就能避免了!这很棒!


构造GUI中的按钮函数:

在GUI里面中,我点击确定之后就弹出了随机的名字,那么这个是通过Text控件实现的。我这里是传入的函数form_name()中,然后通过lambda传入了一些特定值,

代码如下:

def form_name(first_name, num_name, txt):  # 取名
    # first_name = input('请输入后代的姓氏:')
    # num_name = int(input('请输入后代的名字数量:'))
    # 组成名字方式很多 姓名可以一个或者二个  全名最大支持五个字
    sub_num = int(num_name) - len(first_name)  # 名字长度差值
    if len(first_name) == 1:  # 如果姓氏为单姓
        if sub_num == 1:
            form_two(first_name, one, txt)  # 取二个名字
        elif sub_num == 2:
            from_three(first_name, one, two, txt)  # 取三个字名字
        elif sub_num == 3:
            form_four(first_name, one, two, three, txt)  # 取四个字名字
    elif len(first_name) == 2:  # 如果为复姓
        if sub_num == 1:
            forms_three(first_name, one, txt)  # 三个名字
        elif sub_num == 2:
            forms_four(first_name, one, two, txt)  # 四个名字


取名:

这里我使用了随机库random来实现我的功能,具体如下:

这里就展示一个组成实例了,挺多的。

def form_two(a, one, txt):  # 单姓二字

    s = []
    for i in range(300):  # 生成姓名列表
        s.append(a + random.choice(one) + ' ')
    txt.delete(1.0,  END)  # 清空文本框
    for i, j in enumerate(s):  # 输出姓名
        if i % 16 == 0 or i == 0:  # 条件限制
            txt.insert(END, '\n\n\n')  # 追加换行
        else:
            txt.insert(END, j)  # 追加名字



打包程序:

使用pyinstaller库实现:

pyinstaller -F 取名.py

项目总结:

这次项目遇到不少的挫折,但是我都挺了过来,哈哈哈,不错哟!

  • 修复了特殊符号导致的分词阻碍

  • 抓文本的思路错误,刚开始想匹配标题和文本,结果发现这很难,诗歌有很多联,我实现不了。

  • 在GUI界面中修复了导入图片的函数库名冲突问题,以及修复了按钮超时,界面崩溃问题,原因是我想加入延迟,然后一次一次的打印,达到一个效果,结果有点不允许,最后还是直接生成文本列表,然后从中选取。

  • 我想用多线程实现界面崩溃的问题,但是我尝试了很久没有实现,如果有懂的人,希望告诉我。

项目后记:

来自灵魂的问答,你有孩子吗,就想到起名的程序了。哎。。。。。觉得喜欢的朋友给个关注和赞咯!

原创文章 31 获赞 505 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_45906219/article/details/105925781