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

R 从下载的文件中提取源元数据,r,macos,metadata,R,Macos,Metadata,我下载了一堆pdf文件。现在我想从文件的元数据中提取下载url。我如何通过编程实现这一点?我更喜欢R中的解决方案,我正在研究MacOS Mojave 如果你想复制,你可以 我尝试搜索询问不同的方法,以模拟从Terminal.app命令行选择“Get Info” 我找到了使用命令mdls的建议,我从一个R系统调用中得到了这个建议: system("mdls -name kMDItemWhereFroms ~/0.-miljoenennota.pdf") #kMDItemWhereFroms =

我下载了一堆pdf文件。现在我想从文件的元数据中提取下载url。我如何通过编程实现这一点?我更喜欢R中的解决方案,我正在研究MacOS Mojave

如果你想复制,你可以


我尝试搜索
询问不同的方法,以模拟从Terminal.app命令行选择“Get Info”

我找到了使用命令
mdls
的建议,我从一个R
系统
调用中得到了这个建议:

system("mdls -name kMDItemWhereFroms ~/0.-miljoenennota.pdf")

#kMDItemWhereFroms = (
#   "https://www.rijksoverheid.nl/binaries/rijksoverheid/documenten/begrotingen/2016/09/20/miljoenennota-2017/0.-miljoenennota.pdf",
#    ""
#)
要将多行结果输入R(而不是仅仅出现在控制台上),您需要将
intern=TRUE
参数添加到
system
调用中:

> res <- system("mdls -name kMDItemWhereFroms ~/0.-miljoenennota.pdf", intern=TRUE)
> res
[1] "kMDItemWhereFroms = ("                                                                                                                 
[2] "    \"https://www.rijksoverheid.nl/binaries/rijksoverheid/documenten/begrotingen/2016/09/20/miljoenennota-2017/0.-miljoenennota.pdf\","
[3] "    \"\""                                                                                                                              
[4] ")"                                                                                                                                     
> res[2]
[1] "    \"https://www.rijksoverheid.nl/binaries/rijksoverheid/documenten/begrotingen/2016/09/20/miljoenennota-2017/0.-miljoenennota.pdf\","
我还可以通过以下方式获得“元数据”的不同定义:


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

library(xattrs) # https://gitlab.com/hrbrmstr/xattrs (not on CRAN)
让我们看看此文件有哪些扩展属性可用:

xattrs::list_xattrs("~/Downloads/0.-miljoenennota.pdf")
## [1] "com.apple.metadata:kMDItemWhereFroms"
## [2] "com.apple.quarantine" 
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"
但是,它是二进制plist格式的(耶,苹果#叹气)。但是,由于这是“一件事”,因此
xattrs
包有一个
read\u bplist()
函数,但我们必须使用
get\u xattr\u 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"
丑陋的嵌套列表是真正愚蠢的二进制plist文件格式的错误,但源URL在其中

通过使用
lappy
,我们可以通过这种方式(我将一堆随机交互下载的PDF文件扔到一个目录中)获得所有这些文件。这里还有一个例子,但它使用
networkite
和Python包来读取二进制plist数据,而不是内置的包函数(所述内置包函数是macOS
plutil
实用程序或linux
plistutil
实用程序的包装器;Windows用户如果想要使用该函数,可以切换到真实的操作系统)

fils-tmp
从_,其中0){
tmp$plist$array$string[[1]]
}否则{
纳乌性格_
}
数据帧(
fil=基本名称(.x),
url=从何处开始,
stringsAsFactors=FALSE
)
})
)->文件_与_meta
str(带meta的文件)
##“data.frame”:9个obs。共有2个变量:
##$fil:chr“0.-miljoenennota.pdf”“19180242-D02E-47AC-BDB3-73C22D6E1FDB.pdf”“Codebook.pdf”“初级午餐菜单.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" ...

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

到目前为止您尝试了什么?哇,谢谢您的回答,软件包和博客帖子!将努力解决这些问题!我确实最终希望所有url都在一个数据框中。嗯,
导入(“biplist”,as=“biplist”)
给了我一个导入错误。当我在
~/
上成功安装
biplist
时,它找不到模块。我会坚持使用blog帖子中的包内函数vs reticate-d示例。或者,显式地将
~/.Renviron
中的
网状PYTHON
变量设置为指向您使用的PYTHON二进制文件(您可以通过
py_config()查看Networkate正在使用什么)
。它可能在您的系统上拾取了与您认为不同的python版本。Tnx,我现在让您的脚本在没有python工具的情况下工作。为了教育起见,我现在正尝试在purrr.FWIW
xattr-pcom.apple中重新生成您的代码。元数据:kMDItemWhereFroms 0.-miljoenennota.pdf | xxd-r-p | plutil-convert json-r-o--| jq.[0].
将是获取此数据的另一种系统实用方法使用
mdls
在我看来要容易得多。非常感谢您的“斩首”软件包,它的名字真是太棒了!
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"
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"
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" ...