R语言如何提取PDF指定区域文本并保存为数据框
固定区域PDF批量提取方案
你当前用pdf_text()直接提取整页文本的方式,遇到固定版式的批量提取需求很容易因为正文长度变化出现行号错位,最稳妥的实现方式是通过PDF原生坐标定位目标矩形区域提取,坐标仅需测量1次,所有同格式PDF通用,操作门槛低,适合千份级文件批量处理。
第一步:获取目标红框的精确坐标
PDF坐标以页面左下角为原点,单位为点(1英寸=72点),不用手动换算,直接通过内置函数读取所有文本块的坐标即可,比肉眼看图定位更准:
- 跑以下代码读取样例PDF第一页所有文本块的坐标和对应内容:
library(tidyverse) library(pdftools) library(here) # 读取第一页所有文本块坐标 first_page_text <- pdf_data(here("pdf_project/example_for_pdf.pdf"))[[1]] View(first_page_text) - 在弹出的表格里找到红框内的所有文本行,记录4个边界值:
- 所有红框文本最小的
x0值(区域左边界) - 所有红框文本最大的
x1值(区域右边界) - 所有红框文本最小的
y0值(区域下边界) - 所有红框文本最大的
y1值(区域上边界)
- 所有红框文本最小的
- 给4个值各留3个点的余量(左边界减3、右边界加3、下边界减3、上边界加3),避免切到文字边缘,这4个值就是后续提取要用的裁剪框参数。
第二步:编写单文件提取函数
用pdf_text()的cliprect参数可以直接提取指定矩形区域内的文本,不用再处理整页无关内容,函数会自动把提取到的内容清洗整理成结构化dataframe:
# 单文件提取函数 extract_pdf_target <- function(pdf_path, target_page, clip_box) { # 容错逻辑:遇到加密/损坏文件不会中断批量任务,会记录错误信息 tryCatch({ # 提取指定区域文本 area_raw <- pdf_text( pdf = pdf_path, pages = target_page, cliprect = clip_box # 传入之前测的裁剪框坐标 ) # 清洗文本:拆行、去多余空格、删空行 area_lines <- area_raw %>% str_split("\n") %>% unlist() %>% str_squish() %>% discard(~ .x == "") # 整理为dataframe,按两列及以上的连续空格拆分职位和人名(适配样例的对齐排版) df <- tibble(raw_content = area_lines) %>% separate( col = raw_content, into = c("position", "name"), # 列名可以根据实际提取的内容修改 sep = "\\s{2,}", # 按2个及以上连续空格拆分,不会拆坏字段内的单个空格 extra = "merge" ) %>% mutate(pdf_filename = basename(pdf_path), .before = 1) # 加文件名列区分来源 return(df) }, error = function(e) { # 出错时返回标记行 tibble( pdf_filename = basename(pdf_path), position = "提取失败", name = as.character(e) ) }) }
第三步:批量处理所有PDF
拿到所有PDF的文件路径后,循环调用上面的函数,直接合并成一个总dataframe即可:
# 1. 获取文件夹内所有PDF的完整路径 all_pdf <- list.files( path = here("pdf_project/"), # 替换成存所有PDF的文件夹路径 pattern = "\\.pdf$", # 仅识别PDF后缀文件 full.names = TRUE, recursive = FALSE # 如果PDF存在子文件夹里,把这个值改成TRUE ) # 2. 填入第一步测出来的裁剪框坐标!!! my_clip <- c( xleft = 48, # 替换成算好的左边界值 ybottom = 512,# 替换成算好的下边界值 xright = 295, # 替换成算好的右边界值 ytop = 578 # 替换成算好的上边界值 ) # 3. 批量提取,直接合并为最终的dataframe final_df <- map_dfr( .x = all_pdf, .f = ~extract_pdf_target( pdf_path = .x, target_page = 1, # 如果目标区域在其他页,改成对应页码即可 clip_box = my_clip ) )
常见问题调整
- 提取内容缺字:把裁剪框的四个边界再往外扩3-5个点,留足冗余即可
- 列拆分错位:如果字段结构不是「职位+人名」的形式,可以调整
separate的拆分规则,比如用正则匹配固定格式提取对应字段 - 个别PDF提取乱码:检查PDF是不是扫描版图片PDF,如果是扫描件需要先加OCR步骤,同版式的扫描件也可以用同样的坐标裁剪后做OCR,逻辑一致。
内容的提问来源于stack exchange,提问作者TarJae
相关产品推荐
相关产品推荐

