You need to enable JavaScript to run this app. splashr批量爬取URL时cron任务触发curl连接重置错误如何解决?
优惠活动
大模型
产品
解决方案
定价
更多

splashr批量爬取URL时cron任务触发curl连接重置错误如何解决?

问题排查与解决方案

1. 内存/垃圾回收操作必要性

你确实需要在两次爬取间隔执行资源清理操作,但不局限于R层面的垃圾回收:

  • 当前代码每次循环都会新建Splash连接,但没有显式释放会话资源,Splash服务端的内存、网络句柄会持续累积,到达阈值后就会主动断开连接,也就是你遇到的Recv failure: Connection reset by peer错误。
  • 你观察到的QNetworkReplyImplPrivate::error报错是Splash服务端资源耗尽的前置预警,本质是内部未释放的网络请求对象冲突导致的。
  • 清理操作需要覆盖两个层面:每次爬取结束后显式关闭Splash会话,同时调用R的gc()释放闲置的curl句柄和内存。

2. 直接运行成功、cron任务失败的原因

两者的运行环境存在核心差异:

  • 资源限制不同:cron的非交互式运行环境默认的ulimit(最大打开文件数、网络超时时间、内存配额)都比RStudio Server的交互式会话严格,资源耗尽的阈值更低,所以会更早触发连接断开。
  • 自动回收逻辑不同:RStudio的交互式会话会在后台自动触发闲置资源回收,而非交互式的R脚本不会主动执行垃圾回收,内存和句柄泄漏速度更快。
  • 服务状态校验缺失:你在RStudio中运行前会手动确认Splash服务正常运行,但cron任务启动时如果Splash服务异常重启、端口被占用,没有对应的容错逻辑,会直接触发报错。

3. 报错修复方案

3.1 修改爬取代码

增加会话释放、错误重试、显式垃圾回收逻辑:

library("tidyverse")
library("splashr")
library("rvest")

# 启动Splash时增加资源限制参数,避免内存溢出
system2("docker", args = c("run -d -p 5023:5023 -p 8050:8050 -p 8051:8051 --memory=2g -e SPLASH_MAX_RSS=2048 -e SPLASH_TIMEOUT=180 scrapinghub/splash:latest"), wait = FALSE)
# 等待服务启动
Sys.sleep(10)

pause_after_html_read <- 5
pause_after_html_text <- 3
# 单URL最大重试次数
max_retry <- 3

for(idx in 1:28){  
  retry_cnt <- 0
  pg <- NULL
  while(retry_cnt < max_retry && is.null(pg)){
    tryCatch({
      spl <- splash(host = "localhost", port = 8050L)
      pg <- spl |> 
        splash_response_body(FALSE) %>%
        splash_go(url = url_df$web_page[idx]) %>%
        splash_wait(pause_after_html_read) %>%
        splash_html() |> 
        html_text()
      # 显式关闭Splash会话
      splash_close(spl)
    }, error = function(e){
      message(sprintf("第%d个URL第%d次爬取失败: %s", idx, retry_cnt+1, e$message))
      if(exists("spl")) splash_close(spl)
      # 重试到最后一次仍失败则重启Splash服务应对严重异常
      if(retry_cnt == max_retry-1){
        system2("docker", args = c("stop $(docker ps -q --filter ancestor=scrapinghub/splash:latest)"))
        Sys.sleep(5)
        system2("docker", args = c("run -d -p 5023:5023 -p 8050:8050 -p 8051:8051 --memory=2g -e SPLASH_MAX_RSS=2048 -e SPLASH_TIMEOUT=180 scrapinghub/splash:latest"), wait = FALSE)
        Sys.sleep(10)
      }
      Sys.sleep(5)
    })
    retry_cnt <- retry_cnt + 1
  }
  Sys.sleep(pause_after_html_text)
  # 显式执行垃圾回收
  gc(verbose = FALSE)
}

# 爬取结束后关闭Splash容器
system2("docker", args = c("stop $(docker ps -q --filter ancestor=scrapinghub/splash:latest)"))

3.2 调整cron任务配置

  • 执行任务前增加ulimit调整,在cron执行的R脚本开头添加ulimit -n 65535提升最大打开文件数限制
  • 确保cron任务的执行用户和你运行RStudio的用户一致,避免docker访问权限问题
  • 不要丢弃cron任务的输出,重定向到日志文件方便后续排查异常:* * * * * /usr/bin/Rscript /path/to/your/script.R >> /path/to/logfile.log 2>&1

内容的提问来源于stack exchange,提问作者ixodid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 15:24:04