Python提取PDF表格(基于AUTOSAR_SWS_CANDriver.pdf)

news2024/9/30 13:33:06

个人学习笔记,仅供参考。

需求:提取AUTOSAR SWS中所有的API接口信息,用于生成C代码。
此处以AUTOSAR_SWS_CANDriver.pdf为例,若需要提取多个SWS文件,遍历各个文件即可。

1.Python包

pdfplumber是一款完全用python开发的pdf解析库,对于线框完全的表格,pdfminer能给出比较好的抽取效果,但是对于线框不完全(包含无线框)的表格,其效果就差了不少。因为在实际项目所需处理的pdf文档中,线框完全及不完全的表格都比较多。
在这里插入图片描述
备注:安装时,可能会因为网络问题,导致pdfplumber安装失败,可以切换国内镜像进行安装,具体命令如下:

pip install pdfplumber -i http://pypi.douban.com/simple

其他国内源如下:

清华:https://pypi.tuna.tsinghua.edu.cn/simple
阿里云:http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
华中理工大学:http://pypi.hustunique.com/
山东理工大学:http://pypi.sdutlinux.org/

2.实现思路

目标表格
在这里插入图片描述
具体步骤
1、使用extract_tables解析当前page所有表格,判断一个单元格为“Service Name”(关键字)
2、若存在Service Name,将此表格的内容追加到总表
3、读取当前表的同时判断是否是完整的表格,如果不是,则继续读取下一页,在一起追加到总表
备注:第一个单元格不是“Service Name”,存在两种情况,一是非我们想要的表格,另一个是部分我们需要的,后者在步骤3中处理掉,所以无影响
参考代码

import pdfplumber

inputFile = "AUTOSAR_SWS_CANDriver.pdf"
functionList = []
# 前15页无有效信息,为提高效率,减少扫描页数
startPage = 15

def readPdfFile():
    global functionList
    table_settings = {
        "vertical_strategy": "lines",    # 对于完整的表格,vertical_strategy与horizontal_strategy都配置为lines
        "horizontal_strategy": "lines",
        "snap_y_tolerance": 10,          # y方向上较短的线条extract_tables也会识别为表格的边界,最后导致识别出错
                                         # 这里将最小像素点设置为10(小于10丢弃线条丢弃)
    }
    with pdfplumber.open(inputFile) as pdf:
        ########################################
        # 仅前期调试使用,具体使用时,可以屏蔽
        first_page = pdf.pages[63]  # 指定(63+1)页PDF内容
        im = first_page.to_image()  # 转换为image个数
        im.reset().debug_tablefinder(table_settings) # 将table_settings配置效果输出到图片方便观看
        im.save('xx.PNG', format="PNG", quantize=True, colors=256, bits=8)
        ########################################

        for j in range(len(pdf.pages) - startPage):
            page = pdf.pages[j + startPage]
            table = page.extract_tables(table_settings)
            for i in range(len(table)):   # 遍历所有表格
                row = table[i]
                if row[0][0] == 'Service Name':      # 找表头
                    tempList = row                   # 先复制已有的信息
                    if (i == (len(table)-1)) and (row[-1][0] != 'Available via'):  # 最后一个表,且缺少最后一行,继续读取下一页的第一个表
                        page1 = pdf.pages[j + startPage + 1]     # 继续读取下一页
                        table1 = page1.extract_tables(table_settings)
                        for table1_1 in table1[0]:        # 只需要读取第一个表格(其他的会在在下次循环中写入)
                            if table1_1[0] == '':         # 如果第一个表格的第一个参数为空,代表第一行的参数的补充,并不是新的参数,所以此处拼接上去
                                tempList[-1][1] += '\n' + table1_1[1]
                            else:                         # 如果不为空,代表是新参数,直接追加即可
                                tempList.append(table1_1)
                    functionList.append(tempList)         # 最后汇总到总表格内


if __name__ == '__main__':
    readPdfFile()
    for i in functionList:
        print(i)
    print('共%d个函数' % len(functionList))

3.输出结果

最终保存到全局列表functionList中,后续可根据各自的开发规范/要求输出相应的代码。
在这里插入图片描述

4. 配置说明

