【问题标题】:How to extract sections of specific text from PDF files into R data frames? Complex如何将 PDF 文件中的特定文本部分提取到 R 数据框中?复杂的
【发布时间】:2018-10-29 04:27:17
【问题描述】:

如有任何建议,我们将不胜感激。这对时间很敏感。我有大部分是文本块的 PDF 报告。它们是长篇报告(约 50-100 页)。我正在尝试编写一个能够使用开始/停止位置字符串提取这些 PDF 报告的特定部分的 R 脚本。注意:报告的长度各不相同。简短的例子:

DOCUMENT TITLE
01. SECTION 1
This is a test section that I DONT want to extract. 
This text would normally be much longer... Over 100 words.
Sample Text Text Text Text Text Text Text Text

02. SECTION 2
This is a test section that I do want to extract. 
This text would normally be much longer... Over 100 words.
Sample Text Text Text Text Text Text Text Text
...

11. SECTION 11
This is a test section that I do want to extract. 
This text would normally be much longer... Over 100 words.
Sample Text Text Text Text Text Text Text Text
...

12. SECTION 12
This is a test section that I DONT want to extract. 
This text would normally be much longer... Over 100 words.
Sample Text Text Text Text Text Text Text Text
...

因此,此示例中的目标是提取第 2 节下方的段落并将其存储为字段/数据点。我还想将第 11 节存储为字段/数据点。 请注意文档为 PDF 格式

我已经尝试过使用 pdftools、tm、stringr,我确实花了 20 多个小时来寻找有关如何执行此操作的解决方案和教程。我知道这是可能的,因为我以前使用 SAS 做过......

请看下面的代码,我添加了带有问题的 cmets。我相信 RegEx 将成为解决方案的一部分,但我很迷茫。

# Init Step
libs <- c("tm","class","stringr","testthat",
          "pdftools")
lapply(libs, require, character.only= TRUE)


# File name & location
filename = "~/pdf_test/test.pdf"

# converting PDF to text
textFile <- pdf_text(filename) 

cat(textFile[1]) # Text of pg. 1 of PDF
cat(textFile[2]) # Text of pg. 2 of PDF

# I'm at a loss of how to parse the values I want. I have seen things 
  like:

