pdf_parser.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package import_service
  2. import (
  3. "fmt"
  4. "path/filepath"
  5. "strings"
  6. "github.com/ledongthuc/pdf"
  7. )
  8. // PDFParser PDF 解析器(纯 Go,使用 ledongthuc/pdf GetTextByRow 避免竖排)
  9. type PDFParser struct{}
  10. // NewPDFParser 创建 PDF 解析器
  11. func NewPDFParser() *PDFParser {
  12. return &PDFParser{}
  13. }
  14. // Supports 检查是否支持该文件
  15. func (p *PDFParser) Supports(filePath string) bool {
  16. return strings.HasSuffix(strings.ToLower(filePath), ".pdf")
  17. }
  18. // Parse 解析 PDF 文件(使用 GetTextByRow 按行分组,避免字符竖排)
  19. func (p *PDFParser) Parse(filePath string) (*ParsedDocument, error) {
  20. f, reader, err := pdf.Open(filePath)
  21. if err != nil {
  22. return nil, fmt.Errorf("打开 PDF 失败: %w", err)
  23. }
  24. defer f.Close()
  25. var allLines []string
  26. for pageNum := 1; pageNum <= reader.NumPage(); pageNum++ {
  27. page := reader.Page(pageNum)
  28. if page.V.IsNull() {
  29. continue
  30. }
  31. rows, err := page.GetTextByRow()
  32. if err != nil {
  33. continue
  34. }
  35. for _, row := range rows {
  36. var sb strings.Builder
  37. for _, t := range row.Content {
  38. sb.WriteString(t.S)
  39. }
  40. line := strings.TrimSpace(sb.String())
  41. if line != "" {
  42. allLines = append(allLines, line)
  43. }
  44. }
  45. }
  46. text := strings.Join(allLines, "\n")
  47. if strings.TrimSpace(text) == "" {
  48. return nil, fmt.Errorf("PDF 文件中未提取到文本内容")
  49. }
  50. title := strings.TrimSuffix(filepath.Base(filePath), filepath.Ext(filePath))
  51. return &ParsedDocument{
  52. Title: title,
  53. Content: text,
  54. Metadata: map[string]interface{}{"source": "pdf"},
  55. }, nil
  56. }