使用 R 中新的 Tesseract OCR 引擎将许多 .pdf 文件转换为 .txt 文件
Convert many .pdf files to .txt files using the new Tesseract OCR engine in R
我的主管要我将 .pdf
个文件转换为 .txt
个文件,以便通过关键字提取算法进行处理。 .pdf
文件是扫描的法庭文件。她基本上想要一个名为 court_document
的文件夹,其中包含每个子目录,每个子目录都命名为一个 13 个字符的案例 ID。我收到了大约 500 个 .pdf
个文件,文件名为“caseid_docketnumber_date_documentdescription.pdf”,例如“1-20-cr-30164_d2_5_23_2020_complaint.pdf”。她还希望每个 .txt
文件都保存为“docketnumber_date_documentdescription.txt”,例如“d2_5_23_2020_complaint.txt”。 .pdf
文件保存在我的工作目录 court_document
中。期望的结果是一个名为 court_document
的根目录,其中包含 500 个子目录,每个子目录包含 .txt
个文件。我按如下方式解决了这个问题:
# Packages ---------------------------------------------------------------
library(tesseract)
library(pdftools)
library(magrittr)
library(purrr)
library(bench)
# Function to convert .pdf to .txt ----------------------------------------
pdf_convert_txt <- function(pdf) {
# Case id
# The pdf file names are such that the first 13 characters are the case id's
case_id <- str_sub(
string = pdf,
start = 1L,
end = 13L
)
# File path for writing .txt file to subdirectory
txt_file_path <- paste0(
# Subdirectory
paste0(case_id, "/"),
# Ensure .txt file name does not include case id (first 14 char) and .pdf extension (last 4 char)
str_sub(
string = pdf,
start = 15L,
end = -5L
),
# File extension
".txt"
)
# Create subdirectory using case id as its name
if (dir.exits(paths = case_id) == FALSE) dir.create(path = case_id)
# Convert pdf to png
# This function creates one .png file per pdf page in current working dir
# It also returns a character vector of .png file names
pdf_convert(
pdf = pdf,
format = "png",
dpi = 200,
) %>%
# Pass the character vector of .png file names to tesseract::ocr()
# This function returns plain text by default
ocr(image = .) %>%
# Concatenate and save plain text .txt file to subdirectory created above
cat(file = txt_file_path)
# Remove all png files in current working directory
file.remove(
list.files(pattern = ".png")
)
}
# Apply pdf_convert_txt() to all .pdf files in current working dir -------------------
map(
# All .pdf files in current working directory court_document
.x = list.files(pattern = ".pdf"),
.f = pdf_convert_txt
)
此解决方案有效,但分析表明 ocr(image = .)
确实会降低代码速度。一份典型的法庭文件至少有 50 页,因此要从中提取文本的 50 个 png 文件。在我的 intel macbook pro 2020 上,仅这一行 运行 就需要大约 72000 毫秒。我只有这么多 .pdf
个文件,所以我想知道是否有任何方法可以突破这个瓶颈。或者我可能需要切换到其他工具。任何意见和建议将不胜感激。
根据 phiver 的建议和我自己的一些实验,我能够将以下代码块的 运行 时间减少大约 40%,甚至在使用多会话之前,我的典型 pdf 有 50 页:
pdf_convert(
pdf = pdf,
format = "png",
dpi = 80,
) %>%
ocr(image = .) %>%
cat(file = txt_file_path)
我通过在从 .pdf
转换为 .png
时降低分辨率(dpi 参数)来做到这一点。幸运的是,我正在处理的 .pdf
文件类型不需要高分辨率,OCR 引擎就可以从图像中提取字符。最后,为了使用多会话(parallelly::plan()
+ furrr::future_map()
),我在函数之外使用了以下块:
file.remove(
list.files(pattern = ".png")
)
由于我是运行宁并行进程,我需要取出上面的块,否则单个进程将删除工作目录中的所有 .png
文件,包括那些需要完成的文件其他进程。
我的主管要我将 .pdf
个文件转换为 .txt
个文件,以便通过关键字提取算法进行处理。 .pdf
文件是扫描的法庭文件。她基本上想要一个名为 court_document
的文件夹,其中包含每个子目录,每个子目录都命名为一个 13 个字符的案例 ID。我收到了大约 500 个 .pdf
个文件,文件名为“caseid_docketnumber_date_documentdescription.pdf”,例如“1-20-cr-30164_d2_5_23_2020_complaint.pdf”。她还希望每个 .txt
文件都保存为“docketnumber_date_documentdescription.txt”,例如“d2_5_23_2020_complaint.txt”。 .pdf
文件保存在我的工作目录 court_document
中。期望的结果是一个名为 court_document
的根目录,其中包含 500 个子目录,每个子目录包含 .txt
个文件。我按如下方式解决了这个问题:
# Packages ---------------------------------------------------------------
library(tesseract)
library(pdftools)
library(magrittr)
library(purrr)
library(bench)
# Function to convert .pdf to .txt ----------------------------------------
pdf_convert_txt <- function(pdf) {
# Case id
# The pdf file names are such that the first 13 characters are the case id's
case_id <- str_sub(
string = pdf,
start = 1L,
end = 13L
)
# File path for writing .txt file to subdirectory
txt_file_path <- paste0(
# Subdirectory
paste0(case_id, "/"),
# Ensure .txt file name does not include case id (first 14 char) and .pdf extension (last 4 char)
str_sub(
string = pdf,
start = 15L,
end = -5L
),
# File extension
".txt"
)
# Create subdirectory using case id as its name
if (dir.exits(paths = case_id) == FALSE) dir.create(path = case_id)
# Convert pdf to png
# This function creates one .png file per pdf page in current working dir
# It also returns a character vector of .png file names
pdf_convert(
pdf = pdf,
format = "png",
dpi = 200,
) %>%
# Pass the character vector of .png file names to tesseract::ocr()
# This function returns plain text by default
ocr(image = .) %>%
# Concatenate and save plain text .txt file to subdirectory created above
cat(file = txt_file_path)
# Remove all png files in current working directory
file.remove(
list.files(pattern = ".png")
)
}
# Apply pdf_convert_txt() to all .pdf files in current working dir -------------------
map(
# All .pdf files in current working directory court_document
.x = list.files(pattern = ".pdf"),
.f = pdf_convert_txt
)
此解决方案有效,但分析表明 ocr(image = .)
确实会降低代码速度。一份典型的法庭文件至少有 50 页,因此要从中提取文本的 50 个 png 文件。在我的 intel macbook pro 2020 上,仅这一行 运行 就需要大约 72000 毫秒。我只有这么多 .pdf
个文件,所以我想知道是否有任何方法可以突破这个瓶颈。或者我可能需要切换到其他工具。任何意见和建议将不胜感激。
根据 phiver 的建议和我自己的一些实验,我能够将以下代码块的 运行 时间减少大约 40%,甚至在使用多会话之前,我的典型 pdf 有 50 页:
pdf_convert(
pdf = pdf,
format = "png",
dpi = 80,
) %>%
ocr(image = .) %>%
cat(file = txt_file_path)
我通过在从 .pdf
转换为 .png
时降低分辨率(dpi 参数)来做到这一点。幸运的是,我正在处理的 .pdf
文件类型不需要高分辨率,OCR 引擎就可以从图像中提取字符。最后,为了使用多会话(parallelly::plan()
+ furrr::future_map()
),我在函数之外使用了以下块:
file.remove(
list.files(pattern = ".png")
)
由于我是运行宁并行进程,我需要取出上面的块,否则单个进程将删除工作目录中的所有 .png
文件,包括那些需要完成的文件其他进程。