我已经搜索了SO,最接近答案的是here。
但是我的要求是要获得一种更简单,更优雅的方法来从pdf文本的简单段落中提取粗体。 pdftools
包仅提取纯文本组件。有谁知道是否有其他方法可以从pdf文本中检测粗体标记(或单词)。我使用R是为了限制R中的建议。
答案 0 :(得分:2)
您不必使用tabularizer
,但是我不知道不涉及Java的方法。我曾希望可以通过rtika
软件包使用Apache Tika。但是,bold text is not rendered as such。但是,可以使用该凭单中显示的pdfbox:
java -jar <pdfbox-jar> ExtractText -html <pdf-file> <html-file>
该命令通常在shell中启动,但是您也可以在R中使用system(2)
。然后在R中使用
html <- xml2::read_html(<html-file>)
bold <- xml2::xml_find_all(html, '//b')
head(xml2::xml_contents(bold))
处理HTML文件。 对于您的文档,此返回结果
{xml_nodeset (6)}
[1] Preamble\n
[2] WHEREAS it is expedient to define and amend certain parts of the law relating to contracts;\n
[3] History\n
[4] Ancient and Medieval Period\n
[5] The Introduction of English Law Into India\n
[6] Mofussal Courts\n
答案 1 :(得分:2)
除了拥有灵活的工具包外,数据科学还经常需要开箱即用的思想(至少在我的职业中如此)。
我认为它们不是您想的那样。 “粗体”(或“斜体”等)不是“元数据”。您应该花一些时间来阅读PDF文件,因为它们是复杂的,令人讨厌的,邪恶的东西,您在处理数据时可能经常遇到这些东西。阅读此书https://stackoverflow.com/a/19777953/1457051,以了解查找粗体文本实际上需要做些什么(请遵循1.8.x Java pdfbox
解决方案的链接)。
虽然我是R的YUGEst拥护者之一,但不是需要做的所有事情,也不应该在R中完成。当然,我们将使用R最终实现 >获得您的粗体文字,但我们将使用帮助程序命令行实用程序来实现。
pdftools
程序包基于poppler
库。它带有源,因此“我只是R用户”,他们的系统上可能没有完整的poppler
工具集。
Mac使用者可以使用Homebrew(一旦您完成Homebrew设置):
brew install poppler
Linux人员知道如何做事。 Windows用户永远迷路了(有 are poppler二进制文件供您使用,但您最好花费时间切换到实际的操作系统上。)
完成此操作后,您可以使用以下内容实现您的目标。
首先,我们将创建一个具有许多安全保险杠的辅助功能:
#' Uses the command-line pdftohtml function from the poppler library
#' to convert a PDF to HTML and then read it in with xml2::read_html()
#'
#' @md
#' @param path the path to the file [path.expand()] will be run on this value
#' @param extra_args extra command-line arguments to be passed to `pdftohtml`.
#' They should be supplied as you would supply arguments to the `args`
#' parameter of [system2()].
read_pdf_as_html <- function(path, extra_args=character()) {
# make sure poppler/pdftohtml is installed
pdftohtml <- Sys.which("pdftohtml")
if (pdftohtml == "") {
stop("The pdftohtml command-line utility must be installed.", call.=FALSE)
}
# make sure the file exists
path <- path.expand(path)
stopifnot(file.exists(path))
# pdf's should really have a PDF extension
stopifnot(tolower(tools::file_ext(path)) == "pdf")
# get by with a little help from our friends
suppressPackageStartupMessages({
library(xml2, warn.conflicts = FALSE, quietly = TRUE)
library(rvest, warn.conflicts = FALSE, quietly = TRUE)
})
# we're going to do the conversion in a temp directory space
td <- tempfile(fileext = "_dir")
dir.create(td)
on.exit(unlink(td, recursive=TRUE), add=TRUE)
# save our current working directory
curwd <- getwd()
on.exit(setwd(curwd), add=TRUE)
# move to the temp space
setwd(td)
file.copy(path, td)
# collect the extra arguments
c(
"-i" # ignore images
) -> args
args <- c(args, extra_args, basename(path), "r-doc") # saves it to r-doc-html.html
# this could take seconds so inform users what's going on
message("Converting ", basename(path), "...")
# we'll let stderr display so you can debug errors
system2(
command = pdftohtml,
args = args,
stdout = TRUE
) -> res
res <- gsub("^Page-", "", res[length(res)])
message("Converted ", res, " pages")
# this will need to be changed if poppler ever does anything different
xml2::read_html("r-docs.html")
}
现在,我们将使用它:
doc <- read_pdf_as_html("~/Data/Mulla__Indian_Contract_Act2018-11-12_01-00.PDF")
bold_tags <- html_nodes(doc, xpath=".//b")
bold_words <- html_text(bold_tags)
head(bold_words, 20)
## [1] "Preamble"
## [2] "WHEREAS it is expedient to define and amend certain parts of the law relating to contracts;"
## [3] "History"
## [4] "Ancient and Medieval Period"
## [5] "The Introduction of English Law Into India"
## [6] "Mofussal Courts"
## [7] "Legislation"
## [8] "The Indian Contract Act 1872"
## [9] "The Making of the Act"
## [10] "Law of Contract Until 1950"
## [11] "The Law of Contract after 1950"
## [12] "Amendments to This Act"
## [13] "Other Laws Affecting Contracts and Enforcement"
## [14] "Recommendations of the Indian Law Commission"
## [15] "Section 1."
## [16] "Short title"
## [17] "Extent, Commencement."
## [18] "Enactments Repealed."
## [19] "Applicability of the Act"
## [20] "Scheme of the Act"
length(bold_words)
## [1] 1939
完全不需要Java,并且您的粗体字。
如果您确实想像Ralf所说的走pdfbox-app
路线,则可以使用此包装器使其更易于使用:
read_pdf_as_html_with_pdfbox <- function(path) {
java <- Sys.which("java")
if (java == "") {
stop("Java binary is not on the system PATH.", call.=FALSE)
}
# get by with a little help from our friends
suppressPackageStartupMessages({
library(httr, warn.conflicts = FALSE, quietly = TRUE)
library(xml2, warn.conflicts = FALSE, quietly = TRUE)
library(rvest, warn.conflicts = FALSE, quietly = TRUE)
})
path <- path.expand(path)
stopifnot(file.exists(path))
# pdf's should really have a PDF extension
stopifnot(tolower(tools::file_ext(path)) == "pdf")
# download the pdfbox "app" if not installed
if (!dir.exists("~/.pdfboxjars")) {
message("~/.pdfboxjars not found. Creating it and downloading pdfbox-app jar...")
dir.create("~/.pdfboxjars")
httr::GET(
url = "http://central.maven.org/maven2/org/apache/pdfbox/pdfbox-app/2.0.12/pdfbox-app-2.0.12.jar",
httr::write_disk(file.path("~/.pdfboxjars", "pdfbox-app-2.0.12.jar")),
httr::progress()
) -> res
httr::stop_for_status(res)
}
# we're going to do the conversion in a temp directory space
tf <- tempfile(fileext = ".html")
on.exit(unlink(tf), add=TRUE)
c(
"-jar",
path.expand(file.path("~/.pdfboxjars", "pdfbox-app-2.0.12.jar")),
"ExtractText",
"-html",
path,
tf
) -> args
# this could take seconds so inform users what's going on
message("Converting ", basename(path), "...")
system2(
command = java,
args = args
) -> res
xml2::read_html(tf)
}
答案 2 :(得分:0)
此答案基于从@hrbmstr和@ralf收到的答案。因此,感谢他们。我已经简化了答案(主要是去除了HTML转换和文件命名的特殊性)。它也是为MAC OS用户(也许还有LINUX)量身定制的-不确定Windows家伙。
我想您已经在计算机上安装了pdftohtml
。如果不使用brew install pdftohtml
。如果您的MAC上没有自制软件,请先安装。提供了一个链接来帮助您for homebrew。
确定要在Mac上安装pdftohtml
后,请使用此R函数从任何pdf文档中提取粗体。
library(magrittr)
library(rvest)
library(stringr)
# pass a pdf file in current directory to this function
extr_bold <- function(file) {
basefile <- str_remove(file,"\\.pdf|\\.PDF")
htmlfile <- paste0(basefile,"s",".html")
if(!exists(htmlfile) )
system2("pdftohtml",args = c("-i",file),stdout=NULL)
nodevar <- read_html(htmlfile)
x <- html_nodes(nodevar,xpath = ".//b")
html_text(x)
}
答案 3 :(得分:0)
2021 年 6 月 14 日更新的答案
我认为这个问题需要一个更新的答案。
好消息:R 包 pdftools
在其最近的更新中包含了从 pdf 中提取 font-data
的选项。函数 pdf_data
现在具有 documentation 中描述的附加参数 font_info
:
font_info 如果为 TRUE,则为每个框提取字体数据。小心,这 需要最新版本的 poppler,否则会出错。
使用 pdftools::pdf_data
和 font_info=TRUE
的简单实现表明:
pdftools::pdf_data(pdf = "https://arxiv.org/pdf/2012.10582.pdf", font_info = TRUE)
备注:
KBJWLM+NimbusRomNo9L-Medi
。ReguItal
代表“常规斜体”。例如,ZBSJXS+NimbusRomNo9L-ReguItal
。Regu
后缀表示,如 VDTZKA+NimbusRomNo9L-Regu
。警告:此答案从未针对具有重叠/重叠文本的 pdf 图像(扫描)进行过测试。