You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

批量提取PDF文本时,如何将表格置于对应位置?

批量提取PDF文本并精准放置表格的优化方案

以下是几种比文本匹配替换更高效的解决方案,无需手动匹配文本片段:

1. 基于tabulizer的坐标定位插入法

先通过可视化工具锁定表格的页面坐标,再按坐标对应位置将表格插入到整页文本中:

  • 用tabulizer::locate_areas(pdf_path)打开PDF可视化界面,手动框选表格区域,记录下每个表格的坐标(格式:c(左上角x, 左上角y, 右下角x, 右下角y))
  • 批量处理时,先提取整页文本,再根据坐标对应的页面位置,找到文本中的插入点(可通过表格前后的标志性文本或坐标估算位置),将提取的表格转为格式化文本后插入

示例代码:

library(tabulizer)
library(stringr)

# 遍历文件夹内所有PDF
pdf_files <- list.files(pattern = "\\.pdf$")

for (pdf in pdf_files) {
  # 预定义各页表格坐标(用locate_areas获取)
  table_areas <- list(
    1 = c(120, 60, 480, 560),
    3 = c(100, 80, 500, 590)
  )
  
  # 提取整页文本并按页拆分
  full_text <- extract_text(pdf)
  page_texts <- str_split(full_text, "\f")[[1]] # \f为PDF换页符
  
  # 逐页处理表格插入
  for (page_num in seq_along(page_texts)) {
    if (as.character(page_num) %in% names(table_areas)) {
      # 提取该页表格并转为制表符分隔的文本
      table_data <- extract_tables(pdf, pages = page_num, area = table_areas[[as.character(page_num)]])[[1]]
      table_text <- paste(apply(table_data, 1, paste, collapse = "\t"), collapse = "\n")
      
      # 示例:通过表格前的标志性文本定位插入点
      marker <- "以下为统计表格:"
      insert_pos <- str_locate(page_texts[page_num], marker)[2]
      if (!is.na(insert_pos)) {
        page_texts[page_num] <- str_replace(
          page_texts[page_num], 
          paste0("(", marker, ")"), 
          paste0("\\1\n\n", table_text, "\n\n")
        )
      }
    }
  }
  
  # 合并处理后的文本并保存
  final_text <- paste(page_texts, collapse = "\n\n")
  writeLines(final_text, gsub("\\.pdf$", "_processed.txt", pdf))
}

2. 基于pdftools的位置元数据拼接法

利用pdftools提取PDF中所有元素的位置信息,将文本块和表格按页面坐标排序后重新拼接,自动保持原页面布局:

  • 提取文本块的坐标和内容,同时提取表格的边界框和内容
  • 按页码、y轴坐标(PDF原点在左下角,需倒序排序)将文本块和表格重新排列,自动实现表格在原位置的插入

示例代码:

library(pdftools)
library(tabulizer)
library(dplyr)

process_single_pdf <- function(pdf_path) {
  # 提取每页的文本块及位置信息
  text_blocks <- pdf_data(pdf_path)
  
  # 提取表格数据及位置边界框
  tables <- extract_tables(pdf_path, output = "data.frame")
  table_locations <- extract_tables(pdf_path, output = "locations")[[1]]
  
  # 整理文本块为统一数据格式
  text_df <- bind_rows(lapply(text_blocks, function(page) {
    page %>%
      mutate(type = "text", page = unique(page$page)) %>%
      select(page, x, y, text, type)
  }))
  
  # 整理表格为统一数据格式,包含格式化后的表格文本
  table_df <- bind_rows(lapply(seq_along(tables), function(i) {
    bbox <- table_locations[i,]
    table_text <- paste(capture.output(print(tables[[i]])), collapse = "\n")
    tibble(
      page = as.integer(bbox["page"]),
      x = as.numeric(bbox["x1"]),
      y = as.numeric(bbox["top"]),
      text = table_text,
      type = "table"
    )
  }))
  
  # 合并文本与表格,按页码、y坐标倒序排序(还原页面从上到下的顺序)
  combined_df <- bind_rows(text_df, table_df) %>%
    arrange(page, desc(y))
  
  # 拼接内容,同一行的文本合并,表格单独换行分隔
  final_content <- ""
  current_page <- 1
  prev_y <- NULL
  
  for (row in split(combined_df, 1:nrow(combined_df))) {
    if (row$page != current_page) {
      final_content <- paste0(final_content, "\n\n--- 第", row$page, "页 ---\n\n")
      current_page <- row$page
      prev_y <- NULL
    }
    
    if (row$type == "table") {
      final_content <- paste0(final_content, "\n\n", row$text, "\n\n")
    } else {
      # 坐标相近的文本视为同一行,合并内容
      if (is.null(prev_y) || abs(row$y - prev_y) > 5) {
        final_content <- paste0(final_content, "\n", row$text)
        prev_y <- row$y
      } else {
        final_content <- paste0(final_content, " ", row$text)
      }
    }
  }
  
  return(final_content)
}

# 批量处理PDF
pdf_files <- list.files(pattern = "\\.pdf$")
for (pdf in pdf_files) {
  processed_content <- process_single_pdf(pdf)
  writeLines(processed_content, gsub("\\.pdf$", "_processed.txt", pdf))
}

3. 基于Camelot的流式提取法(Python)

Camelot的stream模式可保留表格的页面布局信息,结合PyPDF2提取的文本,直接将表格插入到对应位置:

  • 用Camelot提取表格并保留边界框,同时提取整页文本
  • 根据表格的页面位置,将表格的markdown格式文本插入到对应页面的文本中

示例代码:

import camelot
import PyPDF2
import os

def process_pdf(pdf_path):
    # 提取所有页面的表格(stream模式保留位置)
    tables = camelot.read_pdf(pdf_path, flavor='stream', pages='all')
    
    # 提取整页文本
    reader = PyPDF2.PdfReader(pdf_path)
    page_texts = [page.extract_text() for page in reader.pages]
    
    final_content = []
    for page_num, text in enumerate(page_texts, 1):
        # 筛选当前页的表格
        page_tables = [tbl for tbl in tables if tbl.page == page_num]
        for tbl in page_tables:
            # 将表格转为markdown格式
            table_markdown = tbl.df.to_markdown()
            # 示例:根据表格的y坐标估算插入位置,这里简化为在文本末尾添加
            # 实际可通过文本行的位置匹配更精准的插入点
            text += f"\n\n{table_markdown}\n\n"
        final_content.append(f"--- 第{page_num}页 ---\n\n{text}")
    
    return "\n\n".join(final_content)

# 批量处理文件夹内的PDF
pdf_files = [f for f in os.listdir('.') if f.endswith('.pdf')]
for pdf in pdf_files:
    content = process_pdf(pdf)
    with open(pdf.replace('.pdf', '_processed.txt'), 'w', encoding='utf-8') as f:
        f.write(content)

内容的提问来源于stack exchange,提问作者user760900

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 22:15:04