R中的内存泄漏?

xml r memory-leaks rcurl

288 观看

1回复

65 作者的声誉

我正在尝试使用Rcurl和XML包解析某些站点。执行约1小时后,根据任务管理器重新会话过程使用12G。打电话后

rm(list = ls())
gc()

我所有的记忆仍然被rsession使用。问题是什么?这是代码:

  library(XML);
  library(RCurl);
  rm(list = ls())
  if (file.exists('cookies.txt')){
        file.remove('cookies.txt')
  }
  if (file.exists('words.txt')){
        file.remove('words.txt')
  }

  doGet <- function(url, encode = 'windows-1251') {
        html <- tryCatch(
              {
                    getURL(url, curl=curl, .encoding = encode)
              }, warning = function(w) {
                    print(paste('warning: ', url, w))
              }, error = function(e) {
                    print(paste('error: ', url, e))
              }, finally = {}
        )
        write(x = html, file = '~tmp.html', append = F)
        htmlTreeParse(file = '~tmp.html', useInternalNodes = T, encoding = encode)
  }

  makeURL <- function(url) {
        paste(url_base, url, sep = "")
  }

  parse.morph <- function(n){
        val <- xmlValue(n, encoding = 'UTF-8')
        res <- tolower(gsub(" |-", "", strsplit(val, ':')[[1]][[2]]))
        rm(val)
        res
  }

  morphToList <- function(morphs) {
        print(paste(morphs, collapse=''))
        res <- list()
        res$prefix = unlist(strsplit(morphs[1], split = ';'))
        res$base =   unlist(strsplit(morphs[2], split = ';'))
        res$suffix = unlist(strsplit(morphs[3], split = ';'))
        res$ending = unlist(strsplit(morphs[4], split = ';'))
        res
  }

  indexOf <- function(val, str) {
        grep(val, strsplit(str, "")[[1]])
  }

  parse.word <- function(page) {
        xpathSApply(page, "//div[@class='word-article']/ul/li", parse.morph) 
  }

  append <- function(df, m) {
        tmp <- data.frame(p1 =  m$prefix[3], p2 =  m$prefix[2], p3 =  m$prefix[1], 
                          b1 = m$base[1],   b2 = m$base[2],  
                          s1 = m$suffix[1], s2 = m$suffix[2], s3 = m$suffix[3], s4 = m$suffix[4], 
                          e1 = m$ending[1], e2 = m$ending[2], e3 = m$ending[3])
        rbind(df, tmp)
  }

  parsePage <- function(page) {
        words.url <- xpathSApply(page, "//tr[contains(@class, 'row')]/td/a", xmlGetAttr, 'href') 
        df <- data.frame(p1 = c(), p2 = c(), p3 = c(), b1 = c(), b2 = c(),  s1 = c(), s2 = c(), s3 = c(), s4 = c(), e1 = c(), e2 = c(), e3 = c())
        for(word.url in words.url) {
              page <- doGet(makeURL(word.url))
              word.morphs <- parse.word(page)
              df <- append(df, morphToList(word.morphs))
        }
        return(df)
  }

  saveWords <- function(df, fileName) {
        write.table(file = fileName, x = df, append = T, row.names = F, col.names = F, quote = T, sep = ',')
  }

  url_base <- 'http://slovonline.ru'
  url_addr <- makeURL('/slovar_sostav')
  agent<-"Mozilla/5.0"

  curl<-getCurlHandle()
  curlSetOpt(curl = curl, cookiejar='cookies.txt', useragent='Mozilla/5.0', followlocation=T)


  index <- doGet(url_addr)
  lrs.url <- xpathSApply(index, "//div[@class = 'nletters all']/a", xmlGetAttr, 'href') 

  for (letter in lrs.url[1:2]) {
        page <- doGet(makeURL(letter))
        table <- parsePage(page)
        pages.url <- c(letter, xpathSApply(page, "//div[@class = 'npages']/a", xmlGetAttr, 'href'))
        saveWords(df = table, fileName = 'words.csv')
        for (page.url in pages.url) {
              page <- doGet(makeURL(page.url))
              table <- parsePage(page)
              saveWords(df = table, fileName = 'words.csv')
        }
  }
作者: Dev 的来源 发布者: 2016 年 1 月 6 日

回应 (1)


4

3287 作者的声誉

决定

XML正如StackOverflow查询所揭示的那样,该程序包存在内存管理问题(示例此处此处此处)。包的作者和维护者Duncan Lang 撰写了有关内存使用问题的论文

您可以尝试Hadley Wickham的xml2软件包,该软件包承诺比更好的内存管理XML。就我个人而言,我尚未核实此说法。

上一次,当我不得不抓取大量Web数据(大约2万页)时,我决定用Python重写整个内容。那时没有xml2了。

我尝试过的另一种方法是从shell循环启动R脚本。这样,rsession进程在耗尽内存之前就已停止。尽管相当笨拙,但它运行得还算不错。

如果您有兴趣,这里有算法概述:

  • 在外壳中:
    • 检查文件是否special-name存在
    • 如果不存在,请r在R脚本文件上运行
    • 重复
  • 在R脚本中
    • 从“尚待处理”池中获取地址样本
    • 如果样本为空(“待处理”池已用尽)-使用special-name(信号外壳停止执行)创建文件并完成
    • 对于每个地址:进行处理并将其从“尚待处理”池中删除
作者: Mirek Długosz 发布者: 06.01.2016 12:37
32x32