(连载1.2)招股说明书提取报表的可行方法

背景说明

承接上一篇用直接从pdf提取的博文,运行后发现pdf文件处理时间过长且有些文件提取错误。
各公司文本内容形式和文件格式的可转化性各不相同,同一代码外推适用性较差。
改进思路:用acrobat的pdf格式转换是最佳选择。结合使用按键精灵脚本,依次用home,end,pageup,pagedown作为快捷键调用,每个pdf分五六步人工半自动操作对报表部分进行页面提取单独保存。运用按键精灵全自动操作将pdf通过acrobat转化为word文档。
对word文档进行代码转换的效率比较高,流程上有以下注意点:
1、对无法识别单位的表格设置跳过并报错
2、将转化成功的文件删除便于对检查剩下失败文件的具体情况,所以要做好备份
3、openpyxl,docx的运用方法延续了(连载)加强版Python提取上市公司年报报告中财务报表
4、相对于3中文章的改进之处是运用了表尾文本匹配辅助识别,参考[从招股说明书pdf文件中批量提取财务报表数据]注意上一篇文章没有考虑表内换行的情况
(https://blog.csdn.net/qq_37639139/article/details/121871651)
5、没有处理成功的表格:一类是本身报表不是很标准,另一类是格式转化时文本发生了变化,只有10份左右,可以手动补全。
6、文件名:页面提取自-代码_年份+其他后缀.docx
例如“页面提取自-688001_20190619_1.docx”

算法精炼过程

做了几个测试的脚本来检测转化出错的文件
然后观察这些文件每行第一项的特征用来完善识别条件
由于数据处理不需要非常标准的科目名称,完全可以用代码直接修改统一格式便于条件判断(这里被不知名的特殊空格恶心了一下)
仍然有两张表表头因为格式原因不能使用全等判断,没有找到原因
条件完善以后,除了转化局部乱码以及丢失表头需要直接修改源文件以外,其他意外同时出现的概率非常微乎其微,手工排查的成本降到了可以接受的水平。

代码实现

import os
import docx as d
import openpyxl as o
import re
input_path=r'C:\Users\huang\Desktop\word表 - 副本'
output_path=r'C:\Users\huang\Desktop\手工整理表单'
tle=['资产负债表','利润表','现金流量表']
os.chdir(input_path)
def tab_doc(file,order,output=output_path):
    with open(file, 'rb') as f:
        print('正在处理: ', file)
        doc = d.Document(f)
        typ = 0
        f1 = 0
        f2 = 0
        f3=0
        for dd in doc.paragraphs:
            if dd.text.find('单位') != -1:
                f3=1
            if dd.text.find('负债表') != -1:
                f1 = 1
            if dd.text.find('利润表') != -1 and f3==1:
                f2 = 1
            if f1 == 1 and f2 == 0:
                if dd.text.find('万元') != -1:
                    typ = 2
                else:
                    if dd.text.find('元') != -1:
                        typ = 1
        if typ == 0:
            print(order,"、"+file+" type is wrong!")
            return 0
        mywb = o.Workbook()
        tabs = doc.tables
        flag = 1
        sign = 0
        j = 1
        for tab in tabs:
            rows = tab.rows
            for row in rows:
                i = 65
                cells = row.cells
                if flag <= 3:
                    head=cells[0].text
                    head=head.replace("\n", '')
                    head = head.replace(" ", '')
                    # 半角空格
                    head = head.replace('   ', '')
                    # tab空格
                    head = head.replace(' ', '')
                    # 试了全角空格还是没去掉
                    head = head.replace('	', '')
                    # 没错,这是屏幕输出复制过来的神秘空格
                    head = head.replace("和", '及')
                    head = head.replace("合计", '总计')
                    head = head.replace("股东", '所有者')
                    for h in ["项目",'科目','资产']:
                    #这一步的判断出错会缺表,有两张表头含有未知的格式内容
                        if (head.find(h)!=-1) and (j == 1):
                            mywb.create_sheet(index=flag, title=tle[flag - 1])
                            mysheet = mywb[tle[flag - 1]]
                            for cell in cells:
                                c = cell.text
                                tmp = chr(i) + str(j)
                                mysheet[tmp] = c
                                i = i + 1
                            j = j + 1
                            break

                    if head not in ["项目","科目","资产","负债","负债及所有者权益"]  and j > 1 :
                        # print("find")
                        if typ == 1:
                            for cell in cells:
                                c = cell.text
                                if i > 65:
                                    if type(c) is type('a'):
                                        c = c.replace("\n", '')
                                        ResSearch = re.search(",", c)
                                        if ResSearch != None:
                                            c = c.replace(",", '')
                                        cc = c.replace(".", '')
                                        if cc.isdigit():
                                            c = float(c)

                                tmp = chr(i) + str(j)
                                mysheet[tmp] = c
                                i = i + 1
                            j = j + 1
                        else:
                            if typ == 2:
                                for cell in cells:
                                    c = cell.text
                                    if i > 65:
                                        if type(c) is type('a'):
                                            ResSearch = re.search(",", c)
                                            c = c.replace("\n", '')
                                            if ResSearch != None:
                                                c = c.replace(",", '')
                                            ResSearch = re.search(".", c)
                                            if ResSearch != None:
                                                c = c.replace(".", '') + '00'
                                        cc=c.replace(".", '')
                                        if cc.isdigit():
                                            c = float(c)
                                    tmp = chr(i) + str(j)
                                    mysheet[tmp] = c
                                    i = i + 1
                                j = j + 1
                else:
                    break#注意这里被转化的不是只有一张大表
                if flag == 3 and (head.find('期末现金') != -1 or head.find('年末现金') != -1):
                    flag = 4
                    j = 1
                else:
                    if flag == 2 and (head.find('净利润') != -1 or head.find('净亏损') != -1):
                        flag = 3
                        j=1
                    else:
                        if flag == 1  and head.find('权益') != -1 and head.find('总')!=-1 :
                            flag = 2
                            j = 1
        mywb.save(output + "\\" + file[6:17] + ".xlsx")
        print(order,"、"+file[6:17] + ".xlsx" + ' is done, type is', typ)
    os.remove(file)
oo=1
for file in os.listdir():
    if os.path.splitext(file)[1] == '.docx'and file[0]=="页":
        tab_doc(file,oo)
        oo=oo+1


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无敌的前任

您的支持将使我的探索更进一步

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值