前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Python批量识别发票

Python批量识别发票

原创
作者头像
花落花相惜
发布于 2021-12-05 15:24:25
发布于 2021-12-05 15:24:25
1.1K0
举报

01.场景描述

这里有以四张发票为例(辰哥网上搜的),将发票图片放到pic文件夹下。

image

随便打开一张发票

image

提取目标: 金额名称纳税人识别号开票人

image

最后将每一张发票的这四个内容保存到excel中:

image

02.准备环境

需要用到的库如下:

代码语言:txt
AI代码解释
复制
from PIL import Image as PI
代码语言:txt
AI代码解释
复制
import pyocr
代码语言:txt
AI代码解释
复制
import pyocr.builders
代码语言:txt
AI代码解释
复制
from cnocr import CnOcr

安装的命令如下:

代码语言:txt
AI代码解释
复制
pip install pyocr
代码语言:txt
AI代码解释
复制
pip install cnocr

发票中含有中文内容,我们需要对图片中的中文进行识别,那么 cnocr 是一个不错的选择。

提示 :安装好上面的库之外,还需要安装额外的exe文件,不然会出现下面这种错误

image

需要安装的exe文件:

1. ImageMagick
2. tesseract-OCR

这两个软件的安装过程就不再赘述了,大家可以自行搜索教程进行安装。

03.提取内容

下面以其中一张图片为例,讲解如何提取目标内容: 金额名称纳税人识别号开票人

image

读取图片: pic/pic1.jpg

代码语言:txt
AI代码解释
复制
tool = pyocr.get_available_tools()[0]
代码语言:txt
AI代码解释
复制
img_url = "pic/pic1.jpg"
代码语言:txt
AI代码解释
复制
with open(img_url, 'rb') as f:
代码语言:txt
AI代码解释
复制
    a = f.read()
代码语言:txt
AI代码解释
复制
new_img = PI.open(io.BytesIO(a))

1.提取金额

需要截取到发票中 金额 的位置

代码语言:txt
AI代码解释
复制
## 金额
代码语言:txt
AI代码解释
复制
left = 741
代码语言:txt
AI代码解释
复制
top = 420
代码语言:txt
AI代码解释
复制
right = 850
代码语言:txt
AI代码解释
复制
bottom = 445
代码语言:txt
AI代码解释
复制
image_text1 = new_img.crop((left, top, right, bottom))
代码语言:txt
AI代码解释
复制
#展示图片
代码语言:txt
AI代码解释
复制
image_text1.show()

这里的left、top、right、bottom的数值是通过 多次修改定位而来 。大家根据自己的发票内容去定位即可。

image

接着将 图片中的数字提取出来

image

同样的,下面继续提取: 名称

2.提取名称

代码语言:txt
AI代码解释
复制
left = 155
代码语言:txt
AI代码解释
复制
top = 450
代码语言:txt
AI代码解释
复制
right = 450
代码语言:txt
AI代码解释
复制
bottom = 470
代码语言:txt
AI代码解释
复制
image_obj2 = new_img.crop((left, top, right, bottom))
代码语言:txt
AI代码解释
复制
image_obj2.show()

image

这里的名称是中文的,咱们不能再像提取金额( 数字 )操作。需要使用到cnocr去将图片中的中文取出。

代码语言:txt
AI代码解释
复制
image_obj2.save("tmp.jpg")
代码语言:txt
AI代码解释
复制
ocr = CnOcr()
代码语言:txt
AI代码解释
复制
res = ocr.ocr("tmp.jpg")
代码语言:txt
AI代码解释
复制
print("".join(res[0]))

image

3.提取纳税人识别号

代码语言:txt
AI代码解释
复制
#纳税人识别号
代码语言:txt
AI代码解释
复制
left = 155
代码语言:txt
AI代码解释
复制
top = 470
代码语言:txt
AI代码解释
复制
right = 450
代码语言:txt
AI代码解释
复制
bottom = 490
代码语言:txt
AI代码解释
复制
image_text3 = new_img.crop((left, top, right, bottom))
代码语言:txt
AI代码解释
复制
#展示图片
代码语言:txt
AI代码解释
复制
image_text3.show()