table_settings = {
        "vertical_strategy": "lines",    # 对于完整的表格,vertical_strategy与horizontal_strategy都配置为lines
        "horizontal_strategy": "lines",
        "snap_y_tolerance": 10,          # y方向上较短的线条extract_tables也会识别为表格的边界,最后导致识别出错
                                         # 这里将最小像素点设置为10(小于10丢弃线条丢弃)
    }

4.1 snap_y_tolerance默认值效果

这里可以发现识别了很多无效的边界进入,导致组成了很多多余的单元格,最终识别出错,或者无法识别
在这里插入图片描述
备注:四个正交连接的小圆圈框起来的区域认为是一个单元格,此处不是很明显,具体可以看下图

4.2 snap_y_tolerance配置为10效果

可以很明显看见,上面很多短的边界被忽略掉了。
在这里插入图片描述
备注:“Syntax”出个人了解不应该识别出来,但是此处任然识别出来了,可能因为左侧的两点未连接,所以不影响最终结果,此处未进行深入研究,知道的小伙伴,欢迎讨论

5. 参考资料

1、https://zhuanlan.zhihu.com/p/352722932
2、https://github.com/jsvine/pdfplumber#visual-debugging
3、https://github.com/jsvine/pdfplumber/blob/stable/examples/notebooks/extract-table-nics.ipynb
4、https://zhuanlan.zhihu.com/p/100460222
5、https://zhuanlan.zhihu.com/p/100462752
6、https://zhuanlan.zhihu.com/p/100464246

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql解决随机选取问题

常规的随机选取效率差的原因: 两种解决方法: 总结:

VUE语法--img图片不显示/img的src动态赋值图片显示

1、问题概述 常见情景1:在VUE中使用img显示图片的时候,通过传参的方式传入图片的路径和名称,VUE不加载本地资源而是通过http://localhost:8080/...的地址去加载网络资源,从而出现了图片无法显示的情况。 常见情景2:针…

C#使用WebSocket进行链接

C#使用WebSocket进行网络链接,和服务端搭建一个长连接进行通信。 有两种方式:串口方式(SerialPort)和网口方式(Socket 包括:TcpClient和UdpClient) 准备: 1.C#使用WebSocket的一种…

【vue_3】关于超链接的问题

1、需求2、修改前的代码3、修改之后(1)第一次(2)第二次(3)第三次(4)第四次(5)第五次 1、需求 需求:要给没有超链接的列表添加软超链接 2、修改前…

4.Spring源码解析-loadBeanDefinitions(XmlBeanDefinitionReader)

第一个点进去 发现是空 肯定走的第二个逻辑了 这里在这里已经给属性设置了值,所以肯定不是空能拿到。 1.ClassPathXmlApplicationContext 总结:该loadBeanDefinitions是XmlBeanDefinitionReader设置xml文件在哪。

4D雷达目标检测跟踪算法设计

1.算法流程 4D雷达点云跟踪处理沿用3D毫米波雷达的处理流程,如下图: 从接收到点云开始,先对点云做标定、坐标转换、噪点剔除、动静分离,再分别对动态目标和静态目标做聚类,然后根据聚类结果做目标的特征分析和检测等&a…

Linux - 动静态库(上篇)

Linux 当中的 内存管理模块 不管是操作系统对于进程之间的管理,还是 对于文件的访问和修改等等的操作,都是要把数据加载到内存当中的,所以,所有的工作都离不开 内存管理模块。 内存的本质其实是对数据的一种临时存储&#xff0c…

Linux shell for jar test

Linux shell 脚本,循环解析命令行传入的所有参数,并按照不同的传参实现对不同的 java jar文件 进行测试执行。 [rootlocalhost demo]# cat connTest.sh #!/bin/bash# Linux shell for qftool java jar test# modes DEFAULT_MODE2jarfiles[1]common-1.0…

Redis 两种持久化方式 AOF 和 RDB

目录 一、Redis 的持久化 二、Redis 的持久化方式 RDB RDB 介绍 RDB 的触发方式:. 三、RDB的文件生成策略 四、Save 和 Bgsave 命令的区别 六、RDB 最佳配置 七、触发机制-不容忽略方式 AOF 一、AOF介绍 二、RDB所存在的问题 三、AOF 三种策略 四、AOF…

linux zsh终端美化

