使用rvest下载需要从网站(morphosource)HTML登录的压缩文件

时间:2018-12-03 18:21:56

标签: r rvest

我知道在stackoverflow上也有类似的问题,但是在浏览它们之后,我仍然没有找到下载所需文件的方法。我有一个http网站列表。登录到感兴趣的网站(MorphoSource)后,当我在浏览器中输入地址时,它会自动下载一个压缩文件夹。我需要从R中执行此操作,以便可以循环下载许多这些文件夹。

这是一个这样的http地址(尽管不登录就不会发生任何事情):"http://www.morphosource.org/index.php/Detail/MediaDetail/DownloadMedia/media_id/119/media_file_id/52"

我已经使用下面的代码进行了最深入的研究,但是仍然收到错误消息,表明我是Submitting with 'NULL',当我查看下载的文件时,如果超过50,000kb,则大约为8kb

  library(rvest) 
    login<-"https://www.morphosource.org/LoginReg/form"
    pgsession<-html_session(login)
    pgform<-html_form(pgsession)[[2]]  
    filled_form<-set_values(pgform, username="TestingPackage@gmail.com", password="testingpackage")
    submit_form(pgsession, filled_form)
download.file("http://www.morphosource.org/index.php/Detail/MediaDetail/DownloadMedia/media_id/119/media_file_id/52", "testfile")

我对R并不陌生,对于通过R中的网址下载压缩文件夹的想法是全新的,所以我非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我们只需要为您做一些会话管理:

morphosource_dl <- function(media_id, # if end of URL is /media_id/119/media_file_id/52 then this is 119
                            media_file_id, # if end of URL is /media_id/119/media_file_id/52 then this is 52
                            overwrite = TRUE, # overwrite file if it already exists?
                            .progress = TRUE, # show a download progress bar?
                            username = Sys.getenv("MORPHOSOURCE_EMAIL"), # pass in here or store in ~/.Renviron
                            password = Sys.getenv("MORPHOSOURCE_PASSWORD")) { # pass in here or store in ~/.Renviron

  suppressPackageStartupMessages({
    library(httr, warn.conflicts = FALSE, quietly = TRUE, verbose = FALSE)
    library(rvest, warn.conflicts = FALSE, quietly = TRUE, verbose = FALSE)
  }) 

  # Start a sessiion
  res <- httr::GET(url = "https://www.morphosource.org/Splash/Index")

  # login
  httr::POST(
    url = "https://www.morphosource.org/LoginReg/login",
    httr::add_headers(
      Referer = "https://www.morphosource.org/LoginReg/form"
    ),
    body = list(
      username = username, 
      password = password
    ),
    encode = "form"
  ) -> res

  # if successful
  if (length(html_nodes(httr:::content(res), xpath=".//*[contains(., 'You have been logged in')]")) > 0) {

    httr::stop_for_status(res) # make sure it really was successful

    # do this to get filename
    httr::HEAD(
      url = sprintf(
        "https://www.morphosource.org/index.php/Detail/MediaDetail/DownloadMedia/media_id/%s/media_file_id/%s",
        media_id, media_file_id
      )
    ) -> res

    fil <- gsub("^.*filename=", "", res$headers["content-disposition"])

    httr::GET(
      url = "https://www.morphosource.org/index.php/Detail/MediaDetail/DownloadMedia/media_id/119/media_file_id/52",
      httr::write_disk(fil, overwrite = overwrite),
      if (.progress) httr::progress()
    ) -> res

    if (.progress) cat("\n")

    return(fil)

  } else {
    message("Error logging in")
    httr::stop_for_status(res)
  }

}

您的URL是http://www.morphosource.org/index.php/Detail/MediaDetail/DownloadMedia/media_id/119/media_file_id/52(实际上是 https://www.morphosource.org/index.php/Detail/MediaDetail/DownloadMedia/media_id/119/media_file_id/52

这意味着“媒体ID”为119,而“媒体文件ID”为52

如果您做对了,并在~/.Renviron中输入以下内容:

MORPHOSOURCE_EMAIL=me@example.com
MORPHOSOURCE_PASSWORD=aBetterP@s$w0rDThanThis

并刷新您的R会话,然后您可以执行以下操作:

morphosource_dl("119", "52")
## Downloading: ... MB
## [1] "Morphosource_AMNH-M-100635_M119-52.zip"

,它将为您下载。

否则,您可以这样做:

morphosource_dl(
  media_id = "119", 
  media_file_id = "52", 
  username = "donotdothis@example.com",
  password = "embeddingCredentialsInScriptsIsNotTooBright"
)

,它将仍然下载。

在两种情况下,它都返回文件名。

您可以控制是否使用TRUE参数覆盖文件(默认情况下为overwrite)以及是否使用{{1]覆盖进度条(默认情况下为TRUE) }}。

您遇到的问题是.progress不了解download.file()rvest(以及curl)的基础httr。因此xml2无法提取download.file()调用生成的会话cookie。您可能刚刚调用了rvest和下载版本的httr::GET()版本,并在开始使用之后在其中使用了https,但是上面的函数将所有内容封装为一个动作,并找出文件名(必须手动设置)。

我们只是“漫长的旅程”,并且模仿了浏览器对httr::write_disk()GET所做的操作:

enter image description here