我有来自法律数据库的数百个“.docx”格式的文档。我正在尝试对文档进行一些 NLP 工作,但似乎无法超过 0。由于版权原因,不想发布测试文档。使用officer 和 docxtractr 时,我不断收到 xml2 path_to_connection 错误,并且不知道如何修复它。
如果我创建一个虚拟 docx,我可以毫无问题地将其读入 R。但是,应用于下载文档的相同步骤会失败。一开始我以为问题可能出在文件名上,于是我修改了一个文件名为test.docx,问题依然存在。然后我想也许我遇到了一些网络问题,该问题导致临时目录无法在我的工作计算机(Windows)上正确写入,但我在家用计算机(Mac)上遇到了同样的问题。接下来,我深入研究了底层函数,并意识到路径中发生了一些奇怪的事情。
在工作计算机(Windows)上,我的路径中包含反斜杠和正斜杠的组合。我还注意到该路径包含当我手动探索该路径时不存在的子目录。我不知道这是因为该函数部分失败还是只是指向了错误的位置。子目录“word”不存在,但在 Mac 和 Windows 测试中均出现。这是 Mac 代表
library(tidyverse)
library(officer)
#> Warning: package 'officer' was built under R version 4.4.1
test <- officer::read_docx("~/Downloads/test.docx")
#> Warning in read_core_properties(package_dir): No properties found. Using
#> properties from template file in officer.
#> Error in `path_to_connection()`:
#> !
#> '/var/folders/q2/8qcfd1qd5rqfvhr2x9l2k24m0000gp/T//RtmpZ6jZ5U/file95017ae662ea/word/document.xml'
#> does not exist.
reprex::reprex()
#> ℹ Non-interactive session, setting `html_preview = FALSE`.
#> CLIPR_ALLOW has not been set, so clipr will not run interactively
#> Error in switch(where, expr = stringify_expression(x_expr), clipboard = ingest_clipboard(), : EXPR must be a length 1 vector
我认为回溯显示它在路径检查中中止:
11. signal_abort(cnd, .file)
10. rlang::abort(message, ..., call = call, use_cli_format = TRUE,.frame = .frame)
9. cli::cli_abort(msg, call = call)
8. check_path(path)
7. path_to_connection(x)
6. read_xml.character(file)
5. read_xml(file)
4. super$feed(file.path(private$package_dir, "word", main_file))
3. initialize(...)
2. docx_part$new(package_dir, main_file = "document.xml", cursor = "/w:document/w:body/*[1]",body_xpath = "/w:document/w:body")
1. officer::read_docx("~/Downloads/test.docx")
我认为我的错误可能与使用模板文件并在找不到文档属性时将其映射回路径有关。我只是不知道如何解决它。如果我没有做一些非常愚蠢的事情,是否可以使用另一种方法来阅读文档?
创建于 2024 年 11 月 1 日,使用 reprex v2.1.1
好的。这是我的解决方案。只需打开文档并将其保存为新名称即可消除我遇到的任何格式问题,这些问题阻止 xml2 与Officer 和readtext 一起完成任务。我有 800 多个文档,因此一次只处理一个是行不通的。相反,我使用 RDCOMclient 打开文件并重新保存为paste0(basename(x), "1.docx")。这个简单的操作使我能够将文档解析为 r 数据帧。
library(tidyverse)
library(RDCOMClient)
library(R.utils)
library(here)
here()
#Word to Word conversion
the_source_path <- here("the_data", "enacted")
the_new_path <- here("output", "new_docx")
the_final_path <- here("output", "new_docx_final")
#copying files to new directory because changing file names
for (f in the_source_path) file.copy(from = f, to = the_new_path, recursive=TRUE)
#renaming files so there are no spaces in file names. necessary to use RDCOMCLient
old_names <- list.files(path=the_source_path, recursive=TRUE, pattern=c(".docx"))
new_names <- str_replace_all(old_names, "[:space:]", "_") |>
str_replace_all("-","_") |>
str_replace_all("\\(","") |>
str_replace_all("\\)","")
file.rename(paste0(the_new_path,"/enacted/", old_names),
paste0(the_new_path,"/enacted/", basename(new_names)))
#creating the vector of file paths to pass ot the conversion function
word_docs <- list.files(path=paste0(the_new_path,"/enacted/"), recursive=TRUE, pattern=c(".docx"))
#the function that converts the word file to pdfs
the_word_conversion <- function(x) {
for(i in seq_along(x)){
wordApp <- COMCreate("Word.Application") # create COM object
file <- getAbsolutePath(paste0(the_new_path, "/enacted/", x[i])) # convert to absolute path
file <- str_replace_all(file, "/", "\\\\")
wordApp[["Documents"]]$Open(Filename=file) #opens your docx in wordApp
wordApp[["ActiveDocument"]]$SaveAs(paste0(the_final_path, "\\enacted\\", gsub(pattern = "\\.docx$", "", basename(x[i])),"1.docx"), FileFormat=16)
wordApp$Quit() #quit wordApp
Sys.sleep(5)
}}
#running the function
the_word_conversion(word_docs)
t1 <- readtext::readtext(here("output/new_docx_final/enacted/test.docx"))