python智能联系人管理

示例简介

python利用百度文字识别功能,实现对上传的名片进行扫描,并获取名片信息;可查看名片原图,也可以保存信息到Excel。

开发环境:Windows7+python3.7+pycharm2018.2.4(开发工具);

目录机构:

最终效果:

百度端创建应用

创建过程参考《微信小程序利用百度AI实现扫描身份证获取信息功能》(把“图像识别”换为“文字识别”)。

实现过程

一、阅读器UI设计

1. 安装模块和配置工具,参考《python实现小说阅读器》

2. 运行工具QtDesigner,利用QtDesigner工具箱设计出界面效果(所需要的控件可查看右边区域),保存效果为文件bc.ui;

3. 对文件bc.ui执行pyUIC(ui转化为py代码),执行完生成文件bc.py。

二、代码设计

1. 新建文件bc_main.py,该文件为项目主文件,初始化页面并显示;

2. 添加内置模块(下面代码使用)和主方法(用于运行后弹出界面);

Tips:由于是引入bc(bc.py),而未对其修改,所以开发过程中可以随时修改设计重新生成bc.py,不会覆盖掉自己编写的代码;但要注意如果修改了表单属性和名称等,编写的代码要跟着修改;

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

# 引入自定义模块
import bc
# 引入内置模块
import sys
import os
# 引入第三方模块
import pandas as pd
import requests, base64
from PIL import Image
import phone
# 文字识别sdk所需要模块
from aip import AipOcr
class parentWindow(QWidget,bc.Ui_Form):
    # 初始化方法
    def __init__(self):
        # 找到父类 首页面
        super(parentWindow, self).__init__()
        # 初始化页面方法
        self.setupUi(self)
        # 点击选择名片
        self.selectCard.clicked.connect(self.openfile)
        # 点击查看名片
        self.viewButton.clicked.connect(self.viewbtn)
        # 点击保存按钮
        self.saveButton.clicked.connect(self.saveData)
if __name__=='__main__':
    # 每一个PyQt5应用都必须创建一个应用对象
    app=QApplication(sys.argv)
    # 初始化页面
    window=parentWindow()
    # 显示首页
    window.show()
    sys.exit(app.exec_())

3. 添加公共代码,用来判断“名片信息表.xlsx”是否存在,不存在则新建该文件并定义好列名;

# 获取当前路径
cdir = os.getcwd()
# 文件路径
path = cdir+'/名片信息表.xlsx'
# 读取路径 判断是否创建了文件
if not os.path.exists(path):
    # 根据路径建立文件夹
    # os.makedirs(path)
    # 姓名 手机 电话 邮箱 网址 公司 地址 城市
    cardfile = pd.DataFrame(columns=['name', 'mobile', 'tel', 'email', 'url', 'comp', 'addr', 'city'])
    # 生成xlsx文件
    cardfile.to_excel(path, sheet_name='data', index=None)

4. 添加图片识别函数recgImg,用来扫描图片获取图片信息;而文字识别百度给了两种方法选择,一种使用API(本文使用),详细参考https://cloud.baidu.com/doc/OCR/s/5k3h7xyi2;另一种是使用SDK,详细参考https://cloud.baidu.com/doc/OCR/s/5k3h7xyi2

# 识别名片图片
def recgImg(self):
    # 获取baiduToken
    apikey = '你的apikey'
    seckey = '你的seckey'
    tokenUrl = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + apiKey + '&client_secret=' + seckey
    res = requests.get(url=tokenUrl, headers={'content-type': 'application/json; charset=UTF-8'}).json()
    baiduToken = res['access_token']

    '''
    名片识别(API)
    '''
    request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/business_card"
    # 二进制方式打开图片文件
    f = open(self.download_path[0], 'rb')
    img = base64.b64encode(f.read())

    params = {"image": img}
    # access_token = '[调用鉴权接口获取的token]'
    request_url = request_url + "?access_token=" + baiduToken
    headers = {'content-type': 'application/x-www-form-urlencoded'}
    response = requests.post(request_url, data=params, headers=headers)
    if response:
        print(response.json())
        return response.json()

    # """ 你的 APPID AK SK(SDK) """
    # APP_ID = '你的APP_ID'
    # API_KEY = '你的API_KEY'
    # SECRET_KEY = '你的SECRET_KEY'
    #
    # client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
    # """ 读取图片 """
    # def get_file_content(filePath):
    #     with open(filePath, 'rb') as fp:
    #         return fp.read()
    #
    # image = get_file_content(self.download_path[0])
    #
    # """ 如果有可选参数 """
    # options = {}
    # options["language_type"] = "CHN_ENG"
    # options["detect_direction"] = "true"
    # options["detect_language"] = "true"
    # options["probability"] = "false"
    #
    # """ 调用api"""
    # picture_result = client.basicAccurate(image, options)  # 返回识别结果
    # words_result = picture_result['words_result']
    # print(words_result)
    # return words_result

