#r #rest #error-handling
#r #остальное #обработка ошибок
Вопрос:
Я пытаюсь подсчитать количество слов в текстах исполнителя, взятых из lyrics.ovg. Я написал цикл для перебора песен. Однако, если песня не найдена, я получаю сообщение об ошибке. Я хотел бы обработать ошибку, чтобы продолжить работу со списком песен через короткий промежуток времени. Я пробовал «tryCatch» в сочетании с «withTimeout», но безуспешно. Любая помощь для этого новичка будет оценена по достоинству.
library(musicbrainz)
song_title <- c("Not A Song", "’39", "(You’re So Square) Baby I Don’t Care")
no_songs <- length(song_title)
root_url <- "https://api.lyrics.ovh/v1/"
## Initialise dataframe
df_songs <- data.frame (title = character(),
lyrics = character(),
no_words = integer())
while (no_songs > 0)
{
print(song_title[no_songs])
my_url <- paste0(root_url,"Queen","/",song_title[no_songs])
my_raw_result <- httr::GET(my_url)
my_content <- httr::content(my_raw_result, as = 'text')
#Convert into a more usable r object
my_content_from_json <- jsonlite::fromJSON(my_content)
lyrics <- gsub("[rn]", " ", my_content_from_json$lyrics)
lyrics <- str_squish(lyrics)
word_count <- sapply(strsplit(lyrics, " "), length)
df_songs <- rbind(df_songs, data.frame(song_title[no_songs], lyrics, word_count))
no_songs <- no_songs -1
}
Пример работает для первых двух песен, но терпит неудачу в последней («не песня»). Я пытался написать функцию с tryCatch следующим образом, но это не работает.
SongLyric <- function(x){
tryCatch(
expr = {
withTimeout(my_raw_result <- httr::GET(x),timeout= 3)
my_raw_result$status_code
my_content <- httr::content(my_raw_result, as = 'text')
#Convert into a more usable r object
my_content_from_json <- jsonlite::fromJSON(my_content)
lyrics0 <- gsub("[rn]", " ", my_content_from_json$lyrics)
lyrics0 <- str_squish(lyrics0)
return(lyrics0)
message("Successfully found song")
},
error = function(e){
message('Song not found')
lyrics0 = 404
return(lyrics0)
}
)
}
Ответ №1:
Мы можем использовать withTimeout
from R.utils
package, который прекращает попытки через несколько секунд и возвращает фрейм данных со NA
значениями.
Я также изменил while
цикл map_df
, который должен быть эффективным.
library(musicbrainz)
library(R.utils)
library(stringr)
song_title <- c("Not A Song", "’39", "(You’re So Square) Baby I Don’t Care")
root_url <- "https://api.lyrics.ovh/v1/"
all_urls <- paste0(root_url,"Queen/",song_title)
cbind(song_title, purrr::map_df(all_urls, function(my_url) {
my_content_from_json <- withTimeout(jsonlite::fromJSON(my_url)$lyrics, timeout = 5, onTimeout = "silent")
if(is.null(my_content_from_json)) return(data.frame(lyrics = NA, word_count = NA))
lyrics <- gsub("[rn]", " ", my_content_from_json)
lyrics <- str_squish(lyrics)
word_count <- str_count(lyrics, '\s ') 1
data.frame(lyrics, word_count)
})) -> result
result