从下载的文件中提取源元数据

Tde*_*eus 3 macos metadata r

我有一堆我下载的pdf文件。现在我想从文件的元数据中提取下载 url。我如何以编程方式执行此操作?我更喜欢 R 中的解决方案,我正在研究 MacOS Mojave。

如果你想复制你可以[使用这个文件]

在此处输入图片说明

hrb*_*str 5

虽然您可以通过使用 R 以编程方式下载 PDF 来避免这种需要,但我们可以使用该xattrs包来获取您要查找的数据:

library(xattrs) # https://gitlab.com/hrbrmstr/xattrs (not on CRAN)
Run Code Online (Sandbox Code Playgroud)

让我们看看这个文件有哪些扩展属性可用:

xattrs::list_xattrs("~/Downloads/0.-miljoenennota.pdf")
## [1] "com.apple.metadata:kMDItemWhereFroms"
## [2] "com.apple.quarantine" 
Run Code Online (Sandbox Code Playgroud)

com.apple.metadata:kMDItemWhereFroms 看起来是个不错的目标:

xattrs::get_xattr(
  path = "~/Downloads/forso/0.-miljoenennota.pdf",
  name = "com.apple.metadata:kMDItemWhereFroms"
) -> from_where

from_where
## [1] "bplist00\xa2\001\002_\020}https://www.rijksoverheid.nl/binaries/rijksoverheid/documenten/begrotingen/2016/09/20/miljoenennota-2017/0.-miljoenennota.pdfP\b\v\x8b"
Run Code Online (Sandbox Code Playgroud)

但是,它是二进制 plist 格式(是的 Apple #sigh)。然而,由于那是“一件事”,xattrs包有一个read_bplist()功能,但我们必须get_xattr_raw()使用它:

xattrs::read_bplist(
  xattrs::get_xattr_raw(
    path = "~/Downloads/forso/0.-miljoenennota.pdf",
    name = "com.apple.metadata:kMDItemWhereFroms"
  )
) -> from_where

str(from_where)
## List of 1
##  $ plist:List of 1
##   ..$ array:List of 2
##   .. ..$ string:List of 1
##   .. .. ..$ : chr "https://www.rijksoverheid.nl/binaries/rijksoverheid/documenten/begrotingen/2016/09/20/miljoenennota-2017/0.-miljoenennota.pdf"
##   .. ..$ string: list()
##   ..- attr(*, "version")= chr "1.0"
Run Code Online (Sandbox Code Playgroud)

丑陋的嵌套列表是真正愚蠢的二进制 plist 文件格式的错误,但源 URL 就在那里。

我们可以通过使用lapply. 这篇博文中还有一个例子,但它使用reticulatePython 包来读取二进制 plist 数据,而不是内置包函数来执行此操作(所述内置包函数是 macOSplutil实用程序或 linux的包装器plistutil实用程序;Windows 用户如果想使用该功能,可以切换到真正的操作系统)。

fils <- list.files("~/Downloads/forso", pattern = "\\.pdf", full.names = TRUE)

do.call(
  rbind.data.frame,
  lapply(fils, function(.x) {

    xattrs::read_bplist(
      xattrs::get_xattr_raw(
        path = .x,
        name = "com.apple.metadata:kMDItemWhereFroms"
      )
    ) -> tmp

    from_where <- if (length(tmp$plist$array$string) > 0) {
      tmp$plist$array$string[[1]]
    } else {
      NA_character_
    }

    data.frame(
      fil = basename(.x),
      url = from_where,
      stringsAsFactors=FALSE
    )

  })
) -> files_with_meta

str(files_with_meta)
## 'data.frame': 9 obs. of  2 variables:
##  $ fil: chr  "0.-miljoenennota.pdf" "19180242-D02E-47AC-BDB3-73C22D6E1FDB.pdf" "Codebook.pdf" "Elementary-Lunch-Menu.pdf" ...
##  $ url: chr  "https://www.rijksoverheid.nl/binaries/rijksoverheid/documenten/begrotingen/2016/09/20/miljoenennota-2017/0.-miljoenennota.pdf" "http://eprint.ncl.ac.uk/file_store/production/230123/19180242-D02E-47AC-BDB3-73C22D6E1FDB.pdf" "http://apps.start.umd.edu/gtd/downloads/dataset/Codebook.pdf" "http://www.msad60.org/wp-content/uploads/2017/01/Elementary-February-Lunch-Menu.pdf" ...
Run Code Online (Sandbox Code Playgroud)

注意:IRL 您可能应该在示例中做更多的防弹工作lapply