基于Python开发的AI智能联系人管理程序(源码+可执行程序+程序配置说明书+程序使用说明书)

一、项目简介

本项目是一套基于Python开发的AI智能联系人管理程序,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Python学习者。
包含:项目源码、项目文档等,该项目附带全部源码可作为毕设使用。
项目都经过严格调试,确保可以运行!

二、开发环境要求

本系统的软件开发及运行环境具体如下。
操作系统:Windows 7、Windows 10。
Python版本:Python 3.7。
开发工具:PyCharm 2018。
Python内置模块:sys、os、base64、json、collections。
第三方模块:PyQt5、requests、pandas、Pillow(PIL)、phone、pyecharts、openpyxl、xlrd、pyecharts_snapshot。
说明:由于PIL仅支持到Python 2.7,我们的项目为Python3.x,所以这里导入模块Pillow代替PIL,Pillow为PIL的兼任版本。项目中对图片操作导入模块使用form PIL import Image。

三、系统功能

首页
添加联系人窗口
名片信息展示
选择名片
搜索联系人
编辑联系人
删除联系人
查看联系人分布饼图等功能

四、页面功能

在PyCharm中运行《AI智能联系人管理》即可进入如图1所示的系统主界面。
在这里插入图片描述
具体的操作步骤如下:
(1)添加联系人。在主界面中,单击“添加”按钮,将打开添加联系人窗口,在该窗口中,单击“选择名片”按钮,选择一张名片对应的图片,系统将自动识别该名片中的信息,并且显示到右侧的文本框中,效果如图2所示。如果没有名片也可手动输入联系人信息。

在这里插入图片描述
(2)搜索联系人。在主界面顶部的文本框中,输入要搜索的内容,单击“搜索”按钮,将从已经保存的联系人信息中查找相应的内容,如果找到对应的内容,将显示在下方,如图3所示,否则给出显示“没有搜索内容”的提示对话框,如图4所示。
在这里插入图片描述
说明:在查找联系人时,也可以单击索引字母按钮,按拼音索引来查找。
在这里插入图片描述
(3)编辑或删除联系人。在显示联系人时,每个联系人的右侧都有两个按钮(如图5所示),一个是“编辑”,另一个是“删除”,单击不同的按钮将实现相应的功能。
在这里插入图片描述
(4)查看联系人的分布。在主界面中,单击“查看联系人分布”按钮,将打开“联系人分布”窗口,在该窗口中将以饼图显示联系人的分布,如图6所示。
在这里插入图片描述

五、部分源码展示

