2014-12-20 3 views
1

Я пытаюсь очистить данные с веб-сайта, который, к сожалению, находится на очень ненадежном терминале, который имеет очень изменчивое время реакции. Первой идеей является, конечно, перебрать список (тысяч) URL-адресов и сохранить загруженные результаты, заполнив список.Динамическое изменение последовательности цикла

Проблема в том, что сервер случайным образом реагирует очень медленно, что приводит к ошибке таймаута. Это само по себе не будет проблемой, поскольку я могу использовать функцию tryCatch() и перейти к следующей итерации. Тем не менее, я пропускаю некоторые файлы в каждом прогоне. Я знаю, что каждый из URL-адресов в списке существует, и мне нужны все данные.

Моя идея, таким образом, заключалась бы в использовании tryCatch(), чтобы оценить, дает ли результат и ошибка getURL(). Если это так, цикл переходит к следующей итерации, а ошибочный URL-адрес добавляется в конец списка URL-адреса, по которому выполняется цикл. Мое интуитивное решение будет выглядеть примерно так:

dwl = list() 

for (i in seq_along(urs)) { 

temp = tryCatch(getURL(url=urs[[i]]),error=function(e){e}) 

if(inherits(temp,"OPERATION_TIMEDOUT")){ #check for timeout error 
urs[[length(urs)+1]] = urs[[i]] #if there is one the erroneous url is appended at the end of the sequence 
next} else { 
dwl[[i]] = temp #if there is no error the data is saved in the list 
} 
} 

Если это «бы» работа, которую я бы в конечном итоге иметь возможность загрузить все URL-адреса в списке. Он, однако, не работает, поскольку на странице справки для функции next указано: «seq в цикле for оценивается в начале цикла, а его изменение впоследствии не влияет на цикл». Есть ли обходной путь для этого или трюк, с которым я мог бы достичь своей предполагаемой цели? Я благодарен за каждый комментарий!

ответ

2

Я хотел бы сделать что-то вроде этого (объяснение в комментариях):

## RES is a global list that contain the final result 
## Always try to pre-allocate your results 
RES <- vector("list",length(urs)) 
## Safe getURL returns NA if error, the NA is useful to filter results 
get_url <- function(x) tryCatch(getURL(x),error=function(e)NA) 
## the parser! 
parse_doc <- function(x){## some code to parse the doc}) 


## loop while we still have some not scraped urls 
while(length(urs)>0){ 
    ## get the doc for all urls 
    l_doc <- lapply(urs,get_url) 
    ## parse each document and put the result in RES 
    RES[!is.na(l_doc)] <<- lapply(l_doc [!is.na(l_doc)],parse_doc) 
    ## update urs 
    urs <<- urs[is.na(l_doc)] 
} 
+0

эй спасибо большое! отличное решение! – chameau13