5. 实现点击“选择名片”功能,用来扫描选择的名片,并把名片和获取到的名片信息显示到界面;

# 选择名片按钮执行方法
def openfile(self):
    # 启动选择文件对话空,查找jpg以及png图片
    self.download_path = QFileDialog.getOpenFileName(self, "选择要识别的图片", os.getcwd(), "Image Files(*.jpg *.png)")
    # 判断是否选择图片
    if not self.download_path[0].strip():
        QMessageBox.information(self, '提示信息', '没有选择名片图片')
        pass
    else:
        # pixmap解析图片
        pixmap = QPixmap(self.download_path[0])
        # 设置图片
        self.imgLable.setPixmap(pixmap)
        # 让图片自适应label大小
        self.imgLable.setScaledContents(True)
        try:
            # 识别名片图片返回识别结果
            content = self.recgImg()
        except:
            QMessageBox.information(self, '提示信息', '识别错误请重新选择图片')

        # 识别图片的数据赋值
        words_result = content['words_result']
        for key in words_result:
            textValue = words_result[key][0]
            if key == 'NAME':
                self.usLineEdit.setText(textValue)
            elif key == 'MOBILE':
                self.phoneLineEdit.setText(textValue)
            elif key == 'TEL':
                self.telLineEdit.setText(textValue)
            elif key == 'EMAIL':
                self.emailLineEdit.setText(textValue)
            elif key == 'URL':
                self.urlLineEdit.setText(textValue)
            elif key == 'COMPANY':
                self.companyLineEdit.setText(textValue)
            elif key == 'ADDR':
                self.addrLineEdit.setText(textValue)

6. 实现点击“查看名片”功能,用来全屏显示名片图片;

# 点击查看名片显示大图功能
def viewbtn(self):
    if self.download_path:
        # 使用电脑中的看图工具打开图片
        img = Image.open(self.download_path[0])
        # 显示图片
        img.show()
    else:
        QMessageBox.information(self, '提示信息', '先选择名片图片')

7. 添加公共函数clearCardData,用来在保存成功后清除图片和名片信息;

# 清理名片数据
def clearCardData(self):
    # 去掉历史图片路径
    self.download_path = ''
    # 移除控件上图片
    self.imgLable.setPixmap(QPixmap(""))
    # 移除输入框内容
    self.usLineEdit.setText("")
    self.phoneLineEdit.setText("")
    self.telLineEdit.setText("")
    self.emailLineEdit.setText("")
    self.urlLineEdit.setText("")
    self.companyLineEdit.setText("")
    self.addrLineEdit.setText("")

8. 实现点击“保存”功能,用来把获取的信息保存到Excel;

# 保存名片信息到文档
def saveData(self):
    pi_table = pd.read_excel(path, sheet_name='data')
    # 获取输出框内容
    name = self.usLineEdit.text()
    mobile = self.phoneLineEdit.text()
    tel = self.telLineEdit.text()
    email = self.emailLineEdit.text()
    url = self.urlLineEdit.text()
    comp = self.companyLineEdit.text()
    addr = self.addrLineEdit.text()
    # 判断手机号是否为空
    if mobile.strip():
        # 根据手机号判断区域
        try:
            info = phone.Phone().find(int(mobile))
        except Exception as e:
            QMessageBox.critical(self, "错误:", "手机号码不正确!", QMessageBox.Ok)  # 弹出提示对话框
            self.phoneLineEdit.setFocus()  # 让手机文本框获得焦点
            return
        # 判断手机号是否正确返回信息
        if info == None:
            city = '其他'
        else:
            # 正确返回信息获取省
            city = info['province']
    else:
        city = '其他'
    # 判断姓名是否为空
    if name.strip():
        # 添加数据
        data = pi_table.append({'name': name,
                                'mobile': mobile,
                                'tel': tel,
                                'email': email,
                                'url': url,
                                'comp': comp,
                                'addr': addr,
                                'city': city,
                                }, ignore_index=True)
        # 更新xlsx文件
        pd.DataFrame(data).to_excel(path, sheet_name='data', index=False)
        # 保存成功
        QMessageBox.information(self, '提示信息', '保存成功')

        self.clearCardData()
    else:
        QMessageBox.information(self, '提示信息', '姓名不能为空')
    pass