# qt5模块
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtCore import *
#  自定义模块
import mainpage
import addpage
import gridlayout
import editpage
import pinyintool
# 内置模块
import sys
import requests, base64, json
import collections
import os
import re
# 第三方模块
import pandas as pd
from pandas import DataFrame
from PIL import Image
import phone
from pyecharts import Pie# 获取文件的路径
cdir = os.getcwd()
# 文件路径
path=cdir+'/res/datafile/'
# 读取路径 判断是否创建了文件
if not os.path.exists(path):# 根据路径建立文件夹os.makedirs(path)# 姓名 公司 电话 手机 邮件 地址 城市 分类 name  comp tel mobile email addr city typecardfile = pd.DataFrame(columns=['name', 'comp', 'tel', 'mobile', 'email', 'addr', 'city', 'type'])# 生成xlsx文件cardfile.to_excel(path+'名片信息表.xlsx', sheet_name='data', index=None)# 编辑页面
class editWindow(QWidget,editpage.Ui_Form):# 初始化方法def __init__(self):# 找到父类 首页面super(editWindow, self).__init__()# 初始化页面方法self.setupUi(self)# 为保存按钮添加事件self.pushButton_2.clicked.connect(self.editkeep)# 显示添加名片页面def OPEN(self):# 显示页面self.show()# 保存编辑内容def editkeep(self):# 获取按钮名称indexName =  self.pushButton_2.objectName()# 获取表pi_table = pd.read_excel(path + '名片信息表.xlsx', sheet_name='data')# 获取控件信息 # 'name', 'comp', 'tel', 'mobile', 'email', 'addr', 'city', 'type'name = self.lineEdit.text()comp = self.lineEdit_2.text()tel = self.lineEdit_3.text()mobile = self.lineEdit_4.text()email = self.lineEdit_5.text()addr = self.lineEdit_6.text()# 判断手机号是否为空if mobile.strip():# 根据手机号判断区域try:info = phone.Phone().find(int(mobile))except Exception as e:print("根据手机号判断区域时出错", e)QMessageBox.critical(self, "错误:", "手机号码不正确!", QMessageBox.Ok)  # 弹出提示对话框self.lineEdit_4.setFocus()  # 让手机文本框获得焦点return# 判断手机号是否正确返回信息if info == None:city = '其他'else:# 正确返回信息获取省city = info['province']else:city = '其他'# 判断姓名是否为空if name.strip():# 获取首字母拼音type = pinyintool.getPinyin(name[0])# 根据行号删除数据datas = pi_table.drop(index=[int(indexName)], axis=0)data = datas.append({'name': name,'comp': comp,'tel': tel,'mobile': mobile,'email': email,'addr': addr,'city': city,'type': type}, ignore_index=True)# 更新xlsx文件DataFrame(data).to_excel(path + '名片信息表.xlsx',sheet_name='data', index=False)self.close()window.dataall()else:QMessageBox.information(self, '提示信息', '姓名不能为空')pass#首页列表样式
class griditem(QWidget,gridlayout.Ui_Form):# 初始化方法def __init__(self):# 找到父类 首页面super(griditem, self).__init__()# 初始化页面方法self.setupUi(self)# 显示饼图类
class HtmlWindows(QMainWindow):def __init__(self):super(QMainWindow,self).__init__()self.setGeometry(200, 200, 850, 500)self.browser = QWebEngineView()def set(self,title,hurl):self.setWindowTitle(title)d = os.path.dirname(os.path.realpath(sys.argv[0]))  # 获取当前文件所在路径d=re.sub(r'\\','/',d)  # 将路径中的分隔符\替换为/url=d+'/res/datafile/'+hurlself.browser.load(QUrl(url))self.setCentralWidget(self.browser)
# 首页页面
class parentWindow(QWidget,mainpage.Ui_Form):# 初始化方法def __init__(self):# 找到父类 首页面super(parentWindow, self).__init__()# 初始化页面方法self.setupUi(self)# 标签按钮绑定事件self.pushButton_3.clicked.connect(self.dataall)self.pushButton_4.clicked.connect(lambda:self.dataother('A'))self.pushButton_6.clicked.connect(lambda:self.dataother('B'))self.pushButton_5.clicked.connect(lambda:self.dataother('C'))self.pushButton_7.clicked.connect(lambda:self.dataother('D'))self.pushButton_8.clicked.connect(lambda:self.dataother('E'))self.pushButton_9.clicked.connect(lambda:self.dataother('F'))self.pushButton_10.clicked.connect(lambda:self.dataother('G'))self.pushButton_11.clicked.connect(lambda:self.dataother('H'))self.pushButton_12.clicked.connect(lambda:self.dataother('I'))self.pushButton_13.clicked.connect(lambda:self.dataother('J'))self.pushButton_14.clicked.connect(lambda:self.dataother('K'))self.pushButton_15.clicked.connect(lambda:self.dataother('L'))self.pushButton_16.clicked.connect(lambda:self.dataother('M'))self.pushButton_17.clicked.connect(lambda:self.dataother('N'))self.pushButton_18.clicked.connect(lambda:self.dataother('O'))self.pushButton_19.clicked.connect(lambda:self.dataother('P'))self.pushButton_20.clicked.connect(lambda:self.dataother('Q'))self.pushButton_21.clicked.connect(lambda:self.dataother('R'))self.pushButton_22.clicked.connect(lambda:self.dataother('S'))self.pushButton_23.clicked.connect(lambda:self.dataother('T'))self.pushButton_24.clicked.connect(lambda:self.dataother('U'))self.pushButton_25.clicked.connect(lambda:self.dataother('V'))self.pushButton_26.clicked.connect(lambda:self.dataother('W'))self.pushButton_27.clicked.connect(lambda:self.dataother('X'))self.pushButton_28.clicked.connect(lambda:self.dataother('Y'))self.pushButton_29.clicked.connect(lambda:self.dataother('Z'))# 搜索按钮绑定事件self.pushButton.clicked.connect(self.seachbtn)self.pushButton_30.clicked.connect(self.lookpie)# 显示全部数据self.dataall()# 显示饼图def lookpie(self):# 获取表数据# 读取文件内容pi_table = pd.read_excel(path + '名片信息表.xlsx', sheet_name='data')# 获取城市信息citattr = pi_table['city'].values# 判断是否有城市信息if len(citattr)==0:# 没有信息提示QMessageBox.information(self, '提示信息', '没有联系人')returnattr = []v1 = []# 循环表里city项for i in citattr:# 判断city项是否包含在attr里if not i in attr:# 不包含在attr表里时候添加到attr里attr.append(i)# Counter(计数器)是对字典的补充,用于追踪值的出现次数。d = collections.Counter(citattr)# 循环城市列表for k in attr:# d[k] 是k在列表d中出现的次数v1.append(d[k])# 生成饼图pie = Pie("联系人分布")pie.add("", attr, v1, is_label_show=True)pie.show_config()pie.render(path+'联系人分布饼图.html')# 显示饼图htmlwidows.set('联系人分布','联系人分布饼图.html')htmlwidows.show()pass#搜索功能def seachbtn(self):# 读取文件内容pi_table = pd.read_excel(path + '名片信息表.xlsx', sheet_name='data')seachk=self.lineEdit.text()# 查询数据 用户名和公司如果有一个包含搜索内容筛选出来cardArray = pi_table[(pi_table['name'].str.contains(seachk)) | (pi_table['comp'].str.contains(seachk))].valuestb = pi_table[(pi_table['name'].str.contains(seachk)) | (pi_table['comp'].str.contains(seachk))]if len(cardArray) == 0:QMessageBox.information(self, '提示信息', '没有搜索内容')else:# 每次点循环删除管理器的组件while self.gridLayout.count():# 获取第一个组件item = self.gridLayout.takeAt(0)widget = item.widget()# 删除组件widget.deleteLater()i = -1for n in range(len(cardArray)):# x 确定每行显示的个数 0,1,2 每行3个x = n % 3# 当x为0的时候设置换行 行数+1if x == 0:i += 1item = griditem()item.label_8.setText('姓名:' + str(cardArray[n][0]))item.label_9.setText('公司:' + str(cardArray[n][1]))item.label_10.setText('电话:' + str(cardArray[n][2]))item.label_11.setText('手机:' + str(cardArray[n][3]))item.label_12.setText('邮箱:' + str(cardArray[n][4]))item.label_13.setText('地址:' + str(cardArray[n][5]))# 设置名称 为获取项目行数item.pushButton.setObjectName(str(tb.index.tolist()[n]))item.pushButton_3.setObjectName(str(tb.index.tolist()[n]))# 为按钮绑定点击事件item.pushButton.clicked.connect(self.edit)item.pushButton_3.clicked.connect(self.deletedata)# 动态给gridlayout添加布局self.gridLayout.addWidget(item, i, x)# 设置上下滑动控件可以滑动 把scrollAreaWidgetContents_2添加到scrollArea中self.scrollAreaWidgetContents.setMinimumHeight(i * 200)# girdlayout 添加到滑动控件中self.scrollAreaWidgetContents.setLayout(self.gridLayout)#显示全部数据def dataall(self):# 每次点循环删除管理器的组件while self.gridLayout.count():# 获取第一个组件item = self.gridLayout.takeAt(0)widget = item.widget()# 删除组件widget.deleteLater()i=-1# 读取文件内容pi_table = pd.read_excel(path + '名片信息表.xlsx', sheet_name='data')# 获取所有数据cardArray = pi_table.values# 循环数据for n in range(len(cardArray)):# x 确定每行显示的个数 0,1,2 每行3个x = n % 3# 当x为0的时候设置换行,即行数+1if x == 0:i += 1item = griditem()item.label_8.setText('姓名:'+str(cardArray[n][0]))item.label_9.setText('公司:'+str(cardArray[n][1]))item.label_10.setText('电话:'+str(cardArray[n][2]))item.label_11.setText('手机:'+str(cardArray[n][3]))item.label_12.setText('邮箱:'+str(cardArray[n][4]))item.label_13.setText('地址:'+str(cardArray[n][5]))# 设置名称 为获取项目行数item.pushButton.setObjectName(str(pi_table.index.tolist()[n]))item.pushButton_3.setObjectName(str(pi_table.index.tolist()[n]))# 为按钮绑定点击事件item.pushButton.clicked.connect(self.edit)item.pushButton_3.clicked.connect(self.deletedata)# 动态添加控件到gridlayout中self.gridLayout.addWidget(item,i, x)# 设置上下滑动控件可以滑动 把scrollAreaWidgetContents_2添加到scrollArea中self.scrollAreaWidgetContents.setMinimumHeight(i*200)# 设置gridlayout到滑动控件中self.scrollAreaWidgetContents.setLayout(self.gridLayout)pass# 删除数据方法def deletedata(self):# 获取信号源 点击的按钮sender = self.gridLayout.sender()# 获取按钮名称indexName = sender.objectName()# 获取表信息pi_table = pd.read_excel(path + '名片信息表.xlsx', sheet_name='data')# 根据行号删除数据data=pi_table.drop(index=[int(indexName)], axis=0)# 更新xlsx文件DataFrame(data).to_excel(path + '名片信息表.xlsx',sheet_name='data', index=False)# 显示全部数据self.dataall()# 编辑数据def edit(self):# 获取信号源 点击的按钮sender = self.gridLayout.sender()# 获取按钮名称indexName=sender.objectName()pi_table = pd.read_excel(path + '名片信息表.xlsx', sheet_name='data')# 根据行号 获取数据cardArray =pi_table.iloc[[indexName]].values# 打开编辑页面editWindow.OPEN()# 设置数据editWindow.lineEdit.setText(str(cardArray[0][0]))editWindow.lineEdit_2.setText(str(cardArray[0][1]))editWindow.lineEdit_3.setText(str(cardArray[0][2]))editWindow.lineEdit_4.setText(str(cardArray[0][3]))editWindow.lineEdit_5.setText(str(cardArray[0][4]))editWindow.lineEdit_6.setText(str(cardArray[0][5]))# 设置按钮名称editWindow.pushButton_2.setObjectName(str(indexName))pass# 显示部分数据def dataother(self,typeAZ):# 每次点循环删除管理器的组件while self.gridLayout.count():# 获取第一个组件item = self.gridLayout.takeAt(0)# 获取布局widget = item.widget()# 删除组件widget.deleteLater()pass# 读取文件内容pi_table = pd.read_excel(path + '名片信息表.xlsx', sheet_name='data')i = -1# 筛选内容cardArray = pi_table[pi_table['type'] == typeAZ].valuestb= pi_table[pi_table['type'] == typeAZ]for n in range(len(cardArray)):# x 确定每行显示的个数 0,1,2 每行3个x = n % 3# 当x为0的时候设置换行 行数+1if x == 0:i += 1item = griditem()item.label_8.setText('姓名:' + str(cardArray[n][0]))item.label_9.setText('公司:' + str(cardArray[n][1]))item.label_10.setText('电话:' + str(cardArray[n][2]))item.label_11.setText('手机:' + str(cardArray[n][3]))item.label_12.setText('邮箱:' + str(cardArray[n][4]))item.label_13.setText('地址:' + str(cardArray[n][5]))# 设置名称 为获取项目行数item.pushButton.setObjectName(str(tb.index.tolist()[n]))item.pushButton_3.setObjectName(str(tb.index.tolist()[n]))# 为按钮绑定点击事件item.pushButton.clicked.connect(self.edit)item.pushButton_3.clicked.connect(self.deletedata)# 动态设置控件self.gridLayout.addWidget(item, i, x)# 动态设置滑动控件滑动高度self.scrollAreaWidgetContents.setMinimumHeight(i * 200)# giridLayout 添加到滑动控件中self.scrollAreaWidgetContents.setLayout(self.gridLayout)#添加名片页面
class childWindow(QWidget,addpage.Ui_Form):# 初始化方法def __init__(self):# 找到父类 添加名片页面super(childWindow, self).__init__()# 初始化页面方法self.setupUi(self)# 给选择名片按钮添加事件self.pushButton.clicked.connect(self.openfile)# 给保存按钮添加事件self.pushButton_2.clicked.connect(self.keep)#保存名片信息到文档def keep(self):pi_table = pd.read_excel(path + '名片信息表.xlsx', sheet_name='data')# 获取输出框内容name =self.lineEdit.text()comp = self.lineEdit_2.text()tel= self.lineEdit_3.text()mobile= self.lineEdit_4.text()email= self.lineEdit_5.text()addr= self.lineEdit_6.text()# 判断手机号是否为空if mobile.strip():# 根据手机号判断区域try:info = phone.Phone().find(int(mobile))except Exception as e:print("根据手机号判断区域时出错",e)QMessageBox.critical(self,"错误:","手机号码不正确!",QMessageBox.Ok) # 弹出提示对话框self.lineEdit_4.setFocus()  # 让手机文本框获得焦点return# 判断手机号是否正确返回信息if info==None:city = '其他'else:# 正确返回信息获取省city = info['province']else:city = '其他'# 判断姓名是否为空if name.strip():# 获取首字母拼音type=pinyintool.getPinyin(name[0])# 添加数据data = pi_table.append({'name': name,'comp': comp,'tel': tel,'mobile': mobile,'email': email,'addr': addr,'city': city,'type': type,}, ignore_index=True)# 更新xlsx文件DataFrame(data).to_excel(path + '名片信息表.xlsx',sheet_name='data', index=False)# 首页面显示全部数据window.dataall()# 关闭添加页面self.close()else:QMessageBox.information(self, '提示信息', '姓名不能为空')pass# 显示添加名片页面def OPEN(self):# 移除控件上图片self.label_2.setPixmap(QPixmap(""))# 移除输入框内容self.lineEdit.setText("")self.lineEdit_2.setText("")self.lineEdit_3.setText("")self.lineEdit_4.setText("")self.lineEdit_5.setText("")self.lineEdit_6.setText("")# 显示页面self.show()#选择名片按钮执行方法def openfile(self):# 启动选择文件对话空,查找jpg以及png图片self.download_path = QFileDialog.getOpenFileName(self, "选择要识别的图片", "/", "Image Files(*.jpg *.png)")# 判断是否选择图片if not self.download_path[0].strip():# 没有选择图片执行# 消息对话框 information 提问对话框 question 警告对话框 warning# 严重错误对话框 critical 关于对话框 aboutQMessageBox.information(self, '提示信息', '没有选择名片图片')pass........................

