【问题标题】:How to extract specific parts of messy PDFs in R?如何在 R 中提取杂乱 PDF 的特定部分?
【发布时间】:2020-11-26 20:02:27
【问题描述】:

我需要提取大量 PDF 文档的特定部分。 PDF 是包含各种数字、字母和其他信息的大而杂乱的报告。这些文件的长度不同,但它们之间具有统一的内容和部分。这些文档有一个目录,其中包含部分名称。例如

Table of Content:

Item 1. Business                                                                            1
Item 1A. Risk Factors                                                                       2
Item 1B. Unresolved Staff Comments                                                          5
Item 2. Properties                                                                          10
Item N........

..........text I do not care about...........

Item 1A. Risk Factors 

.....text I am interested in getting.......

(section ends)

Item 1B. Unresolved Staff Comments

..........text I do not care about...........

阅读它们并对其进行整体分析没有问题,但我只需要提取 "Item 1A. Risk Factors""Item 1B. Unresolved Staff 之间的文本评论”。 我使用了 pdftools、tm、quanteda 和 readtext 包 这是我用来读入文档的部分代码。我创建了一个放置我的 PDF 的目录并将其命名为“PDF”和另一个目录,R 将在其中放置转换为“.txt”文件的位置。

pdf_directory <- paste0(getwd(), "/PDF")
txt_directory <- paste0(getwd(), "/Texts")

然后我使用“list.files”函数创建一个文件列表。

files <- list.files(pdf_directory, pattern = ".pdf", recursive = FALSE, 
                    full.names = TRUE)
files

之后,我继续创建一个提取文件名的函数。

extract <- function(filename) {
  print(filename)
  try({
    text <- pdf_text(filename)
  })
  f <- gsub("(.*)/([^/]*).pdf", "\\2", filename)
  write(text, file.path(txt_directory, paste0(f, ".txt")))
}

for (file in files) {
  extract(file)
}

在这一步之后,我卡住了,不知道如何继续。我不确定在读取数据时是否应该尝试提取感兴趣的部分,因此,我想我将不得不与我创建函数的块搏斗——f &lt;- gsub("(.*)/([^/]*).pdf", "\\2", filename)?我为这些问题道歉,但我是在自学。 我还尝试在一个文件而不是语料库上使用以下代码:

start <- grep("^\\*\\*\\* ITEM 1A. RISK FACTORS", text_df$text) + 1

stop <- grep("^ITEM 1B. UNRESOLVED STAFF COMMENTS", text_df$text) - 1

lines <- raw[start:stop]

scd <- paste0(".*",start,"(.*)","\n",stop,".*")  
gsub(scd,"\\1", name_of_file)

但它对我没有任何帮助。

【问题讨论】:

标签: r pdf text nlp pdftools


【解决方案1】:

我真的不明白你为什么要先将文件写入 txt,所以我一口气完成了。

让我有点失望的是你的图案有很多额外的空间。你可以用正则表达式\\s+来匹配它们

library(stringr)
files <- c("https://corporate.exxonmobil.com/-/media/Global/Files/investor-relations/investor-relations-publications-archive/ExxonMobil-2016-Form-10-K.pdf",
           "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf")


relevant_l <- lapply(files, function(file) {
  
  # print status message
  message("processing: ", basename(file))
  
  lines <- unlist(stringr::str_split(pdftools::pdf_text(file), "\n"))
  start <- stringr::str_which(lines, "ITEM 1A.\\s+RISK FACTORS")
  end <- stringr::str_which(lines, "ITEM 1B.\\s+UNRESOLVED STAFF COMMENTS")
  
  # cover a few different outcomes depending on what was found
  if (length(start) == 1 & length(end) == 1) {
    relevant <- lines[start:end]
  } else if (length(start) == 0 | length(end) == 0) {
    relevant <- "Pattern not found"
  } else {
    relevant <- "Problems found"
  }
  
  return(relevant)
})
#> processing: ExxonMobil-2016-Form-10-K.pdf
#> processing: dummy.pdf

names(relevant_l) <- basename(files)
sapply(relevant_l, head)
#> $`ExxonMobil-2016-Form-10-K.pdf`
#> [1] "ITEM 1A.           RISK FACTORS\r"                                                                                                   
#> [2] "ExxonMobil’s financial and operating results are subject to a variety of risks inherent in the global oil, gas, and petrochemical\r" 
#> [3] "businesses. Many of these risk factors are not within the Company’s control and could adversely affect our business, our financial\r"
#> [4] "and operating results, or our financial condition. These risk factors include:\r"                                                    
#> [5] "Supply and Demand\r"                                                                                                                 
#> [6] "The oil, gas, and petrochemical businesses are fundamentally commodity businesses. This means ExxonMobil’s operations and\r"         
#> 
#> $dummy.pdf
#> [1] "Pattern not found"

我会将结果作为列表返回,然后使用原始文件名来命名列表元素。如果您有任何问题,请告诉我。我使用包stringr,因为它在处理字符串时快速且一致。但是命令str_whichgrep 几乎是一样的。

【讨论】:

  • 非常感谢您的帮助,@JBGruber。我很抱歉打扰,但在多个 PDF 上运行该代码时遇到了问题。我所做的是将文件的路径从链接更改为files &lt;- list.files("/Volumes/GoogleDrive/My Drive/R/Projects/Work package 2/Exxon/PDF/", pattern = "*.pdf$", full.names = TRUE)
  • 我收到一个错误:Error in file(con, "rb") : invalid 'description' argument
  • 你好。感谢您花费时间和精力帮助我解决这个问题。但是,我仍然无法在文件列表上运行该代码。它仅适用于一个文件。我得到Error in start:end : argument of length 0
  • 我认为这意味着您的模式没有找到。您可以使用 if 语句涵盖搜索的几种不同结果。检查我更新的答案。
  • @JBGruber 我认为这是一个很好的解决方案,尽管我不明白为什么它不适用于我的 PDF 集。没有错误;我加载了六个 PDF 文件,并分别运行这些行,确认 str_which() 命令返回有效信息。但是当我运行整个 lapply 函数时,我得到“发现问题”---为什么?
猜你喜欢
  • 2018-10-29
  • 1970-01-01
  • 2012-12-16
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
  • 2022-11-18
  • 1970-01-01
相关资源
最近更新 更多