9. 最终合并代码:

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

# 引入自定义模块
import bc
# 引入内置模块
import sys
import os
# 引入第三方模块
import pandas as pd
import requests, base64
from PIL import Image
import phone
# 文字识别sdk所需要的模块
from aip import AipOcr

# 获取当前路径
cdir = os.getcwd()
# 文件路径
path = cdir+'/名片信息表.xlsx'
# 读取路径 判断是否创建了文件
if not os.path.exists(path):
    # 根据路径建立文件夹
    # os.makedirs(path)
    # 姓名 手机 电话 邮箱 网址 公司 地址 城市
    cardfile = pd.DataFrame(columns=['name', 'mobile', 'tel', 'email', 'url', 'comp', 'addr', 'city'])
    # 生成xlsx文件
    cardfile.to_excel(path, sheet_name='data', index=None)

class parentWindow(QWidget,bc.Ui_Form):
    # 初始化方法
    def __init__(self):
        # 找到父类 首页面
        super(parentWindow, self).__init__()
        # 初始化页面方法
        self.setupUi(self)
        # 点击选择名片
        self.selectCard.clicked.connect(self.openfile)
        # 点击查看名片
        self.viewButton.clicked.connect(self.viewbtn)
        # 点击保存按钮
        self.saveButton.clicked.connect(self.saveData)

    #选择名片按钮执行方法
    def openfile(self):
        # 启动选择文件对话空,查找jpg以及png图片
        self.download_path = QFileDialog.getOpenFileName(self, "选择要识别的图片", os.getcwd(), "Image Files(*.jpg *.png)")
        # 判断是否选择图片
        if not self.download_path[0].strip():
            QMessageBox.information(self, '提示信息', '没有选择名片图片')
            pass
        else:
            # pixmap解析图片
            pixmap = QPixmap(self.download_path[0])
            # 设置图片
            self.imgLable.setPixmap(pixmap)
            # 让图片自适应label大小
            self.imgLable.setScaledContents(True)
            try:
                # 识别名片图片返回识别结果
                content=self.recgImg()
            except:
                QMessageBox.information(self, '提示信息', '识别错误请重新选择图片')

            # 识别图片的数据赋值
            words_result = content['words_result']
            for key in words_result:
                textValue = words_result[key][0]
                if key == 'NAME':
                    self.usLineEdit.setText(textValue)
                elif key == 'MOBILE':
                    self.phoneLineEdit.setText(textValue)
                elif key == 'TEL':
                    self.telLineEdit.setText(textValue)
                elif key == 'EMAIL':
                    self.emailLineEdit.setText(textValue)
                elif key == 'URL':
                    self.urlLineEdit.setText(textValue)
                elif key == 'COMPANY':
                    self.companyLineEdit.setText(textValue)
                elif key == 'ADDR':
                    self.addrLineEdit.setText(textValue)

    # 识别名片图片
    def recgImg(self):
        # 获取baiduToken
        apikey = '你的apikey'
        seckey = '你的seckey'
        tokenUrl = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id='+apikey+'&client_secret='+seckey
        res = requests.get(url=tokenUrl, headers={'content-type': 'application/json; charset=UTF-8'}).json()
        baiduToken = res['access_token']

        '''
        名片识别(API)
        '''
        request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/business_card"
        # 二进制方式打开图片文件
        f = open(self.download_path[0], 'rb')
        img = base64.b64encode(f.read())

        params = {"image": img}
        # access_token = '[调用鉴权接口获取的token]'
        request_url = request_url + "?access_token=" + baiduToken
        headers = {'content-type': 'application/x-www-form-urlencoded'}
        response = requests.post(request_url, data=params, headers=headers)
        if response:
            print(response.json())
            return response.json()

        # """ 你的 APPID AK SK(SDK) """
        # APP_ID = '你的APP_ID'
        # API_KEY = '你的API_KEY'
        # SECRET_KEY = '你的SECRET_KEY'
        #
        # client = AipOcr(APP_ID, API_KEY, SECRET_KEY)
        # """ 读取图片 """
        # def get_file_content(filePath):
        #     with open(filePath, 'rb') as fp:
        #         return fp.read()
        #
        # image = get_file_content(self.download_path[0])
        #
        # """ 如果有可选参数 """
        # options = {}
        # options["language_type"] = "CHN_ENG"
        # options["detect_direction"] = "true"
        # options["detect_language"] = "true"
        # options["probability"] = "false"
        #
        # """ 调用api"""
        # picture_result = client.basicAccurate(image, options)  # 返回识别结果
        # words_result = picture_result['words_result']
        # print(words_result)
        # return words_result

    # 点击查看名片显示大图功能
    def viewbtn(self):
        if self.download_path:
            # 使用电脑中的看图工具打开图片
            img = Image.open(self.download_path[0])
            # 显示图片
            img.show()
        else:
            QMessageBox.information(self, '提示信息', '先选择名片图片')

    # 保存名片信息到文档
    def saveData(self):
        pi_table = pd.read_excel(path, sheet_name='data')
        # 获取输出框内容
        name =self.usLineEdit.text()
        mobile = self.phoneLineEdit.text()
        tel = self.telLineEdit.text()
        email = self.emailLineEdit.text()
        url = self.urlLineEdit.text()
        comp = self.companyLineEdit.text()
        addr = self.addrLineEdit.text()
        # 判断手机号是否为空
        if mobile.strip():
           # 根据手机号判断区域
           try:
               info = phone.Phone().find(int(mobile))
           except Exception as e:
               QMessageBox.critical(self,"错误:","手机号码不正确!",QMessageBox.Ok) # 弹出提示对话框
               self.phoneLineEdit.setFocus()  # 让手机文本框获得焦点
               return
           # 判断手机号是否正确返回信息
           if info==None:
               city = '其他'
           else:
               # 正确返回信息获取省
               city = info['province']
        else:
           city = '其他'
        # 判断姓名是否为空
        if name.strip():
            # 添加数据
            data = pi_table.append({'name': name,
                                    'mobile': mobile,
                                    'tel': tel,
                                    'email': email,
                                    'url': url,
                                    'comp': comp,
                                    'addr': addr,
                                    'city': city,
                                    }, ignore_index=True)
            # 更新xlsx文件
            pd.DataFrame(data).to_excel(path, sheet_name='data', index=False)
            # 保存成功
            QMessageBox.information(self, '提示信息', '保存成功')

            self.clearCardData()
        else:
            QMessageBox.information(self, '提示信息', '姓名不能为空')
        pass

    # 清理名片数据
    def clearCardData(self):
        # 去掉历史图片路径
        self.download_path = ''
        # 移除控件上图片
        self.imgLable.setPixmap(QPixmap(""))
        # 移除输入框内容
        self.usLineEdit.setText("")
        self.phoneLineEdit.setText("")
        self.telLineEdit.setText("")
        self.emailLineEdit.setText("")
        self.urlLineEdit.setText("")
        self.companyLineEdit.setText("")
        self.addrLineEdit.setText("")

if __name__=='__main__':
    # 每一个PyQt5应用都必须创建一个应用对象
    app=QApplication(sys.argv)
    # 初始化页面
    window=parentWindow()
    # 显示首页
    window.show()
    sys.exit(app.exec_())

最后结语

本文利用python+百度文字识别,实现上传名片的扫描,并把图片和获取的信息显示到界面,可点击“查看名片”全屏浏览图片,也可点击“保存”,把信息保存到Excel。

                                                                             扫描公众号,了解更多实例分享

Guess you like

Origin blog.csdn.net/king0964/article/details/106193694