image

代码语言:txt
AI代码解释
复制
txt3 = tool.image_to_string(image_text3)
代码语言:txt
AI代码解释
复制
print(txt3)

将图片中的纳税人识别号提取出来,结果如下:

image

4.提取开票人

代码语言:txt
AI代码解释
复制
left = 528
代码语言:txt
AI代码解释
复制
top = 550
代码语言:txt
AI代码解释
复制
right = 670
代码语言:txt
AI代码解释
复制
bottom = 600
代码语言:txt
AI代码解释
复制
image_obj4 = new_img.crop((left, top, right, bottom))
代码语言:txt
AI代码解释
复制
image_obj4.show()

image

代码语言:txt
AI代码解释
复制
image_obj4.save("tmp.jpg")
代码语言:txt
AI代码解释
复制
ocr = CnOcr()
代码语言:txt
AI代码解释
复制
res = ocr.ocr("tmp.jpg")
代码语言:txt
AI代码解释
复制
print("".join(res[0]))

由于有中文,咱们这里同样和提取 名称 一样,使用cnocr将图片中的中文取出。

image

ok这样我们就将发票中的四个目标内容提取出来,接着将 文件夹pic 下的所有发票,进行识别将内容保存到excel。

04.批量识别发票并保存到excel

在读取图片之前,先将上面的四个操作封装成函数,方便每一种发票对象进行调用。

image

读取文件夹下的所有图片。

代码语言:txt
AI代码解释
复制
filePath = 'pic'
代码语言:txt
AI代码解释
复制
pic_name = []
代码语言:txt
AI代码解释
复制
for i,j,name in os.walk(filePath):
代码语言:txt
AI代码解释
复制
    pic_name = name
代码语言:txt
AI代码解释
复制
for i in pic_name:
代码语言:txt
AI代码解释
复制
    print(i)

image

开始进行识别,并将结果写入到excel中。

代码语言:txt
AI代码解释
复制
for i in pic_name:
代码语言:txt
AI代码解释
复制
    img_url = filePath+"/"+i
代码语言:txt
AI代码解释
复制
    with open(img_url, 'rb') as f:
代码语言:txt
AI代码解释
复制
        a = f.read()
代码语言:txt
AI代码解释
复制
    new_img = PI.open(io.BytesIO(a))
代码语言:txt
AI代码解释
复制
    ## 写入csv
代码语言:txt
AI代码解释
复制
    outws.cell(row=count, column=1, value=text2(new_img))
代码语言:txt
AI代码解释
复制
    outws.cell(row=count, column=2, value=text3(new_img))
代码语言:txt
AI代码解释
复制
    outws.cell(row=count, column=3, value=text1(new_img))
代码语言:txt
AI代码解释
复制
    outws.cell(row=count, column=4, value=text4(new_img))
代码语言:txt
AI代码解释
复制
    count = count + 1
代码语言:txt
AI代码解释
复制
outwb.save("发票汇总-李运辰.xls")  # 保存结果

最后保存为:发票汇总-李运辰.xls,其结果如下:

image

05.发票验证真伪

在辰哥的交流群里,和小伙伴聊到这个内容时,小伙伴建议可以加一个功能: 发票验证真伪

image

所有在上面的开始识别之前(自己公司的发票可能不需要查验这步),先调用一下第三方的接口,对发票进行识别,识别通过之后再将其提取发票中目标内容。

1.申请百度AI应用

image

2.获取token