六、源码地址

https://download.csdn.net/download/weixin_43860634/88335299

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/108354.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎样吃透一个java项目?

前言 对于刚开始看视频敲代码,最忌讳的便是一上来就完全照着视频做,这么做就算完完全全的跟着视频做出来一个项目,始终都无法将里面具体的知识化为己有,单纯来说只是简单的复刻,视频的作者本身是不会对他在做该项目过…

【文件上传-配置文件】crossdomain.xml跨域策略配置文件上传

目录 一、0x00 前言 二、基础知识 1、Flash 2、crossdomain.xml文件 3、crossdomain.xml格式 4、crossdomain.xml相关参数 三、漏洞利用 1、方法: 2、上传漏洞配置文件 一、0x00 前言 在很多地方都会见查是否跨域 比如某些特定的步骤、CSRF、flash跨域劫…

快速傅里叶变换

引言 目标 傅里叶变化(Fourier transform)是一种信号处理技术,它可以将时间信号转换为频率信号,即将一组具有相同数量频率的正弦波叠加在一起,形成一组新的正弦波。如果我们把时间信号从频域转换到时域,那么…

【计算机网络】 TCP流量控制——滑动窗口和累积应答

文章目录 累积应答TCP流量控制——滑动窗口 累积应答 我们前面所说的是我们每发送一个包对端就要回一个ack,那么这样效率太慢了,我们这里就有一个累积应答的机制,就是说我们客户端累积发送多个包,然后服务端再统一进行回复。 TCP…

