#r #api #for-loop #http-post #httr
#r #API #for-цикл #http-post #httr
Вопрос:
Я работаю с REST API NIH / NLM и пытаюсь программно извлекать много данных одновременно. Я никогда не работал с API, который проверяет с помощью служебных билетов (TGT и ST) вместо OAUTH, которые необходимо обновлять для каждого запроса GET, который вы делаете, поэтому я не уверен, что я даже делаю это правильно. Любая помощь приветствуется.
Вот код, который у меня есть в настоящее время:
library(httr)
library(jsonlite)
library(xml2)
UTS_API_KEY <- 'MY API KEY'
# post to the CAS endpoint
response <- POST('https://utslogin.nlm.nih.gov/cas/v1/api-key', encode='form', body=list(apikey = 'MY API KEY'))
# print out the status_code and content_type
status_code(response)
headers(response)$`content-type`
doc <- content(response)
action_uri <- xml_text(xml_find_first(doc, '//form/@action'))
action_uri
# Service Ticket
response <- POST(action_uri, encode='form', body=list(service = 'http://umlsks.nlm.nih.gov'))
ticket <- content(response, 'text')
ticket #this is the ST I need for every GET request I make
# build search_uri using the paste function for string concatenation
version <- 'current'
search_uri <- paste('https://uts-ws.nlm.nih.gov/rest/search/', version, sep='')
# pass the the query params into httr GET to get the response
query_string <- 'diabetic foot'
response <- GET(search_uri, query=list(ticket=ticket, string=query_string))
## print out some of the results
search_uri
status_code(response)
headers(response)$`content-type`
search_results_auto_parsed <- content(response)
search_results_auto_parsed
class(search_results_auto_parsed$result$results)
search_results_data_frame <- fromJSON(content(response,'text'))
search_results_data_frame
Этот код отлично работает только для нескольких запросов GET, однако я пытаюсь извлечь 300 с чем-то медицинских терминов. Например, в строке запроса я хотел бы перебирать массив строк (например, «диабет», «кровяное давление», «сердечно-сосудистая помощь», «Скорая помощь» и т. Д.). Мне нужно было бы выполнить POST-запрос и передать ST в параметр GET для каждой строки в массиве.
Я поиграл с этим кодом:
for (i in 1:length(Entity_Subset$Entities)){
ent = Entity_Subset$Entities[i] #Entities represents my df of strings
url <- paste(' https://uts-ws.nlm.nih.gov/rest/search/current?string=',
ent,'amp;ticket=', sep = "")
print(url)
}
Но мне не очень повезло собрать воедино запросы POST и GET после ввода строк в (GET) HTTPS-запрос.
Боковая панель: я также попытался написать несколько предварительных сценариев в Postman, но, как ни странно, служебный билет не возвращается как JSON (нет пары ключ-значение для захвата и передачи). Просто обычный текст.
Спасибо за любые советы, которые вы можете предоставить!
Комментарии:
1. Вы сказали, что POST-запрос необходим для каждого GET-запроса. Таким образом, каждый служебный билет предназначен только для одноразового использования, а не для повторного использования вообще?
2. @ekoam Точно. Только для одноразового использования и вообще не используется повторно. Это можно использовать повторно (в течение 5 минут), только если вы нажмете точно такой же запрос GET — почему, кто-нибудь захочет это сделать, я не уверен. Итак, в идеале, можно было бы встроить POST-запрос в какой-то цикл, который также проходит через массив строк для запроса GET?
Ответ №1:
Я думаю, вы можете просто обернуть оба запроса POST и GET в функцию. Затем lapply
эта функция преобразуется в список символов.
library(httr)
library(jsonlite)
library(xml2)
fetch_data <- function(query_string = 'diabetic foot', UTS_API_KEY = 'MY API KEY', version = 'current') {
response <- POST('https://utslogin.nlm.nih.gov/cas/v1/api-key', encode='form', body=list(apikey = UTS_API_KEY))
# print out the status_code and content_type
message(status_code(response), "n", headers(response)$`content-type`)
action_uri <- xml_text(xml_find_first(content(response), '//form/@action')); message(action_uri)
# Service Ticket
response <- POST(action_uri, encode = 'form', body=list(service = 'http://umlsks.nlm.nih.gov'))
ticket <- content(response, 'text'); message(ticket)
# build search_uri using the paste function for string concatenation
search_uri <- paste0('https://uts-ws.nlm.nih.gov/rest/search/', version)
# pass the the query params into httr GET to get the response
response <- GET(search_uri, query=list(ticket=ticket, string=query_string))
## print out some of the results
message(search_uri, "n", status_code(response), "n", headers(response)$`content-type`)
fromJSON(content(response, 'text'))
}
# if you have a list of query strings, then
lapply(Entity_Subset$Entities, fetch_data, UTS_API_KEY = "blah blah blah")
# The `lapply` above is logically equivalent to
result <- vector("list", length(Entity_Subset$Entities))
for (x in Entity_Subset$Entities) {
result[[x]] <- fetch_data(x, "blah blah blah")
}
Комментарии:
1. Большое вам спасибо! Это абсолютно сработало. И спасибо за подробное объяснение.