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

在R中将扫描版PDF转为可搜索PDF并提取表格的方法

扫描版PDF表格提取与R数据清洗方案

一、将扫描PDF转为可搜索PDF(OCR处理)

扫描版PDF本质是图片集合,必须先做光学字符识别(OCR)转成可搜索文本后,才能用tabulizer提取表格。用R的tesseract+pdftools组合可以完成全流程处理:

# 安装依赖包
install.packages(c("pdftools", "tesseract", "magick"))
library(pdftools)
library(tesseract)
library(magick)

# 下载对应语言包(中文用"chi_sim",英文用"eng")
tesseract_download("chi_sim")
ocr_engine <- tesseract("chi_sim")

# 把扫描PDF转成单页图片(高dpi提升识别准确率)
pdf_images <- pdf_convert("你的扫描文件.pdf", format = "png", dpi = 300)

# 逐页做OCR并生成可搜索PDF页
lapply(pdf_images, function(img_path) {
  img <- image_read(img_path)
  ocr_text <- ocr(img, engine = ocr_engine)
  # 生成单页可搜索PDF模板
  pdf_content <- sprintf(
    "%PDF-1.4\n1 0 obj\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 3 0 R >>\nendobj\n2 0 obj\n<< /Type /Pages /Kids [1 0 R] /Count 1 >>\nendobj\n3 0 obj\n<< /Length %d >>\nstream\nBT /F1 12 Tf 50 750 Td (%s) Tj ET\nendstream\nendobj\nxref\n0 4\n0000000000 65535 f \n0000000010 00000 n \n0000000100 00000 n \n0000000200 00000 n \ntrailer\n<< /Size 4 /Root 2 0 R >>\nstartxref\n300\n%%EOF",
    nchar(ocr_text), ocr_text
  )
  writeLines(pdf_content, paste0("temp_page_", basename(img_path), ".pdf"))
})

# 合并所有临时PDF成最终可搜索文件
pdf_combine(list.files(pattern = "temp_page_.*\\.pdf"), output = "可搜索版表格.pdf")

# 清理临时文件
file.remove(pdf_images)
file.remove(list.files(pattern = "temp_page_.*\\.pdf"))

生成可搜索PDF后,再用tabulizer::extract_tables()提取表格,根据表格类型调整lattice = TRUE(线框表格)或stream = TRUE(无框表格)参数。

二、直接提取扫描PDF表格的替代方案

如果转可搜索PDF后提取效果仍不理想,可以跳过转PDF步骤,直接对图片OCR后用R工具整理数据:

  1. 固定宽度表格用read.fwf()快速拆分
    若表格列宽固定,先观察每行文本的列分隔位置,用固定宽度读取:
# 假设你已有OCR后的原始文本字符对象
raw_text <- readLines("ocr_result.txt") # 或直接用你现有的字符对象

# 定义各列宽度(根据实际表格调整)
col_widths <- c(12, 18, 15, 20, -1) # -1表示剩余部分归最后一列
df <- read.fwf(textConnection(raw_text), widths = col_widths, strip.white = TRUE)

# 设置列名
colnames(df) <- c("列名1", "列名2", "列名3", "列名4", "列名5")
  1. 用正则表达式拆分不规则文本
    如果列宽不固定但有规律(比如多空格分隔),用dplyr+stringr拆分:
library(dplyr)
library(stringr)

df <- tibble(raw_line = raw_text) %>%
  filter(raw_line != "") %>% # 过滤空行
  mutate(
    列1 = str_extract(raw_line, "^[^\\s]+"), # 提取第一个空格前内容
    列2 = str_extract(raw_line, "(?<=^\\S+\\s).+?(?=\\s{2,})"), # 提取连续两个空格前内容
    列3 = str_extract(raw_line, "(?<=\\s{2,}).+?(?=\\s{2,})"),
    列4 = str_extract(raw_line, "(?<=\\s{2,}).*")
  ) %>%
  select(-raw_line) %>%
  mutate(across(everything(), str_trim)) # 去除多余空格
  1. 精准裁剪表格区域OCR
    若页面包含多余内容,先裁剪图片到表格区域再识别,提升准确率:
img <- image_read(pdf_images[1]) # 取第一页图片
# 裁剪格式:"宽度x高度+左偏移+上偏移",根据实际表格位置调整
cropped_img <- image_crop(img, "500x600+80+150")
table_text <- ocr(cropped_img, engine = ocr_engine)

三、处理已有的错乱字符对象

你目前拿到的错乱字符对象,先按换行拆分成向量:text_lines <- str_split(raw_char, "\n")[[1]],再按以下步骤处理:

  • 过滤空行和无关说明行;
  • 观察每行的重复结构,比如列之间的空格数、固定分隔符号;
  • 用上面的read.fwf()或正则方法拆分列,再逐步清洗异常值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:01:14