Функция tryCatch работает с большинством несуществующих URL-адресов, но не работает (по крайней мере) в одном случае - PullRequest
0 голосов
/ 27 сентября 2019

Уважаемые пользователи Stackoverflow,

Я использую R, чтобы очистить профили некоторых психотерапевтов из Psychology Today;это сделано для упражнений и обучения.

Я новичок в R (я начал несколько недель назад, и до этого я использовал только Stata, но это статистическое программное обеспечение, где можно реализовать некоторые программы), это не язык программирования).

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

Короче говоря, ситуация следующая.Я создал функцию, с помощью которой я собираю информацию из 15 узлов профилей психотерапевтов;функция показана в этом сообщении stackoverflow .

Затем я создаю цикл, в котором эта функция используется для профилей нескольких психотерапевтов;цикл также приведен в вышеприведенном посте, но я сообщу об этом ниже, потому что это часть скрипта, которая порождает некоторые проблемы (в дополнение к тому, что я решил в вышеупомянутом посте).

j <- 1
MHP_codes <-  c(150000:150200) #therapist identifier
df_list <- vector(mode = "list", length(MHP_codes))
  for(code1 in MHP_codes) {
    URL <- paste0('https://www.psychologytoday.com/us/therapists/illinois/', code1)
    #Reading the HTML code from the website
    URL <- read_html(URL)
    df_list[[j]] <- tryCatch(getProfile(URL), 
                             error = function(e) NA)
    j <- j + 1
  }

когдацикл завершен, я связываю информацию из разных профилей в один фрейм данных и сохраняю ее.

final_df <- rbind.fill(df_list)
save(final_df,file="final_df.Rda")

Функция (getProfile) хорошо работает на отдельных профилях.Он также работает с небольшим диапазоном профилей (c (150000: 150100)).Пожалуйста, обратите внимание, что я не знаю, какой идентификатор психотерапевта фактически назначен;поэтому некоторые URL в пределах диапазона не существуют.

Однако, в общем, tryCatch должен решить эту проблему.Когда URL-адрес не существует (и, следовательно, идентификатор не связан с каким-либо психотерапевтом), каждый из 15 узлов (и, следовательно, каждая из 15 соответствующих переменных в моем фрейме данных) являются пустыми (т. Е. Фрейм данных показывает NA всоответствующие ячейки).

Однако при увеличении диапазона идентификаторов могут возникнуть две проблемы.

Во-первых, после 152 URL-адресов появляется одно сообщение об ошибке:

Ошибка в open.connection (x, "rb"): ошибка HTTP 404.

Итак, это происходит, несмотря на то, что я использую tryCatch, и несмотря на то, что он работает (приминимум, до появления сообщения об ошибке).

Более того, после остановки цикла и запуска R строки:

final_df <- rbind.fill(df_list)

Появляется второе сообщение об ошибке:

Предупреждающее сообщение: в df [[var]]: закрытие неиспользуемого соединения 3 (https://www.psychologytoday.com/us/therapists/illinois/150152)

Похоже, что существует конкретная проблема с этим пустым URL. Фактически,когда я изменяю диапазон, например c (150153: 150300), цикл работает хорошо: на один часи когда URL-адрес существует, информация удаляется с веб-сайта, с другой стороны, когда URL-адрес не существует, 15 переменных, связанных с этим URL-адресом (и, следовательно, с этим идентификатором психотерапевта), получают NA.

Возможно ли, возможно, сказать R пропустить URL, если он пуст?Без записи ничего?это решение было бы превосходным, поскольку оно уменьшало бы фрейм данных до существующих URL, но я не знаю, как это сделать, и я не знаю, является ли это решением моей проблемы.

Любой, ктов состоянии помочь мне разобраться с этой проблемой?

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

Да, вам нужно обернуть tryCatch вокруг read_html вызова.Здесь R пытается подключиться к веб-сайту, поэтому он выдаст ошибку (в отличие от возврата пустого объекта), если не сможет подключиться.Вы можете перехватить эту ошибку и затем использовать next, чтобы указать R перейти к следующей итерации цикла.

library(rvest)
##Valid URL, works fine
URL <- "https://news.bbc.co.uk"
read_html(URL)

##Invalid URL, error raised
URL <- "https://news.bbc.co.uk/not_exist"
read_html(URL)
##Leads to error
Error in open.connection(x, "rb") : HTTP error 404.

##Invalid URL, catch and skip to next iteration of the loop
URL <- "https://news.bbc.co.uk/not_exist"
tryCatch({
URL <- read_html(URL)},
error=function(e) {print("URL Not Found, skipping")
                  next})
0 голосов
/ 27 сентября 2019

Я хотел бы поблагодарить @Jul за ответ.Здесь я публикую свой обновленный цикл:

  j <- 1
MHP_codes <-  c(150000:150200) #therapist identifier
df_list <- vector(mode = "list", length(MHP_codes))
for(code1 in MHP_codes) {
  delayedAssign("do.next", {next})
  URL <- paste0('https://www.psychologytoday.com/us/therapists/illinois/', code1)
  #Reading the HTML code from the website
  URL <-  tryCatch(read_html(URL), 
           error = function(e) force(do.next))

  df_list[[j]] <- getProfile(URL)
  j <- j + 1
}
final_df <- rbind.fill(df_list)

Как видите, что-то нужно было изменить: хотя ответ @Jul был близок к решению проблемы, цикл все равно остановился, и поэтому мне пришлосьнемного изменить оригинальное предложение.В частности, я ввел в цикл, но за пределами функции tryCatch, следующую строку:

delayedAssign("do.next", {next})

А в функции tryCatch следующий аргумент:

force(do.next)

Это основано наэто другое сообщение stackoverlflow .

...