发票账单很多?python助你批量完成数据提取

每天面对成堆的发票,无论是税务发票还是承兑单据,抑或是其他各类公司数据要从照片、PDF等不同格式的内容中提取,我们都有必要进行快速办公的能力提升。
因此,我们的目标要求就十分明显了,首先要从图片中获取数据,其次将数据统一导入到EXCEL中。
配置需求:
1.ImageMagick : https://download.csdn.net/download/yyfloveqcw/87579790
2.tesseract-OCR : https://download.csdn.net/download/yyfloveqcw/87579801
3.Python3.7
4.from PIL import Image as PI
5.import io
6.import os
7.import pyocr.builders
8.from cnocr import CnOcr
9.import xlwt

分析上图发现票据金额为“贰拾万元整”,数据金额为大写中文,因此在导入Excel之前我们需要将金额票据的数据转换成数字的格式,基于此,我们需要首先完成大写汉字和数字的转换。
def chineseNumber2Int(strNum: str):result = 0temp = 1 # 存放一个单位的数字如:十万count = 0 # 判断是否有chArrcnArr = ['壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']chArr = ['拾', '佰', '仟', '万', '亿']for i in range(len(strNum)):b = Truec = strNum[i]for j in range(len(cnArr)):if c == cnArr[j]:if count != 0:result += tempcount = 0temp = j + 1b = Falsebreakif b:for j in range(len(chArr)):if c == chArr[j]:if j == 0:temp *= 10elif j == 1:temp *= 100elif j == 2:temp *= 1000elif j == 3:temp *= 10000elif j == 4:temp *= 100000000count += 1if i == len(strNum) - 1:result += tempreturn result
通过上述代码即可实现大写字母与数字的转换,例如输入“贰拾万元整”即可导出“200000”,再将其转换成数字后即可极大地简化表格的操作,也可以在完成表格操作的同时有利于数据归档。
接下来,我们需要分析发票的内部内容,分析下图可知,我们需要获取以下几个数据内容:“出票日期”、“汇票到账日期”、“票据号码”、“收款人”、“票据金额”、“出票人”,可以通过画图软件获取精准定位。

如图,小黑点即鼠标所在地,画图软件左下角即他的坐标。

