首页 > 其他分享 >Go 语言实现读取 pdf 文件内容

Go 语言实现读取 pdf 文件内容

时间:2023-12-29 11:55:39浏览次数:31  
标签:return 读取 err go tika Go pdf

本篇介绍一个如何在 go 语言环境下,如何解析/读取 pdf 文件内容从而进行一些业务逻辑。本篇将会介绍两种方案,可以按自己的需求进行对比和最终选择。

最近在帮朋友做一个小的程序,帮他减少一些人工繁琐的工作,将一些机器可以做的事情交给机器,提高效率他效率。

需求也相对简单,就是从大量 pdf/docx 文件内容中读取一些关键信息(这些信息有一定的规律),并输出一个 Excel 表格。听到这个需求我第一个想法是可以做的,我之前在一些招聘网站也是看过解析 pdf 内容的功能。最典型的就是在招聘网站上传个人简历时,会读出来个人信息以及其他信息。既然市面上有人这么干,那就说是肯定有一定的解决方案可以供我利用的。

接下来就是去找解决方案了,调研了一下午后,目标基本明确了。有两个项目进入了最终决赛圈,我需要分别使用,并把一些优缺点列出来就能确定最终胜者了。

这两个方案分别是:

  1. ledongthuc/pdf go语言实现的 pdf 解析库。有不少的 star 和 fork,并且从 demo 上看到确实能读取到内容。

  2. apache/tika Java 实现的 pdf 解析库。之所以能进入决赛圈是因为网上大量人推荐并且是 apache 的项目,所以我也比较放心使用。

首先对 ledongthuc/pdf 进行使用测试。先上代码:

 
package main

import (
    "bytes"
    "fmt"

    "github.com/ledongthuc/pdf"
)

func main() {
    pdf.DebugOn = true
    content, err := readPdf("test.pdf") // Read local pdf file
    if err != nil {
        panic(err)
    }
    fmt.Println(content)
    return
}

func readPdf(path string) (string, error) {
    f, r, err := pdf.Open(path)
    // remember close file
    defer f.Close()
    if err != nil {
        return "", err
    }
    var buf bytes.Buffer
    b, err := r.GetPlainText()
    if err != nil {
        return "", err
    }
    buf.ReadFrom(b)
    return buf.String(), nil
}

这是一段项目自己提供 demo,我本地确实也跑起来了。但是我当对一些我朋友提供的测试案例 pdf 文件进行解析时,遇到了问题,报了下面的错:

malformed PDF: reading at offset 0: stream not present

我第一反应是可能我的 pdf 不是很标准 pdf 格式导致,然后去项目 issue 里看到类似的问题,并且作者也给了解决方案,明显比较麻烦的一种解决方案。因为需要对文件进行一些处理,这个方案我不是很能接受。不过我找一些网上标准(所谓的标准就是去找了一些权威的网站上的 pdf 文件)的 pdf 文件的时候,的确能读出内容。这个方案我先标注为 backup, 实在没辙我再回来折腾。

apache/tika 是一个比较万能的工具集,其能力可以参考官方的说明。

apache/tika

Apache Tika - a content analysis toolkit

The Apache Tika™ toolkit detects and extracts metadata and text from over a thousand different file types (such as PPT, XLS, and PDF). All of these file types can be parsed through a single interface, making Tika useful for search engine indexing, content analysis, translation, and much more.

虽然说是Java 项目,我不能直接引入到我的 go 项目使用,但是人家提供了 API,这就非常的 nice 了。然后几乎同时我发现了 Google 的一个项目 go-tika, tika 的 go 语言版 client 端,也就是我不用去写调用 api 相关代码了,简直又省了我不少时间。

因为 tika 是个 server 端项目,那我得用的时候需要把他跑起来才行,但是我本地没有 Java 环境,我也不想去折腾(自己又不懂,瞎搞绝对浪费时间还搞不定)。所以我转向了万能的 docker 部署。找到 tika 的 docker 镜像,本地启动就可以用了。

 
$ docker run -d -p 9998:9998 apache/tika:latest

部署完事儿。

使用方面也是非常简单,有了 go-tika 项目的加成,我需要写的代码几乎很少,代码如下:

 
package main

import (
    "fmt"
    "flag"
    "context"
    "os"

    "github.com/google/go-tika/tika"
)

func main() {
    var filePath string
    flag.StringVar(&filePath, "fp", "", "pdf file path.")
    flag.Parse()
    if filePath == "" {
        panic("file path must be provided")
    }
    content, err := readPdf(filePath) // Read local pdf file
    if err != nil {
        panic(err)
    }
    fmt.Println(content)
    return
}

func readPdf(path string) (string, error) {
    f, err := os.Open(path)
    defer f.Close()
    if err != nil {
        return "", err
    }

    client := tika.NewClient(nil, "http://127.0.0.1:9998")
    return client.Parse(context.TODO(), f)
}

 

