Skip to content

Instantly share code, notes, and snippets.

@artemklevtsov
Last active January 27, 2017 17:52
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artemklevtsov/525ca6af1ade619845b67afb76899b99 to your computer and use it in GitHub Desktop.
Save artemklevtsov/525ca6af1ade619845b67afb76899b99 to your computer and use it in GitHub Desktop.
Геолокация по IP адресу
#' @title Geolocate IP Addresses Through ip-api.com
#' @description
#' \code{geolocate} consumes a vector of IP addresses and geolocates them via
#' \href{http://ip-api.com}{ip-api.com}.
#' @param ip a character vector of IP addresses.
#' @param lang a string to specify an output localisation language.
#' Allowed values: en, de, es, pt-BR, fr, ja, zh-CN, ru.
#' @param fields a string to specify which fields to return.
#' @param delay a logical to whether or not to delay each request by 400ms.
#' ip-api.com has a maximum threshold of 150 requests a minute. Disable it for
#' the pro account.
#' @return A data frame with geolocation information.
#' @references http://ip-api.com/docs/api:batch
#' @author Artem Klevtsov \email{a.a.klevtsov@gmail.com}
#' @importFrom crul HttpClient
#' @importFrom jsonlite fromJSON rbind.pages
geolocate <- function(ip, lang = "en", fields = "258047", delay = TRUE) {
cl <- crul::HttpClient$new(url = "http://ip-api.com")
lang <- match.arg(lang, c("en", "de", "es", "pt-BR", "fr", "ja", "zh-CN", "ru"))
query <- list(lang = lang, fields = fields)
if (missing(ip) || ip == "") {
resp <- cl$post(path = "json", query = query)
parsed <- jsonlite::fromJSON(resp$parse("UTF-8"))
return(as.data.frame(parsed))
}
ip <- unique(ip)
get_data <- function(ip, query = NULL, delay = TRUE) {
body <- data.frame(query = ip)
if (delay) Sys.sleep(0.4)
resp <- cl$post(path = "batch", query = query, encode = "json", body = body)
resp$raise_for_status()
parsed <- jsonlite::fromJSON(resp$parse("UTF-8"))
return(parsed)
}
if (length(ip) > 100L) {
by <- seq_along(ip) - 1 %/% 100L
splitted <- unname(split(ip, by))
res <- lapply(splitted, get_data, query = query, delay = delay)
res <- jsonlite::rbind.pages(res)
} else {
res <- get_data(ip, query = query, delay = delay)
}
return(res)
}
@artemklevtsov
Copy link
Author

artemklevtsov commented Nov 24, 2016

R> str(geolocate(c("8.8.8.8", "2.2.2.2", "sdfadsf"), lang = "ru"))
'data.frame':	3 obs. of  17 variables:
 $ as         : chr  "AS15169 Google Inc." "" NA
 $ city       : chr  "Маунтин-Вью" "Исси-ле-Мулино" NA
 $ country    : chr  "США" "Франция" NA
 $ countryCode: chr  "US" "FR" NA
 $ isp        : chr  "Google" "Orange" NA
 $ lat        : num  37.4 48.8 NA
 $ lon        : num  -122.08 2.27 NA
 $ mobile     : logi  FALSE FALSE NA
 $ org        : chr  "Google" "Orange" NA
 $ proxy      : logi  FALSE FALSE NA
 $ query      : chr  "8.8.8.8" "2.2.2.2" "sdfadsf"
 $ region     : chr  "CA" "J" NA
 $ regionName : chr  "Калифорния" "Île-de-France" NA
 $ status     : chr  "success" "success" "fail"
 $ timezone   : chr  "America/Los_Angeles" "Europe/Paris" NA
 $ zip        : chr  "94035" "" NA
 $ message    : chr  NA NA "invalid query"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment