R语言,循环:错误控制 异常控制

在R中,循环如果出错,程序就会被kill掉。对于计算开销较大的循环来说,这样的错误是难以忍受的。

  • 一种方法是逐步地debug,针对所有的情况都能提供处理方案,但是很费心费力;
  • 一种方法是使用错误 异常控制函数,把错误跳过 或者说,提升对错误的容忍能力,即容错性。

针对第二种方法,有try tryCatch等函数。网上虽然教程较少,但是也能学个大概。最不济,看R 帮助文件也是可以的。本文,主要是记录我遇到的问题和解决的方法。

问题背景

使用爬虫爬取表格。该表格结构简单,不涉及到动态网页相关知识。问题就在于内容较大,每页有500行,有7000+页。

  • 网页结构:静态网页
  • url结构:有规律
  • 网络状态:较差,难以次次连接成功
  • 出现的问题:连接不上(报错),连接超时(不报错,但是爬虫卡死了)

由于代码涉及到项目,所以具体细节不能公开。这里只是说明类似的问题和提供解决的思路。

代码撰写

略,下文使用expr1代表出现问题的代码块,其他expr\\d表示用于处理该过程的代码块。

错误控制

  • 针对爬虫连接网页失败,报错并打断进程的问题
  • 使用的R基础包中的函数 tryCatch
tryCatch(
  expr1, 
  error=function(e){
    expr2
  },finnally = {
    expr3
  }
)
  • tryCatch的思路是
    • run expr1
    • if expr1 is error, doing expr2
    • finnally, weather expr1 error or not, doing expr3
  • 我的代码与下面类似:
while(i != m+1){
  tryCatch(
     {
        expr1 # expr1是爬取网络的代码块 ,所以会遇到连接失败的error
        i = i+1 # 如果expr1有error,则该语句不会运行,因而下一次循环使用的还是本次循环的i值
      }, error = function(e){
          cat("Sleeping for net connection agian at i = ", i, "\n")
          Sys.sleep(10) # sleep 10s,而后重复发生了错误的那个i
      }, finnaly = {
    expr3 #是啥都行。我用来输出循环信息
      }
   )
}

异常控制

  • 针对连接超时,导致循环停滞,爬虫卡死的问题
  • 使用R.utils包的withTimeout函数
  • 我的代码类似于:
while(i != m+1){
  tryCatch(
    {
      R.utils::withTimeout(
        expr1,
        timeout = 60
      )
       i = i+1
    }, TimeoutException = function(ex){
        message("Times out! Now refresh it") # 输出提示信息。但是事实上Timeout函数已经终止了expr1,并开始下一次循环(i值不变)
    }, error = function(e){
        cat("Sleeping for net connection agian at i = ", i, "\n")
        Sys.sleep(10) # sleep 10s,而后重复发生了错误的那个i
    }, finnaly = {
        expr3 #是啥都行。我用来输出循环信息
    }
  )
}

感悟

爬取数据,虽然是爬,但是却是比手动复制粘贴优雅一千倍的贵族运动。电脑随便爬去吧,这边看会儿生信技能树、生信星球的推文或者去峡谷里维护一下正义,难道不香吗?

你可能感兴趣的:(R语言,循环:错误控制 异常控制)