#r #web-scraping #image-processing
Вопрос:
Цель здесь-загрузить кучу изображений, но некоторые URL — адреса изображений повреждены. Что я хочу сделать, так это изменить код с помощью простого оператора next, чтобы, если ссылка возвращает что-либо, кроме кода состояния 200, перейти к следующему URL (или если ссылка возвращает 404 перехода к следующему), но я не уверен, как написать это в векторизованном коде, и когда я пытаюсь написать это в цикле for, я не могу понять, как инициализировать вектор типа «картинка» для записи в цикле for. Итак, теперь я смотрю на код функции, пытаясь выяснить, где вызывается ошибка и куда поместить следующий оператор или что-то похожее на него… если вы не можете поместить следующий оператор в какую-либо форму векторизованного кода:
Простой Векторизованный Код:
library(magick)
library(rsvg)
image_urls <- na.omit(articles$url_to_image)
image_content <- image_read(image_urls)
Непрозрачный код «Функции» (Где вызывается ошибка?—просто куча звонков для загрузки различных типов изображений)
function (path, density = NULL, depth = NULL, strip = FALSE,
coalesce = TRUE, defines = NULL)
{
if (is.numeric(density))
density <- paste0(density, "x", density)
density <- as.character(density)
depth <- as.integer(depth)
#doesn't seem relevant: https://rdrr.io/cran/magick/src/R/defines.R
defines <- validate_defines(defines)
#test whether the object is an instance of an S4 class and a function to test inheritance relationships between object and class -- seems relevant maybe?
image <- if (isS4(path) amp;amp; methods::is(path, "Image"))
{
#bioconductor class
convert_EBImage(path)
}
else if (inherits(path, "nativeRaster") || (is.matrix(path) amp;amp;
is.integer(path))) {
image_read_nativeraster(path)
}
else if (inherits(path, "cimg")) {
image_read_cimg((path))
}
else if (grDevices::is.raster(path)) {
image_read_raster2(path)
}
else if (is.matrix(path) amp;amp; is.character(path)) {
image_read_raster2(grDevices::as.raster(path))
}
else if (is.array(path)) {
image_readbitmap(path)
}
else if (is.raw(path)) {
magick_image_readbin(path, density, depth, strip, defines)
}
else if (is.character(path) amp;amp; all(nchar(path))) {
path <- vapply(path, replace_url, character(1))
path <- if (is_windows()) {
enc2utf8(path)
}
else {
enc2native(path)
}
magick_image_readpath(path, density, depth, strip, defines)
}
else {
stop("path must be URL, filename or raw vector")
}
if (is.character(path) amp;amp; !isTRUE(magick_config()$rsvg)) {
if (any(grepl("\.svg$", tolower(path))) || any(grepl("svg|mvg",
tolower(image_info(image)$format)))) {
warning("ImageMagick was built without librsvg which causes poor qualty of SVG rendering.nFor better results use image_read_svg() which uses the rsvg package.",
call. = FALSE)
}
}
if (isTRUE(coalesce) amp;amp; length(image) > 1 amp;amp; identical("GIF",
toupper(image_info(image)$format[1]))) {
return(image_coalesce(image))
}
return(image)
}
Когда ссылка нарушена, она возвращает: Ошибка в файле download_url(путь) : Не удалось загрузить «ссылку» (HTTP 404), когда URL-адрес нарушен
Возможно Для Кода Цикла?
library(magick)
library(rsvg)
image_urls <- na.omit(articles$url_to_image)
image_content <- c() #doesn't work, nor does NULL
#nor does setting to typeof image_content <- image_url[1]
for(i in 1:length(image_urls){
image_content[i] = image_read(image_urls[i])
if(grepl('404', download_path(url), fixed = TRUE) == T)
next
}
Но опять же, я не могу инициализировать, и я не знаю, прервется ли цикл до того, как он доберется до оператора if в любом случае.
Может быть, есть другая библиотека, которую я должен использовать… или просто другой язык?
Вот некоторые примеры данных
data <- c("https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AAOgEbG.img?h=488amp;w=799amp;m=6amp;q=60amp;o=famp;l=f",
"https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AAOh6FW.img?h=533amp;w=799amp;m=6amp;q=60amp;o=famp;l=f",
"https://img-s-msn-com.net/tenant/amp/entityid/AAOgIFh.img?h=450amp;w=799amp;m=6amp;q=60amp;o=famp;l=famp;x=570amp;y")
Комментарии:
1. (1)
articles$url_to_image
не определено. Должна ли всяna.omit()
функция быть заменена вашими данными примераdata
? (2)download_path(url)
не определено.2. Спасибо вам за ваши комментарии. download_path(url) — это идеализированная функция, основанная на полученной неясной ошибке. статьи$url_to_image должны быть заменены данными примера, вы правы, спасибо, что указали на это.
Ответ №1:
Вы могли бы попробовать эту try
функцию:
image_urls <- data
image_content <- lapply(seq_along(image_urls), function(i) try(image_read(image_urls[i])))
Это сохранит ваши изображения в списке. С помощью
image_content[[1]]
дает вам доступ к первому изображению. Если есть такие ошибки, как
Error in curl::curl_fetch_memory(url) :
Could not resolve host: img-s-msn-com.net simpleError in curl::curl_fetch_memory(url)
они пропущены, и цикл переходит к следующей задаче.
Комментарии:
1. Я подумал о функции try… есть какая-нибудь причина для того, чтобы лапли над ваппли?
2. Я редко использую
vapply
, и я хотел, чтобы результат был списком. Таковlapply
был мой первый выбор.3. Это полностью имеет смысл, и мой вопрос был глупым, из-за формата изображения вывод не может быть vector…my плохо… : / извините.
4. Вопрос не был глупым. Не нужно извиняться. 🙂
Ответ №2:
Другой вариант-использовать purrr::safely
для создания «безопасной» версии image_read
, которая будет возвращать оба result
и error
для каждого URL-адреса.
Результаты можно извлечь из списка, используя что-то вроде purrr::map(y,`[[`, 'result')
.
# two working links and one broken
urls <- c("https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AAOgEbG.img?h=488amp;w=799amp;m=6amp;q=60amp;o=famp;l=f",
"https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AAOh6FW.img?h=533amp;w=799amp;m=6amp;q=60amp;o=famp;l=f",
"https://img-s-msn-com.net/tenant/amp/entityid/AAOgIFh.img?h=450amp;w=799amp;m=6amp;q=60amp;o=famp;l=famp;x=570amp;y")
# create 'safe' function
image_read_safe <- purrr::safely(magick::image_read)
# apply 'safe' function
y <- purrr::map(urls, image_read_safe)
y
#> [[1]]
#> [[1]]$result
#> format width height colorspace matte filesize density
#> 1 JPEG 799 488 sRGB FALSE 39743 96x96
#>
#> [[1]]$error
#> NULL
#>
#>
#> [[2]]
#> [[2]]$result
#> format width height colorspace matte filesize density
#> 1 JPEG 799 533 sRGB FALSE 53910 96x96
#>
#> [[2]]$error
#> NULL
#>
#>
#> [[3]]
#> [[3]]$result
#> NULL
#>
#> [[3]]$error
#> <simpleError in curl::curl_fetch_memory(url): Could not resolve host: img-s-msn-com.net>
Создано 2021-09-10 пакетом reprex (v2.0.0)
Комментарии:
1. Хорошенькая. Раньше такого не видел
safely
.2. Отслеживание ошибок на самом деле действительно полезно для меня в этом случае. Однако, когда я печатаю y, я не получаю информацию о формате изображения. Любопытно, почему это произошло.
3. На моей машине с RStudio, когда я распечатывал список, он записывал вывод, который вы видите выше, на консоль, а также отображал изображение в окне предварительного просмотра. Не уверен, почему
reprex
не взял изображения или почему они могут отображаться по-другому на вашем компьютере.4. @nniloc На этот раз он появился правильно. Мне было интересно, не могли бы вы обновить свой ответ, чтобы работать с новыми данными в моем вопросе? Так что очень извиняюсь за хлопоты!
5. Без проблем. Отредактировано для добавления в новые URL-адреса.