响应速度完全在可接受范围内(30ms 左右),而且更让我惊喜的是,之前在用 go 语言的库解析出错的 pdf 在这里完全没问题,没有漏掉一个字的给我解析出来了。可以说是完全达到我的要求了。

从我个人的需求上面来说 tika 是完胜的,但是速度上的确没有 ledongthuc/pdf 快,但是只是快并不能解决问题。ledongthuc/pdf 读取标准的 pdf 没问题,如果你的需求是读取一些标准的 pdf ,那 ledongthuc/pdf 绝对比 tika 好用的,又快又不需要搭建一个 server 端。

如果你遇到的 pdf 不能保证来源和质量,那 tika 更适合,读取内容的概率更高,我自己测了大概 100 来份各种 pdf,成功率也很高,除非是非常模糊的 pdf,否则都能读取到内容,而且延迟 30ms 对于一般需求来说是足够的。况且是 docker 部署的无状态服务,如果你要大量的 pdf 需要处理,那就多搭建几个 server 端同时处理就好了。

其他方面的对比 ,可以参考这篇文章:https://www.jianshu.com/p/68609f51b6e7 讲得比较细,感兴趣的可以去阅读。

如果你有不同的想法,那再评论区见吧~

标签:return,读取,err,go,tika,Go,pdf
From: https://www.cnblogs.com/siyunianhua/p/17934576.html

相关文章

  • nodejs学习05——mongoose
    简介Mongoose是一个对象文档模型库,官网http://www.mongoosejs.net/作用:方便使用代码操作mongodb数据库初体验//1.安装mongoose//2.导入mongooseconstmongoose=require('mongoose');//设置strictQuery为truemongoose.set('strictQuery',true);//3.连接......
  • Golang合并、通过逗号拆分字符串
    Golang开发常用函数将逗号分隔的字符串转换为数组,将数组slice转为逗号分隔的string字符串,以及strings的其他函数。一、Go开发中最常用函数1.将数组slice转为逗号分隔的string字符串strings.Join(a[]string,sepstring)string或者strings.Join(str_arr,",")示例代码:......
  • golang对map排序
    golang中map元素是随机无序的,所以在对maprange遍历的时候也是随机的,不像php中是按顺序。所以如果想按顺序取map中的值,可以采用以下方式:import("fmt""sort")funcmain(){m:=make(map[int]string)m[1]="a"m[2]="c"m[0]="b"......
  • SpringBoot中读取yml中配置的list对象的配置项
    场景SpringBoot中通过ConfigurationProperties注解的方式读取application.yml中配置的属性值:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108385148参考上面获取yml配置文件中简单的配置项的方式。如果需要获取application.yml中配置的list数据,且每个list有多......
  • go-carbon v2.3.1 发布,轻量级、语义化、对开发者友好的 Golang 时间处理库
    carbon是一个轻量级、语义化、对开发者友好的golang时间处理库,支持链式调用。目前已被awesome-go收录,如果您觉得不错,请给个star吧github.com/golang-module/carbongitee.com/golang-module/carbon安装使用Golang版本大于等于1.16//使用github库goget-ugithu......
  • Go语言变量类型
     一、基本类型1.数字型2.字符串3.布尔型二、派生类型指针、数组、切片、Map、结构体 三、数字类型1、整型int8、int16、int32、int64、uint8、uint16、uint32、uint642、浮点型float32、float643、复数型......
  • Vb.net 使用Webview2显示pdf文件
    使用webview2显示PDF文件需要wvliulanqi--Webview2控件的 AwaitWv2.EnsureCoreWebView2Async函数来启动浏览器否则会报错注意Div的宽度高度PrivateSubButton1_ClickAsync(senderAsObject,eAsEventArgs)HandlesButton1.ClickDimstrPathAs......
  • .NET 6 控制台程序(Console)读取配置appsettings.json配置文件
    ​ 1、添加引用Microsoft.Extensions.Configuration.Json添加引用 Microsoft.Extensions.Configuration.Json,引用方法可以参考:1)使用Nuget界面管理器搜索"Microsoft.Extensions.Configuration.Json"在列表中分别找到它,点击"安装"相关文档:VS(VisualStudio)中Nuget的使用......
  • Go 泛型之明确使用时机与泛型实现原理
    目录一、引入二、何时适合使用泛型?场景一:编写通用数据结构时场景二:函数操作的是Go原生的容器类型时场景三:不同类型实现一些方法的逻辑相同时三、Go泛型实现原理Stenciling方案Dictionaries方案Go最终采用的方案:GCShapeStenciling方案四、泛型对执行效率的影响五、小结一......
  • Go 泛型之泛型约束
    Go泛型之泛型约束目录Go泛型之泛型约束一、引入二、最宽松的约束:any三、支持比较操作的内置约束:comparable四、自定义约束五、类型集合(typeset)六、简化版的约束形式七、约束的类型推断八、小结一、引入虽然泛型是开发人员表达“通用代码”的一种重要方式,但这并不意味着所有......