如何编写一个运行在服务器上的R脚本,在网络上检测远端文件夹中新添加的CSV文件(或其他特定格式),并自动下载?
文件夹的例子。https:/ftp.ncbi.nlm.nih.govpubpmc。
一旦在这个文件夹中添加了一个新的CSV文件,我想马上下载它在本地处理。
我知道OP在寻找一个 "事件监听器 "来监控文件服务器上的变化,但是... 一些 消息必须从远方的计算机上发送,以通知你的计算机有变化。如果你对文件服务器没有控制权,让它给你发消息的唯一方法就是先给它发一个请求。这意味着唯一可用的一般 "事件监听器 "是通过间歇性地轮询服务器来工作的。
根据你的轮询频率,这应该完全可以作为一个事件监听器来使用。打个比方,许多种类的蝙蝠通过发出间歇性的超声波脉冲并聆听响应来捕猎。这是一种间歇性轮询的形式,它的工作原理足以让它们活下去。
这确实意味着必须在自己的电脑上有某种软件在后台运行。你的两个选择是使用调度来间歇性地运行R脚本,或者在后台运行一个R脚本,在轮询之间暂停。
从评论中可以看出,OP只想下载任何一个 新的 文件添加到服务器上,但不是在程序第一次运行时创建现有文件的副本。这意味着必须在本地存储一个文件,列出上次检查时ftp目录的内容,然后将其与ftp目录的当前内容进行比较,并下载任何新文件以及更新内容记录。
这里有一个函数就是这样做的。第一次运行时,它会创建一个新的本地目录,以主机的url命名,并在目录中添加一个 .csv
文件,并列出该点的目录。之后对该函数的调用将比较本地和远程目录的内容,并下载任何新文件。
local_mirror <- function(url, root_dir = path.expand("~/"), silent = FALSE)
{
if(substring(root_dir, nchar(root_dir), nchar(root_dir)) != "/")
root_dir <- paste0(root_dir, "/")
content <- rvest::html_nodes(xml2::read_html(url), "a")
links <- rvest::html_attr(content, "href")
links <- grep("/", links, invert = TRUE, value = TRUE)
rel_path <- strsplit(url, "//")[[1]][2]
mirror_path <- paste0(root_dir, rel_path)
if(!dir.exists(mirror_path))
{
build_path <- root_dir
for(i in strsplit(rel_path, "/")[[1]])
{
build_path <- paste0(build_path, i, "/")
dir.create(build_path)
}
write.csv(links, paste0(mirror_path, ".mirrordat.csv"))
}
records <- read.csv(paste0(mirror_path, ".mirrordat.csv"), stringsAsFactors = FALSE)
current_files <- records$x
n_updated <- 0
if(!silent) cat("Updating files - please wait")
for(i in seq_along(links))
{
if(!(links[i] %in% current_files))
{
download.file(paste0(url, links[i]), paste0(mirror_path, links[i]))
n_updated <- n_updated + 1
}
}
if(!silent) message(paste("Downloaded", n_updated, "files"))
write.csv(links, paste0(mirror_path, ".mirrordat.csv"))
}
要在你的情况下运行这个函数,你只需要运行:
local_mirror("https://ftp.ncbi.nlm.nih.gov/pub/pmc/")
如果要在后台作为一个持续的 "事件监测器 "运行它,你可以把它放在一个循环函数里面,比如这样:
listen_for_changes <- function(url, poll_every = 5, silent = TRUE)
{
repeat
{
local_mirror(url, silent = silent)
Sys.sleep(poll_every)
}
}
你只要运行这个函数就可以了。
listen_for_changes("https://ftp.ncbi.nlm.nih.gov/pub/pmc/")
我之前也遇到过类似的问题,我写了一个(有点)综合性的函数,叫做 repchkdl()
为此,我将其捆绑在一个小的 R
包。
这里是一个 联系 到其Github repo上。
它在很多方面都与@Allan Cameron建议的解决方案类似,并提供了额外的选项来微调远程URL的扫描方式(manualauto选项)、文件的下载方式(例如,用正则表达式过滤)以及迭代频率+限制(例如,每2分钟扫描一次,共重复两次,之后退出)等。
使用实例。
test <- repchkdl(inpurl = "ftp://speedtest.tele2.net/upload/",
inpregex = ".txt$", autoscan = "y", autodl = "y", inpwait = 10,
scanlim = 2)
这将自动下载(autoscan = "y"
, autodl = "y"
) 所有以 .txt
(inpregex = ".txt$"
)从URL ftp://speedtest.tele2.net/upload/
,并每10秒检查一次更新 (inpwait = 10
). 该函数将重新检查两次(scanlim = 2
),然后退出。文件名的向量将被保存到对象的 test
.
编辑。该包已被彻底改造,并有额外的功能,包括静音模式操作。仓库的位置仍然是 一样. 函数调用略有变化,如下所示(举例说明)。
test <- repchkdl(url = "ftp://ftp.swfwmd.state.fl.us/pub/usf/",
usr = "anonymous", pwd = "[email protected]",
scanlim = 2, wait = 2, verbosity = TRUE)
head(test)
# flinks fsizes dlstats
# 1 SWFWMD_May2020.txt 25321197 SUCCESS
# 2 USF_SCADA_AM_20200517.csv 2322041 SUCCESS
# 3 USF_SCADA_AM_20200518.csv 2321932 SUCCESS
# 4 USF_SCADA_AM_20200519.csv 2323118 SUCCESS
# 5 USF_SCADA_AM_20200520.csv 2322689 SUCCESS
# 6 USF_SCADA_AM_20200521.csv 2322243 SUCCESS