Golang PDF文件转换问题求助

Golang PDF文件转换问题求助 我需要帮助转换一个PDF文件。转换可以从PDF转为txt,也可以从PDF转为json。这些PDF文件将始终遵循一套固定的文本位置和内容模式。

2 回复

PDF转文本并非易事。尽管存在pdf2txt工具,但它依赖于PDF中嵌入的文本信息。

在最坏的情况下,您可能需要使用OCR软件从像素数据中提取文本。

更多关于Golang PDF文件转换问题求助的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


对于遵循固定模式的PDF文件转换,推荐使用unipdf库进行文本提取和结构化处理。以下是两种转换方式的实现示例:

1. PDF转TXT(提取所有文本)

package main

import (
    "fmt"
    "os"
    "github.com/unidoc/unipdf/v3/extractor"
    "github.com/unidoc/unipdf/v3/model"
)

func pdfToTxt(inputPath, outputPath string) error {
    f, err := os.Open(inputPath)
    if err != nil {
        return err
    }
    defer f.Close()

    pdfReader, err := model.NewPdfReader(f)
    if err != nil {
        return err
    }

    numPages, err := pdfReader.GetNumPages()
    if err != nil {
        return err
    }

    outputFile, err := os.Create(outputPath)
    if err != nil {
        return err
    }
    defer outputFile.Close()

    for i := 1; i <= numPages; i++ {
        page, err := pdfReader.GetPage(i)
        if err != nil {
            return err
        }

        ex, err := extractor.New(page)
        if err != nil {
            return err
        }

        text, err := ex.ExtractText()
        if err != nil {
            return err
        }

        fmt.Fprintf(outputFile, "=== Page %d ===\n%s\n", i, text)
    }

    return nil
}

func main() {
    err := pdfToTxt("input.pdf", "output.txt")
    if err != nil {
        panic(err)
    }
}

2. PDF转JSON(基于固定模式解析)

package main

import (
    "encoding/json"
    "fmt"
    "os"
    "regexp"
    "strings"
    "github.com/unidoc/unipdf/v3/extractor"
    "github.com/unidoc/unipdf/v3/model"
)

type DocumentData struct {
    Title     string            `json:"title"`
    Author    string            `json:"author"`
    Sections  []Section         `json:"sections"`
    Metadata  map[string]string `json:"metadata"`
}

type Section struct {
    Header  string `json:"header"`
    Content string `json:"content"`
}

func pdfToJson(inputPath, outputPath string) error {
    f, err := os.Open(inputPath)
    if err != nil {
        return err
    }
    defer f.Close()

    pdfReader, err := model.NewPdfReader(f)
    if err != nil {
        return err
    }

    // 提取所有文本
    var fullText strings.Builder
    numPages, _ := pdfReader.GetNumPages()
    
    for i := 1; i <= numPages; i++ {
        page, err := pdfReader.GetPage(i)
        if err != nil {
            continue
        }

        ex, err := extractor.New(page)
        if err != nil {
            continue
        }

        text, err := ex.ExtractText()
        if err != nil {
            continue
        }

        fullText.WriteString(text + "\n")
    }

    // 根据固定模式解析文本
    docData := parseFixedPattern(fullText.String())

    // 转换为JSON
    jsonData, err := json.MarshalIndent(docData, "", "  ")
    if err != nil {
        return err
    }

    return os.WriteFile(outputPath, jsonData, 0644)
}

func parseFixedPattern(text string) DocumentData {
    data := DocumentData{
        Metadata: make(map[string]string),
    }

    // 示例:提取标题(假设标题在第一行)
    lines := strings.Split(text, "\n")
    if len(lines) > 0 {
        data.Title = strings.TrimSpace(lines[0])
    }

    // 示例:使用正则表达式提取特定模式
    // 假设作者信息格式为 "Author: 姓名"
    authorRe := regexp.MustCompile(`Author:\s*(.+)`)
    if matches := authorRe.FindStringSubmatch(text); len(matches) > 1 {
        data.Author = matches[1]
    }

    // 示例:提取章节(假设章节以"## "开头)
    sectionRe := regexp.MustCompile(`##\s+(.+?)\n(.+?)(?=##|$)`)
    matches := sectionRe.FindAllStringSubmatch(text, -1)
    
    for _, match := range matches {
        if len(match) >= 3 {
            section := Section{
                Header:  strings.TrimSpace(match[1]),
                Content: strings.TrimSpace(match[2]),
            }
            data.Sections = append(data.Sections, section)
        }
    }

    // 提取其他元数据(假设格式为"Key: Value")
    metaRe := regexp.MustCompile(`(\w+):\s*(.+)`)
    allMeta := metaRe.FindAllStringSubmatch(text, -1)
    
    for _, meta := range allMeta {
        if len(meta) >= 3 && meta[1] != "Author" {
            data.Metadata[meta[1]] = meta[2]
        }
    }

    return data
}

func main() {
    err := pdfToJson("input.pdf", "output.json")
    if err != nil {
        panic(err)
    }
}

3. 安装依赖

go get github.com/unidoc/unipdf/v3

4. 针对固定模式的优化建议

如果PDF有严格的固定格式,可以更精确地提取:

func extractByCoordinates(pdfReader *model.PdfReader) map[string]string {
    // 使用文本位置信息提取
    // 需要根据实际PDF的文本位置调整坐标
    result := make(map[string]string)
    
    // 示例:提取特定区域的文本
    // 假设标题在 (50, 750) 到 (400, 800) 的矩形区域内
    // 实际实现需要使用更精确的文本定位
    
    return result
}

关键点:

  1. unipdf提供了强大的文本提取功能
  2. 对于固定模式的PDF,结合正则表达式可以准确提取结构化数据
  3. 如果PDF包含表格或复杂布局,可能需要使用unipdfTextMark功能获取精确位置信息

根据PDF的具体模式调整正则表达式和解析逻辑即可实现准确的转换。

回到顶部