Проверьте, существует ли URL в R - PullRequest
0 голосов
/ 21 октября 2018

Я хочу просмотреть список URL-адресов и выяснить, существуют ли эти URL-адреса или нет.

RCurl обеспечивает функцию url.exists().Тем не менее, вывод не кажется правильным, потому что, например, он говорит, что amazon.com не зарегистрирован (это происходит потому, что функция url.exists() не возвращает значение в диапазоне 200, в случаеamazon.com это 405 («метод не разрешен»).

Я также пробовал HEAD() и GET(), предоставляемые пакетом httr. Но иногда я получаю здесь сообщения об ошибках, например, для тайм-аутов илипотому что URL не зарегистрирован.

Сообщения об ошибках выглядят следующим образом:

Error in curl::curl_fetch_memory(url, handle = handle) : Timeout was reached: Connection timed out after 10000 milliseconds

Error in curl::curl_fetch_memory(url, handle = handle) : Could not resolve host: afsadadssadasf.com

Когда я получаю такую ​​ошибку,весь цикл for останавливается. Можно ли продолжить цикл for? Я пытался tryCatch(), но, насколько мне известно, это может помочь, только когда проблема находится в самом кадре данных.

Ответы [ 2 ]

0 голосов
/ 21 октября 2018

pingr::ping() использует только ICMP, который блокируется в разумных организационных сетях, поскольку злоумышленники используют ICMP как способ эксфильтрации данных и связи с серверами управления и контроля.

pingr::ping_port() не использует заголовок HTTP Host:, поэтому IP-адрес может отвечать, но целевой виртуальный веб-хост может не работать на нем, и он определенно не проверяет, существует ли путь вцелевой URL.

Вы должны уточнить, что вы хотите, чтобы происходило, когда есть только HTTP-коды состояния, отличные от 200: 299.Следующее делает предположение.

ПРИМЕЧАНИЕ: Вы использовали Amazon в качестве примера, и я надеюсь , что это первый сайт, который просто «пришёл в голову», так как это неэтично и преступление поцарапатьАмазонка и я были бы признательны, если бы мой код не попал в вашу вселенную, если вы на самом деле просто наглый вор контента.Если вы крадете контент, то вряд ли вы будете здесь откровенны, но если у вас есть шанс, что вы оба крадете и обладаете совестью, пожалуйста, дайте мне знать, чтобы я мог удалить этот ответ, чтобы, по крайней мере, другие воры контента могли ».t использовать его.

Вот отдельная функция для проверки URL:

#' @param x a single URL
#' @param non_2xx_return_value what to do if the site exists but the
#'        HTTP status code is not in the `2xx` range. Default is to return `FALSE`.
#' @param quiet if not `FALSE`, then every time the `non_2xx_return_value` condition
#'        arises a warning message will be displayed. Default is `FALSE`.
#' @param ... other params (`timeout()` would be a good one) passed directly
#'        to `httr::HEAD()` and/or `httr::GET()`
url_exists <- function(x, non_2xx_return_value = FALSE, quiet = FALSE,...) {

  suppressPackageStartupMessages({
    require("httr", quietly = FALSE, warn.conflicts = FALSE)
  })

  # you don't need thse two functions if you're alread using `purrr`
  # but `purrr` is a heavyweight compiled pacakge that introduces
  # many other "tidyverse" dependencies and this doesnt.

  capture_error <- function(code, otherwise = NULL, quiet = TRUE) {
    tryCatch(
      list(result = code, error = NULL),
      error = function(e) {
        if (!quiet)
          message("Error: ", e$message)

        list(result = otherwise, error = e)
      },
      interrupt = function(e) {
        stop("Terminated by user", call. = FALSE)
      }
    )
  }

  safely <- function(.f, otherwise = NULL, quiet = TRUE) {
    function(...) capture_error(.f(...), otherwise, quiet)
  }

  sHEAD <- safely(httr::HEAD)
  sGET <- safely(httr::GET)

  # Try HEAD first since it's lightweight
  res <- sHEAD(x, ...)

  if (is.null(res$result) || 
      ((httr::status_code(res$result) %/% 200) != 1)) {

    res <- sGET(x, ...)

    if (is.null(res$result)) return(NA) # or whatever you want to return on "hard" errors

    if (((httr::status_code(res$result) %/% 200) != 1)) {
      if (!quiet) warning(sprintf("Requests for [%s] responded but without an HTTP status code in the 200-299 range", x))
      return(non_2xx_return_value)
    }

    return(TRUE)

  } else {
    return(TRUE)
  }

}

Попробуйте:

c(
  "http://content.thief/",
  "http://rud.is/this/path/does/not_exist",
  "https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=content+theft", 
  "https://www.google.com/search?num=100&source=hp&ei=xGzMW5TZK6G8ggegv5_QAw&q=don%27t+be+a+content+thief&btnK=Google+Search&oq=don%27t+be+a+content+thief&gs_l=psy-ab.3...934.6243..7114...2.0..0.134.2747.26j6....2..0....1..gws-wiz.....0..0j35i39j0i131j0i20i264j0i131i20i264j0i22i30j0i22i10i30j33i22i29i30j33i160.mY7wCTYy-v0", 
  "https://rud.is/b/2018/10/10/geojson-version-of-cbc-quebec-ridings-hex-cartograms-with-example-usage-in-r/"
) -> some_urls

data.frame(
  exists = sapply(some_urls, url_exists, USE.NAMES = FALSE),
  some_urls,
  stringsAsFactors = FALSE
) %>% dplyr::tbl_df() %>% print()
##  A tibble: 5 x 2
##   exists some_urls                                                                           
##   <lgl>  <chr>                                                                               
## 1 NA     http://content.thief/                                                               
## 2 FALSE  http://rud.is/this/path/does/not_exist                                              
## 3 TRUE   https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords=con…
## 4 TRUE   https://www.google.com/search?num=100&source=hp&ei=xGzMW5TZK6G8ggegv5_QAw&q=don%27t…
## 5 TRUE   https://rud.is/b/2018/10/10/geojson-version-of-cbc-quebec-ridings-hex-cartograms-wi…
## Warning message:
## In FUN(X[[i]], ...) :
##   Requests for [http://rud.is/this/path/does/not_exist] responded but without an HTTP status code in the 200-299 range
0 голосов
/ 21 октября 2018

Попробуйте функцию ping в пакете pingr.Это дает время пингов.

library(pingr)

ping("amazon.com") # good site
## [1] 45 46 45

ping("xxxyyyzzz.com") # bad site
## [1] NA NA NA
...