提取出票日期
def text1(new_img):#提取出票日期left = 80top = 143right = 162bottom = 162image_text1 = new_img.crop((left, top, right, bottom))#展示图片#image_text1.show()txt1 = tool.image_to_string(image_text1)print(txt1)return str(txt1)
2.提取金额
def text2(new_img):#提取金额left = 224top = 355right = 585bottom = 380image_text2 = new_img.crop((left, top, right, bottom))#展示图片#image_text2.show()image_text2.save("img/tmp.png")temp = ocr.ocr("img/tmp.png")temp="".join(temp[0])txt2=chineseNumber2Int(temp)print(txt2)return txt2
3.提取出票人
def text3(new_img):#提取出票人left = 177top = 207right = 506bottom = 231image_text3 = new_img.crop((left, top, right, bottom))#展示图片#image_text3.show()image_text3.save("img/tmp.png")temp = ocr.ocr("img/tmp.png")txt3="".join(temp[0])print(txt3)return txt3
4.提取付款行
def text4(new_img):#提取付款行left = 177top = 274right = 492bottom = 311image_text4 = new_img.crop((left, top, right, bottom))#展示图片#image_text4.show()image_text4.save("img/tmp.png")temp = ocr.ocr("img/tmp.png")txt4="".join(temp[0])print(txt4)return txt4
5.提取汇票到账日期
def text5(new_img):#提取汇票到日期left = 92top = 166right = 176bottom = 184image_text5 = new_img.crop((left, top, right, bottom))#展示图片#image_text5.show()txt5 = tool.image_to_string(image_text5)print(txt5)return txt5
6.提取票据单据
def text6(new_img):#提取票据号码left = 598top = 166right = 870bottom = 182image_text6 = new_img.crop((left, top, right, bottom))#展示图片#image_text6.show()txt6 = tool.image_to_string(image_text6)print(txt6)return txt6
在将数据全部提取完成之后,即进入设置环节,我们需要首先将所有账单文件进行提取,获取他们的文件名和路径。
ocr=CnOcr()
tool = pyocr.get_available_tools()[0]
filePath='img'
img_name=[]
for i,j,name in os.walk(filePath):img_name=name
在获取完整后,即可进行数据导入Excel的操作。
count=1
book = xlwt.Workbook(encoding='utf-8',style_compression=0)
sheet = book.add_sheet('test',cell_overwrite_ok=True)
for i in img_name:img_url = filePath+"/"+iwith open(img_url, 'rb') as f:a = f.read()new_img = PI.open(io.BytesIO(a))## 写入csvcol = ('年份','出票日期','金额','出票人','付款行全称','汇票到日期','备注')for j in range(0,7):sheet.write(0,j,col[j])book.save('1.csv')shijian=text1(new_img)sheet.write(count,0,shijian[0:4])sheet.write(count,1,shijian[5:])sheet.write(count,2,text2(new_img))sheet.write(count,3,text3(new_img))sheet.write(count,4,text4(new_img))sheet.write(count,5,text5(new_img))sheet.write(count,6,text6(new_img))count = count + 1
至此,完整流程结束。
附上源码全部:
from wand.image import Image
from PIL import Image as PI
import pyocr
import io
import re
import os
import shutil
import pyocr.builders
from cnocr import CnOcr
import requests
import xlrd
import xlwt
from openpyxl import load_workbookdef chineseNumber2Int(strNum: str):result = 0temp = 1 # 存放一个单位的数字如:十万count = 0 # 判断是否有chArrcnArr = ['壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']chArr = ['拾', '佰', '仟', '万', '亿']for i in range(len(strNum)):b = Truec = strNum[i]for j in range(len(cnArr)):if c == cnArr[j]:if count != 0:result += tempcount = 0temp = j + 1b = Falsebreakif b:for j in range(len(chArr)):if c == chArr[j]:if j == 0:temp *= 10elif j == 1:temp *= 100elif j == 2:temp *= 1000elif j == 3:temp *= 10000elif j == 4:temp *= 100000000count += 1if i == len(strNum) - 1:result += tempreturn resultdef text1(new_img):#提取出票日期left = 80top = 143right = 162bottom = 162image_text1 = new_img.crop((left, top, right, bottom))#展示图片#image_text1.show()txt1 = tool.image_to_string(image_text1)print(txt1)return str(txt1)
def text2(new_img):#提取金额left = 224top = 355right = 585bottom = 380image_text2 = new_img.crop((left, top, right, bottom))#展示图片#image_text2.show()image_text2.save("img/tmp.png")temp = ocr.ocr("img/tmp.png")temp="".join(temp[0])txt2=chineseNumber2Int(temp)print(txt2)return txt2def text3(new_img):#提取出票人left = 177top = 207right = 506bottom = 231image_text3 = new_img.crop((left, top, right, bottom))#展示图片#image_text3.show()image_text3.save("img/tmp.png")temp = ocr.ocr("img/tmp.png")txt3="".join(temp[0])print(txt3)return txt3
def text4(new_img):#提取付款行left = 177top = 274right = 492bottom = 311image_text4 = new_img.crop((left, top, right, bottom))#展示图片#image_text4.show()image_text4.save("img/tmp.png")temp = ocr.ocr("img/tmp.png")txt4="".join(temp[0])print(txt4)return txt4
def text5(new_img):#提取汇票到日期left = 92top = 166right = 176bottom = 184image_text5 = new_img.crop((left, top, right, bottom))#展示图片#image_text5.show()txt5 = tool.image_to_string(image_text5)print(txt5)return txt5
def text6(new_img):#提取票据号码left = 598top = 166right = 870bottom = 182image_text6 = new_img.crop((left, top, right, bottom))#展示图片#image_text6.show()txt6 = tool.image_to_string(image_text6)print(txt6)return txt6ocr=CnOcr()tool = pyocr.get_available_tools()[0]filePath='img'
img_name=[]
for i,j,name in os.walk(filePath):img_name=name
count=1book = xlwt.Workbook(encoding='utf-8',style_compression=0)
sheet = book.add_sheet('test',cell_overwrite_ok=True)for i in img_name:img_url = filePath+"/"+iwith open(img_url, 'rb') as f:a = f.read()new_img = PI.open(io.BytesIO(a))## 写入csvcol = ('年份','出票日期','金额','出票人','付款行全称','汇票到日期','备注')for j in range(0,7):sheet.write(0,j,col[j])book.save('1.csv')shijian=text1(new_img)sheet.write(count,0,shijian[0:4])sheet.write(count,1,shijian[5:])sheet.write(count,2,text2(new_img))sheet.write(count,3,text3(new_img))sheet.write(count,4,text4(new_img))sheet.write(count,5,text5(new_img))sheet.write(count,6,text6(new_img))count = count + 1
相关文章:

发票账单很多?python助你批量完成数据提取
每天面对成堆的发票,无论是税务发票还是承兑单据,抑或是其他各类公司数据要从照片、PDF等不同格式的内容中提取,我们都有必要进行快速办公的能力提升。因此,我们的目标要求就十分明显了,首先要从图片中获取数据&#x…...
[闪存2.1] NAND FLASH特性串烧 | 不了解闪存特性,你能用好闪存产品吗?
前言 为了利用好闪存, 发挥闪存的优势, 以达到更好的性能和使用寿命, 那自然要求了解闪存特性。 闪存作为一种相对较新的存储介质, 有很多特别的特性。 一.闪存的特性 凡是采用Flash Memory的存储设备,可以统称为闪存存储。我们经常谈的固态硬盘(SSD),可以由volatile/…...
面试官问我按钮级别权限怎么控制,我说v-if,面试官说再见
最近的面试中有一个面试官问我按钮级别的权限怎么控制,我说直接v-if啊,他说不够好,我说我们项目中按钮级别的权限控制情况不多,所以v-if就够了,他说不够通用,最后他对我的评价是做过很多东西,但…...
阿里云服务器使用教程:CentOS 7安装nginx详细步骤
目录 1、下载nginx压缩包 2、配置nginx安装所需环境 3、解压nginx压缩包 4、编译安装nginx 5、nginx启动...
Android JNI浅析、Java和Native通信对象的传值和回调
简单了解一下jni JNI是一个本地编程接口,它允许运行在Java虚拟机的Java代码与用其他语言(如C,C和汇编)编写的库交互。 jni函数签名 首先看一下java类型对应的jni类型: Java类型符号BooleanZByteBCharCShortSIntILongJFloatFDo…...

linux目录/usr/lib/systemd/system目录详解
文章目录前言一. systemd介绍二. service 脚本详解2.1 [Unit] 区块2.2 [Service] 区块2.3 [Install] 区块总结前言 init的进化经历了这么几个阶段: CentOS 5: SysV init,串行 CentOS 6:Upstart,并行,借鉴ubuntu CentOS 7:Syste…...

408考研计算机之计算机组成与设计——知识点及其做题经验篇目4:CPU的功能和基本结构
随着考研的慢慢复习,我们逐渐进入了计算机组成与设计的第五章中央处理器。它原名为CPU。姓C,名PU,字中央处理器,号计组难点,乃计算机之中心与核心部件,小编称之曰能算能控,赐名曰九天宏教普济生…...
2022-12-10青少年软件编程(C语言)等级考试试卷(五级)解析
2022-12-10青少年软件编程(C语言)等级考试试卷(五级)解析T1、漫漫回国路 2020年5月,国际航班机票难求。一位在美国华盛顿的中国留学生,因为一些原因必须在本周内回到北京。现在已知各个机场之间的航班情况,求问他回不回得来(不考虑转机次数和机票价格)。 时间限制:10…...