目前的centos系统默认的shell还是bash,但是zsh被称为终极shell,国外有个程序员开发出了一个能够让你快速上手的zsh项目,叫做「oh my zsh」,Github 网址是:https://github.com/robbyrussell/oh-my-zsh 有了这玩意zsh用起…

vue3中的动态component组件

is属性来指定要渲染的组件(填写组件名&#xff09; 多个子组件通过component标签挂载在同一个父组件中&#xff0c; 可以修改is属性进行动态切换组件。 可以搭配<keep-alive></keep-alive>使用。 父组件代码&#xff1a; <template><div style"fon…

Linux系统下查询指定网卡的型号及用途

接到应用侧的特殊要求&#xff0c;需要查询服务器上特定网口的物理型号及配置用途&#xff0c;发现没有一条现成指令可以完成此事。经测试&#xff0c;可按以下步骤执行3条命令来组合完成。 一、使用lspci命令来查询指定网卡的型号 按照以下步骤进行操作&#xff1a; 打开终…

基于振弦式轴力计和采集仪的安全监测解决方案

基于振弦式轴力计和采集仪的安全监测解决方案 振弦式轴力计是一种测量结构物轴向力的设备&#xff0c;通过测量结构物上的振弦振幅变化&#xff0c;可以确定结构物轴向力的大小。采集仪是一种用于采集和存储传感器数据的设备&#xff0c;通常与振弦式轴力计一起使用&#xff0c…

【无标题】【教3妹学编程-算法题】设计前中后队列

3妹&#xff1a;好冷啊&#xff0c; 冻得瑟瑟发抖啦 2哥 : 又一波寒潮来袭&#xff0c; 外面风吹的呼呼的。 3妹&#xff1a;今天还有雨&#xff0c;2哥上班记得带伞。 2哥 : 好的 3妹&#xff1a;哼&#xff0c;不喜欢冬天&#xff0c;也不喜欢下雨天&#xff0c;要是我会咒语…

FPGA模块——DA转换模块(AD9708类)

FPGA模块——DA转换模块&#xff08;AD9708类&#xff09; AD9708/3PD9708代码 AD9708/3PD9708 由于电路接了反相器&#xff0c;所以对应就不一样了。 电路图&#xff1a; 代码 在ROM中存入要输出的波形数据&#xff1a; 用软件生成各个对应的点。 给DA转换器一个时钟&…

JAVA配置jdk17 Graa1VM

按照网上内容下载好对应的jdk17版本的Graa1VM&#xff0c; 解压后&#xff0c;修改环境变量中的JAVA_HOME为当前的目录&#xff0c;例如 D:\ruanjian\jdk\gra_jdk17\graalvm-ce-java17-22.3.0 。 然后在命令行中输入java -version的时候&#xff0c; 返回的并不是 Graa1VM 相关…

java导入数据代码示例

1. 导入所需的库 java import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.Proxy; import org.openqa.selenium.chrome.ChromeOptio…

1146:吃糖果(C语言)

题目描述 HOHO&#xff0c;终于从Speakless手上赢走了所有的糖果&#xff0c;是Gardon吃糖果时有个特殊的癖好&#xff0c;就是不喜欢连续两次吃一样的糖果&#xff0c;喜欢先吃一颗A种类的糖果&#xff0c;下一次换一种口味&#xff0c;吃一颗B种类的糖果&#xff0c;这样&…

振南技术干货集:znFAT 硬刚日本的 FATFS 历险记(5)

注解目录 1、znFAT 的起源 1.1 源于论坛 &#xff08;那是一个论坛文化兴盛的年代。网友 DIY SDMP3 播放器激起了我的兴趣。&#xff09; 1.2 硬盘 MP3 推了我一把 &#xff08;“坤哥”的硬盘 MP3 播放器&#xff0c;让我深陷 FAT 文件系统不能自拔。&#xff09; 1.3 我…

VQ一下Key,Transformer的复杂度就变成线性了

©PaperWeekly 原创 作者 | 苏剑林 单位 | 月之暗面 研究方向 | NLP、神经网络 Efficient Transformer&#xff0c;泛指一切致力于降低 Transformer 的二次复杂度的工作&#xff0c;开始特指针对 Attention 的改进&#xff0c;后来更一般的思路&#xff0c;如傅立叶变换、…