sectionxyz <- str_extract_all(textFile, #??? )

rm_between()

# 1) How do I loop through each page of PDF file?
# 2) How do I identify start/stop positions for section to be extracted?
# 3) How do I add logic to extract text between start/stop positions
#    and then add the result to a data field?
# 4) Sections in PDF will be long sections of text (i.e. 100+ words into a field)

新-----

所以我已经能够: - 正确准备文档 - 识别正确的开始/停止模式:

length(grep("^11\\. LIMITS OF LIABILITY( +){1}$",source_main2)) length(grep("Applicable\\s+[Ll]imits\\s+[Oo]f",source_main2))

pat_st_lol <- "^11\\. LIMITS OF LIABILITY( +){1}$" pat_ed_lol <- "Applicable\\s+[Ll]imits\\s+[Oo]f"

length(grep()) 语句验证仅找到 1 个实例。从这里开始,我有点迷失了如何使用 gsub 或类似方法来提取我想要的数据部分。我试过了:

pat <- paste0(".*",pat_st_lol,"(.*)",pat_ed_lol,".*") test <- gsub(".*^11\\. LIMITS OF LIABILITY( +){1}$(.*)\n", "Applicable\\s+[Ll]imits\\s+[Oo]f", source_main2) test2 <-gsub(".*pat_st_lol(.*)\npat_ed_lol.*")

到目前为止,进展不大,但无论如何都有进展。

【问题讨论】:

  • 在将 pdf 转换为文本时,我尝试了多种方法......但是文本只是在 RStudio 中存储为“值”。我真的需要能够识别开始POSITION(从哪里开始提取字符串)--> START EXTRACTING STRING INTO DATAFRAME --> IDENTIFY END POSITION(从哪里停止提取字符串)

标签: r regex text-extraction data-extraction


【解决方案1】:

如果您可以系统地识别您需要的部分,您可以按照您的指示使用正则表达式来提取您想要的文本。

在你上面的例子中,像gsub(".*SECTION 11(.*)\n12\\..*","\\1",string) 这样的东西应该可以工作。

现在您可以使用paste 动态定义模式并遍历所有文件。然后可以将每个结果保存在您的 data.frame, list,... 中。


这里有一个简要更详细的模式解释:

  • 首先,.* 是匹配“任何东西”的方式。如果要匹配数字,可以使用 \\d 或等效的 [0-9]Here 是 R 中 Regex 的简短介绍(我发现它非常有用),您可以在其中找到几个字符类。
  • .*在图案的边缘表示可以在之前/之后有文字
  • (.*) 表示我们想要的内容(所以这里匹配任何内容为.* 使用)。基本上它意味着在SECTION 1112.之间提取“任何东西”
  • \\. 表示点,\n 是“换行”元字符(与之前的“12.”一样,开始换行)
  • 在 Regex 中,您可以使用方括号在模式中创建分组,即 gsub(".*(\\d{2}\\:\\d{2})", "\\1","18.05.2018, 21:37") 将返回 21:37,或者 gsub("([A-z]) \\d+","\\1","hello 123") 将返回 hello
  • 现在gsub 中的第二个参数可以并且经常用于提供替代,即替换匹配模式的内容。然而,在这里,我们不想要任何替代品,我们想要提取一些东西。 \\1 表示提取第一个分组,即第一个括号内的内容(您可以有多个分组)。
  • 最后,string 是我们要从中提取的字符串,即 PDF 文件

现在,如果您想在循环中执行类似的操作,您可以执行以下操作:

# we are in the loop
# first is your starting point in the extraction, i.e. "SECTION 11"
# last is your end point, i.e. "12."

first <- "SECTION 11"   # first and last can be dynamically assigned 
last <- "12\\."         # "\\" is added before the dot as "." is a Regex metachar
# If last doesn't systematically contain a dot
# you could use gsub to add "\\" before the dot when needed:
# gsub("\\.","\\\\.",".") returns "\\."
# so gsub("\\.","\\\\.","12.") returns "12\\."

pat <- paste0(".*",first,"(.*)","\n",last,".*")  #"\n" is added to stop before the newline, but it could be omitted (then "\n" might appear in the extraction)
gsub(pat,"\\1",string) # returns the same as above

【讨论】:

  • 感谢您的快速答复。看起来很有希望,我现在要测试你的建议,然后让你知道结果。我需要查找 gsub,因为我对它没有深入的了解。 IE。在您列出 string 的地方,我不知道这是定义类型:字符串还是它是更有意义的示例词。很快就会公布结果。
  • @J.Koren 我忘记了可以在字符串中找到的\n 元素。我编辑了我的gsub,见上文。
  • 我还没有进行完整的测试......我真的很难理解模式的简要解释 - 我这样做非常重要......我明白:.*成为边缘; (.*)我们想要的内容,介于两者之间; \\. 是那个时期......但是我在弄清楚其他一些东西时有点挣扎......嗯,我只是想知道是否有任何方法可以识别##。 (或 11./12.)动态的,基于部分名称的位置。
  • @J.Koren 我已经添加了有关该模式的更多详细信息,希望对您有所帮助。
  • 非常感谢。不幸的是,由于组织限制,我要到星期一才能进行测试。我一定会让你知道情况如何。目标是遍历一个报告文件夹,从每个报告中提取相同的部分。我现在将把你提出的测试答案放在一份报告上,然后从那里继续。没想到会得到这么多帮助。再次感谢。
猜你喜欢
  • 2020-11-26
  • 2019-07-12
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
  • 2018-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多