刷题专练之链表(一)
文章目录前言一、 移除链表元素1.题目介绍2.思路3.代码二、反转链表1.题目介绍2.思路3.代码三、链表的中间结点1.题目介绍2.思路3.代码四、链表的中间结点1.题目介绍2.思路3.代码前言 以下是链表经常考的面试题,我在这里进行归纳和讲解,采取的是循序渐进…...
elasticsearch高级查询api
yml配置 #es配置 spring:elasticsearch:rest:uris: 192.168.16.188:9200添加依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>使用编程的形式…...

力扣-股票的资本损益
大家好,我是空空star,本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目:1393. 股票的资本损益二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.其他…...

蓝桥杯刷题冲刺 | 倒计时26天
作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.路径2.特别数的和3.MP3储存4.求和1.路径 题目 链接: 路径 - 蓝桥云课 (lanqiao.cn…...

嵌入式软件开发之Linux 用户权限管理
目录 Ubuntu 用户系统 权限管理 权限管理命令 权限修改命令 chmod 文件归属者修改命令 chown Ubuntu 用户系统 Ubuntu 是一个多用户系统,我们可以给不同的使用者创建不同的用户账号,每个用户使用各自的账号登陆,使用用户账号的目的一是方便…...
2023-03-15 RabbitMQ
RabbitMQ整合 官网erlang版本 : 20.3.8.x 官方rabbitMq版本: rabbitmq-server-generic-unix-3.7.14.tar.xz 1.安装 1.1 安装erlang 1.安装环境 yum -y install make gcc gcc-c kernel-devel m4 ncurses-devel openssl-devel2.在/usr/local/下创建erlangapp文件…...

二叉树链式结构的实现
文章目录1.二叉树的遍历1.1前序、中序以及后序遍历1.2代码测试1.3层序遍历1.4二叉树遍历习题2.节点个数以及高度2.1二叉树节点个数2.2叶子节点个树2.3第k层节点个数2.4树的高度1.二叉树的遍历 1.1前序、中序以及后序遍历 学习二叉树结构,最简单的方式就是遍历。所…...

蓝桥杯刷题冲刺 | 倒计时28天
作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.卡片2.数字三角形3.购物单4.回文日期1.卡片 题目 链接: 卡片 - 蓝桥云课 (lanqiao…...
一文带你吃透操作系统
文章目录1. 进程、线程管理2. 内存管理3. 进程调度算法4. 磁盘调度算法5. 页面置换算法6. 网络系统7. 锁8. 操作系统知识点文章字数大约1.9万字,阅读大概需要65分钟,建议收藏后慢慢阅读!!!1. 进程、线程管理 进程和线程…...
计算机网络英文简称汇总
分类名词全拼汉译概述B2CBusiness-to-Consumer商对客概述P2PPeer-to-Peer对等概述C/SClient-Server服务器-客户机概述ITUInternational Telecommunication Union国际电信联盟概述IEEEInstitute of Electrical and Electronics Engineers电气与电子工程师协会概述ICCCInternatio…...

腾讯云云服务器标准型S5性能配置简单测评
腾讯云服务器标准型S5实例CPU采用Intel Xeon Cascade Lake或者Intel Xeon Cooper Lake处理器,主频2.5GHz,睿频3.1GHz,标准型S5云服务器基于全新优化虚拟化平台,配有全新的Intel Advanced Vector Extension (AVX-512) 指令集&#…...

RK3568平台开发系列讲解(Linux系统篇)消息队列
🚀返回专栏总目录 文章目录 一、创建消息队列二、发送和接收消息三、内核结构沉淀、分享、成长,让自己和他人都能有所收获!😄 📢消息队列在如下两个方面上比管道有所增强: 消息队列中的数据是有边界的,发送端和接收端能以消息为单位进行交流,而不再是无分隔的字节流…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...