return 使用 download.file() 与 xml2::read_html() 的格式不一致

return format inconsistencies using download.file() vs xml2::read_html()

我正在尝试解析 FTP 站点的索引页,以便根据 <a href = ""> 标签的内容获取文件列表。我很难理解为什么我在尝试以不同方式下载 ftp 文件夹的索引时得到不同格式的结果(结果具有不同的 DOCTYPE 规范)。考虑以下因素:

  tf = tempfile()
  download.file("ftp://ftp.dfg.ca.gov/IEP_Zooplankton/", tf)
  file.show(tf)

结果:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

<HTML>
<HEAD>
<TITLE>FTP directory /IEP_Zooplankton/ at ftp.dfg.ca.gov</TITLE>
</HEAD>
<BODY>
<H2 ID="WinINetFtpDirectory">FTP directory /IEP_Zooplankton/ at ftp.dfg.ca.gov</H2>
<HR>
<A HREF="..">Up to higher level directory</A><BR><PRE>
09/06/2019 01:26PM      Directory <A HREF="/IEP_Zooplankton/./"><B>.</B></A>
09/06/2019 01:26PM      Directory <A HREF="/IEP_Zooplankton/../"><B>..</B></A>
07/09/2019 12:00AM     11,393,654 <A HREF="/IEP_Zooplankton/1972-2018CBMatrix.xlsx">1972-2018CBMatrix.xlsx</A>
05/09/2019 12:00AM      3,174,362 <A HREF="/IEP_Zooplankton/1972-2018MysidMatrix.xlsx">1972-2018MysidMatrix.xlsx</A>
05/09/2019 12:00AM      6,058,037 <A HREF="/IEP_Zooplankton/1972-2018Pump%20Matrix.xlsx">1972-2018Pump Matrix.xlsx</A>
05/09/2019 12:00AM         16,238 <A HREF="/IEP_Zooplankton/ReadMeZooplanktonStudyMatricesMay2019.docx">ReadMeZooplanktonStudyMatricesMay2019.docx</A>
09/06/2019 01:26PM      1,737,932 <A HREF="/IEP_Zooplankton/ZooplanktonMetadataSept2019.pdf">ZooplanktonMetadataSept2019.pdf</A>
05/01/2008 12:00AM        202,752 <A HREF="/IEP_Zooplankton/ZP%20Monitoring%20Station%20Map%20Historic.ppt">ZP Monitoring Station Map Historic.ppt</A>
10/31/2017 12:00AM        199,023 <A HREF="/IEP_Zooplankton/ZPCoreAndCurrentStationsAug2017.pdf">ZPCoreAndCurrentStationsAug2017.pdf</A>
</PRE>
<HR>
</BODY>
</HTML>

但是,如果我尝试使用 xml2::read_html()(或 curl::curl_fetch_memory())执行等效操作,我会得到完全不同的格式:

xml = xml2::read_html("ftp://ftp.dfg.ca.gov/IEP_Zooplankton/")

结果(你可以通过 as.character(xml) 将整页内容打印到控制台):

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>drwxrwxrwx   1 user     group           0 Sep  6 13:26 .
drwxrwxrwx   1 user     group           0 Sep  6 13:26 ..
-rw-rw-rw-   1 user     group    11393654 Jul  9  2019 1972-2018CBMatrix.xlsx
-rw-rw-rw-   1 user     group     3174362 May  9  2019 1972-2018MysidMatrix.xlsx
-rw-rw-rw-   1 user     group     6058037 May  9  2019 1972-2018Pump Matrix.xlsx
-rw-rw-rw-   1 user     group       16238 May  9  2019 ReadMeZooplanktonStudyMatricesMay2019.docx
-rw-rw-rw-   1 user     group     1737932 Sep  6 13:26 ZooplanktonMetadataSept2019.pdf
-rw-rw-rw-   1 user     group      202752 May  1  2008 ZP Monitoring Station Map Historic.ppt
-rw-rw-rw-   1 user     group      199023 Oct 31  2017 ZPCoreAndCurrentStationsAug2017.pdf
</p></body></html>

第一个结果(通过 download.file())可以使用 xml2::xml_find_*() 函数解析,但后者不能。为什么同一个文件会出现不同的格式?我怎样才能确保我得到以前的格式(即带有 <a> 标签的格式)?

我发现你的 ftp link 超时所以我不能给你一个可重现的例子,但我想如果你这样做:

xml <- xml2::read_html("ftp://ftp.dfg.ca.gov/IEP_Zooplankton/")
link_nodes <- xml2::xml_find_all(xml, xpath = "//a") 
xml2::xml_attr(link_nodes, "href")

您应该获得所需页面上所有 link 的向量。

虽然它没有解释为什么 FTP 下载的索引页的格式 download.file()与使用curl::curl_download()下载的不同, 我确实找到了 this gist,它提供了使用 curl 完成原始任务的替代解决方案:获取 FTP 目录中的文件列表。

library(curl)

con = curl(url = url, "r", handle = new_handle(dirlistonly = TRUE))
files = readLines(con)
close(con)
print(files)

[1] "1972-2018CBMatrix.xlsx"
[2] "1972-2018MysidMatrix.xlsx"
[3] "1972-2018Pump Matrix.xlsx"
[4] "ReadMeZooplanktonStudyMatricesMay2019.docx" [5] "ZooplanktonMetadataSept2019.pdf"
[6] "ZP Monitoring Station Map Historic.ppt"
[7] "ZPCoreAndCurrentStationsAug2017.pdf"