代码语言:txt
AI代码解释
复制
# client_id 为官网获取的AK, client_secret 为官网获取的SK
代码语言:txt
AI代码解释
复制
host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=【官网获取的AK】&client_secret=【官网获取的SK】'
代码语言:txt
AI代码解释
复制
response = requests.get(host)
代码语言:txt
AI代码解释
复制
if response:
代码语言:txt
AI代码解释
复制
    print(response.json()['access_token']

这里的client_id 为官网获取的AK, client_secret 为官网获取的SK,是上面申请好应用即可获取

3.查验

image

咱以这张图片为例,进行查验

image

其中的发票类型对应如下:

image

结果如下:

image

感觉这个结果查询不是很好(不详细)。下面还可以去 税务局 查询

4.税务局查询发票

image

同样以这张图片为例,进行查验

image

填写好信息点击查验,结果如下:

image

再税务局查验更加清晰。读者可以根据自己的情况去选择自己的方式去查验。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
暂无评论
推荐阅读
浅谈@Autowired注解shiyong
因为Student 的两个bean id分别为student和student02,恰好我们的变量名也叫student和student02,故不会报错。假如变量名为stu没有对应的bean id,那么就会在使用时抛出异常BeanCreationException。
编程大道
2019/08/02
9730
为什么 Spring 和 IDEA 都不推荐使用 @Autowired 注解?
大家在使用IDEA开发的时候有没有注意到过一个提示,在字段上使用Spring的依赖注入注解@Autowired后会出现如下警告
终码一生
2022/10/28
7540
为什么 Spring 和 IDEA 都推荐使用 @Resource注解而不是@Autowired?
@Autowired 和 @Resource 都是 Spring/Spring Boot 项目中,用来进行依赖注入的注解。它们都提供了将依赖对象注入到当前对象的功能,但二者却有众多不同。
默 语
2024/11/20
4400
为什么 Spring 和 IDEA 都推荐使用 @Resource注解而不是@Autowired?
Autowired注解
package com.how2java.pojo; import org.springframework.beans.factory.annotation.Autowired; public class Product { private int id; private String name; @Autowired // 等价于 @Resource(name="c") private Category category; public int g
互联网金融打杂
2018/04/03
6250
@Autowired 注解
在 Spring 框架中,@Autowired 注解是一个常用的注解,用于自动注入依赖对象。本文将深入探讨 @Autowired 注解的含义、用法以及运行原理,帮助读者更好地理解和使用该注解。
疯狂的KK
2023/07/01
4050
04 Spring的@Autowired注解、@Resource注解、@Service注解
什么是注解 传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop、事务,这么做有两个缺点: 1、如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大;如果按需求分开.xml文件,那么.xml文件又会非常多。总之这将导致配置文件的可读性与可维护性变得很低。 2、开发中需要在.java文件和.xml文件之间不断切换,是一件麻烦的事,同时这种思维上的不连贯也会降低开发的效率。 为了解决这两个问题,Spring引入了注解,通过@XXX的方式,让注解与Java Bean 紧密结合
nnngu
2018/03/15
1.6K0
为什么 Spring和IDEA 都不推荐使用 @Autowired 注解
原因详情描述: Inspection info: Spring Team recommends: "Always use constructor based dependency injection in your beans. Always use assertions for mandatory dependencies". 译为: Spring 团队建议: 始终在您的 bean 中使用基于构造函数的依赖注入。始终对强制依赖项使用断言
时间静止不是简史
2022/04/02
1.6K0
为什么 Spring和IDEA 都不推荐使用 @Autowired 注解
Autowired注解与Resource注解的区别
在我们使用Spring的过程中,经常需要使用bean,而Spring提供了bean的自动注入机制,在Java中,存在Autowired注解与Resource注解两种实现bean自动注入的注解,但两者存在区别。
摸鱼的G
2023/05/07
2620
原来 @Autowired 注解还可以这么玩?!
Spring 是我们平常开发中离不开的核心框架,每天开发都在使用 Spring 的功能。
macrozheng
2021/07/02
2.7K1
原来 @Autowired 注解还可以这么玩?!
为什么Spring不推荐@Autowired用于字段注入?
作为Java程序员,Spring绝对是我们日常开发中使用频次最高的框架之一。它灵活的依赖注入机制为我们开发高可维护性的代码提供了极大的便利。然而,尽管@Autowired注解让依赖注入变得如此简单,Spring官方却明确不推荐在字段上使用它进行注入。那么,为什么会这样?今天,我们就来深入探讨一下这个问题。
阿珍
2024/10/15
3590
为什么Spring不推荐@Autowired用于字段注入?
Spring注解-@Autowired注解使用
首先要知道另一个东西,default-autowire,它是在xml文件中进行配置的,可以设置为byName、byType、constructor和autodetect;比如byName,不用显式的在bean中写出依赖的对象,它会自动的匹配其它bean中id名与本bean的set**相同的,并自动装载。 @Autowired是用在JavaBean中的注解,通过byType形式,用来给指定的字段或方法注入所需的外部资源。 两者的功能是一样的,就是能减少或者消除属性或构造器参数的设置,只是配置地方不一样而已。 autowire四种模式的区别
SerMs
2022/04/11
1K0
Spring注解-@Autowired注解使用
为什么IDEA不推荐你使用@Autowired?
但是当我们使用IDEA写代码的时候,经常会发现@Autowired注解下面是有小黄线的,我们把小鼠标悬停在上面,可以看到这个如下图所示的警告信息:
SerMs
2022/04/11
6250
为什么IDEA不推荐你使用@Autowired?
注解@Autowired是如何实现的
使用spring开发时,进行配置主要有两种方式,一是xml的方式,二是java config的方式。spring技术自身也在不断的发展和改变,从当前springboot的火热程度来看,java config的应用是越来越广泛了,在使用java config的过程当中,我们不可避免的会有各种各样的注解打交道,其中,我们使用最多的注解应该就是@Autowired注解了。这个注解的功能就是为我们注入一个定义好的bean。那么,这个注解除了我们常用的属性注入方式之外还有哪些使用方式呢?它在代码层面又是怎么实现的呢?这是本篇文章着重想讨论的问题。
chengcheng222e
2021/11/04
7270
为什么 Spring和IDEA 都不推荐使用 @Autowired 注解
点击上方“芋道源码”,选择“设为星标” 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java 2021 超神之路,很肝~ 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络应用框架 Netty 源码解析 消息中间件 RocketMQ 源码解析 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析 作业调度中间件 Elastic-Job 源码解析 分布式事务中间件 TCC-Transaction
芋道源码
2022/09/07
4640
为什么 Spring和IDEA 都不推荐使用 @Autowired 注解
@Autowired注解到底怎么实现的,你能说清楚么?
使用spring开发时,进行配置主要有两种方式,一是xml的方式,二是java config的方式。
Java小咖秀
2021/07/12
6760
手写Spring的@Autowired注解
在使用Spring框架时,我们经常会用到@Autowired注解,也就是自动装配的意思。
Defu Li
2020/05/28
7650
让dubbo支持@Autowired注解
参考文章:http://dubbo.apache.org/zh-cn/docs/user/configuration/api.html
小贝壳
2020/03/05
4.1K0
Spring: @Autowired注解原理解析
AutowiredAnnotationBeanPostProcessor类是@Autowired的具体实现类
Freedom123
2024/03/29
1810
Spring: @Autowired注解原理解析
HttpServletRequest 使用@Autowired 注解会有问题吗?
SpringBoot 中,默认注入的对象是单例对象,那么,我们如果注入一个 HttpServletRequest,会有问题吗?因为每次请求,Request 是不同的,用一个单例去获取这个请求肯定是不对的。
水货程序员
2019/06/11
4.2K0
为什么Spring和IDEA不推荐使用@Autowired注解,有哪些替代方案?
在使用Spring框架和JetBrains IDEA集成开发环境(IDE)进行Java开发时,你可能经常会遇到@Autowired注解。@Autowired是Spring框架中用于实现依赖注入的核心注解之一。然而,近年来,Spring和IDEA都不再推荐使用@Autowired注解,并提出了更好的替代方案。本文将详细分析为什么Spring和IDEA不推荐使用@Autowired注解,并介绍这些替代方案。
网络技术联盟站
2023/07/03
1.5K0
为什么Spring和IDEA不推荐使用@Autowired注解,有哪些替代方案?
相关推荐
浅谈@Autowired注解shiyong
更多 >
LV.5
编程严选网软件架构师
目录
  • 01.场景描述
  • 02.准备环境
  • 03.提取内容
    • 1.提取金额
    • 2.提取名称
    • 3.提取纳税人识别号
    • 4.提取开票人
  • 04.批量识别发票并保存到excel
  • 05.发票验证真伪
    • 1.申请百度AI应用
    • 2.获取token
    • 3.查验
    • 4.税务局查询发票
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档