将一列数S(元组、列表等)指定起止范围取出S中的一部分数itertools.islice()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将一列数S(元组、列表等) 指定起止范围 取出S中的一部分数 itertools.islice() 选择题 以下程序的运行结果是? import itertools S (0,1,2,3,4,5,6) print("【显…

(2023|CVPR,GigaGAN 注意力 自适应核)扩展 GAN 以进行文本到图像的合成

Scaling up GANs for Text-to-Image Synthesis 公众号:EDPJ(添加 VX:CV_EDPJ 进交流群获取资料) 目录 0. 摘要 1. 简介 2. 相关工作 3. 方法 3.1. 建模复杂的上下文交互 3.2. 生成器设计 3.3. 鉴别器设计 3.4. 基于…

安卓内部存储不需要申请权限,外部文件需要申请权限

内部存储和外部存储的访问权限区别&#xff1a; 内部路径&#xff1a;/data/user/0/com.xxx.xxx/ getExternalFilesDir可以获取到属于 App 自身的文件路径&#xff0c;通常是~/Android/data/<package-name>/**/。在该目录中读写文件均不需要申请权限,随着APP卸载就会删…

85 # koa 使用 koa-router 以及 koa-views 实现路由视图逻辑分离

mvc model 数据view 视图controller 控制器 下面实现一个路由视图逻辑分离例子&#xff0c;先安装依赖 npm init -y npm i koa koa-static koa-bodyparser koa-router koa-combine-routers ejs koa-views6.2.3没有分离的时候&#xff0c;路由视图逻辑都是混在一起的 const …

【Linux常用命令】

一、防火墙相关 1、查看防火墙状态 systemctl status flrewalld2、如果防火墙是开启状态的&#xff0c;需要关闭 systemctl stop firewalld3、永久行关闭操作&#xff08;禁止开机自启动&#xff09; 因为防火默认是开启状态的&#xff0c;如果只是手动关闭&#xff0c;先次…

《机器学习核心算法》分类算法 - 朴素贝叶斯 MultinomialNB

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 朴素贝叶斯 1、朴素贝叶斯API2、朴素贝叶斯算法实际应用2.1、获取数据集2.2、划分…

Java笔记042-反射章节练习

反射章节练习 练习1&#xff1a;通过反射修改私有成员变量 定义PrivateTest类&#xff0c;有私有name属性&#xff0c;并且属性值为helloKitty提供getName的公有方法创建PrivateTest的类&#xff0c;利用Class类得到私有的name属性&#xff0c;修改私有的name属性值&#xff…

算法 数据结构 递归冒泡算法 java冒泡算法 优化递归冒泡 数据结构(九)

使用递归算法实现冒泡&#xff1a; package com.nami.algorithm.study.day06;import java.util.Arrays;/*** beyond u self and trust u self.** Author: lbc* Date: 2023-09-05 15:36* email: 594599620qq.com* Description: keep coding*/ public class BubbleSort2 {// p…