Это был хороший вызов!
Проблема не связана с языком R. У нас будет тот же результат на любом языке, если мы просто попытаемся опубликовать некоторые данные в скрипте загрузки. Здесь мы должны иметь дело с неким «шаблоном» безопасности. Сайт запрещает пользователям извлекать URL-адреса файлов и просит их заполнять формы данными для предоставления этих ссылок. Если браузер может получить эти ссылки, то и мы сможем, написав соответствующие HTTP-вызовы. Дело в том, что нам нужно точно знать, какие звонки мы должны сделать. Чтобы найти это, нам нужно увидеть отдельные звонки, которые сайт делает каждый раз, когда кто-то нажимает, чтобы загрузить. Вот что я обнаружил за несколько вызовов до успешного 302 AJDownload.jsp
POST
вызова:
Мы можем это ясно увидеть, если посмотрим на исходный код AJDocumentation.jsp
, он делает эти вызовы, используя jQuery $.get
:
$.get("http://ipinfo.io?token=xxxxxxxxxxxxxx", function (response) {
var geodatos=encodeURIComponent(response.ip+"\t"+response.country+"\t"+response.postal+"\t"+
response.loc+"\t"+response.region+"\t"+response.city+"\t"+
response.org);
$.get("jdsStatJD.jsp?ID="+geodatos+
"&url=http%3A%2F%2Fwww.worldvaluessurvey.org%2FAJDocumentation.jsp&referer=null&cms=Documentation",
function (resp2) {
});
}, "jsonp");
Затем, несколькими вызовами ниже, мы можем увидеть успешный POST /AJDownload.jsp
со статусом 302 Moved Temporarily
и разыскиваемым Location
в заголовках ответов:
HTTP/1.1 302 Moved Temporarily
Content-Length: 0
Content-Type: text/html
Location: http://www.worldvaluessurvey.org/wvsdc/CO00001/F00003724-WVS_Longitudinal_1981-2014_stata_dta_v_2015_04_18.zip
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Thu, 01 Dec 2016 16:24:37 GMT
Итак, это механизм безопасности этого сайта. Он использует ipinfo.io для хранения информации о посетителях об их IP-адресе, местонахождении и даже организации интернет-провайдера непосредственно перед тем, как пользователь собирается чтобы начать загрузку, нажав на ссылку. Скрипт, который получает эти данные, называется /jdsStatJD.jsp
. Я не использовал ни ipinfo.io, ни их API-ключ для этой службы (он скрыт на моих скриншотах), а вместо этого создал фиктивную валидную последовательность данных только для проверки запроса. Данные почтовой формы для «защищенных» файлов вообще не требуются. Файлы можно скачивать без публикации этих данных.
Также не требуется библиотека curlconverter
. Все, что нам нужно сделать, это простые запросы GET
и POST
с использованием библиотеки httr
. Я хочу отметить одну важную часть: чтобы функция httr
POST
не следовала за заголовком Location
, полученным со статусом 302
при нашем последнем вызове, нам нужно использовать параметр конфигурации config(followlocation = FALSE)
, который, конечно же, не позволит ей следовать за Location
. и давайте извлечем Location
из заголовков.
ВЫВОД
Мой сценарий R можно запустить из командной строки, и он может принимать DOID
числовых значений параметров для получения необходимого файла. Например, если мы хотим получить ссылку на файл WVS_Longitudinal_1981-2014_stata_dta_v_2015_04_18
, то мы должны добавить его DOID
(что равно 3724) в конец нашего скрипта при вызове его с помощью команды Rscript
:
Rscript wvs_fetch_downloads.r 3724
[1] "http://www.worldvaluessurvey.org/wvsdc/CO00001/F00003724-WVS_Longitudinal_1981-2014_stata_dta_v_2015_04_18.zip"
Я создал функцию R, чтобы получить каждое местоположение файла, которое вы хотите, просто передав DOID
:
getFileById <- function(fileId)
Вы можете удалить синтаксический анализ аргумента командной строки и использовать функцию, передав DOID
напрямую:
#args <- commandArgs(TRUE)
#if(length(args) == 0) {
# print("No file id specified. Use './script.r ####'.")
# quit("no")
#}
#fileId <- args[1]
fileId <- "3724"
# DOID=3843 : WVS_EVS_Integrated_Dictionary_Codebook v_2014_09_22 (Excel)
# DOID=3844 : WVS_Values Surveys Integrated Dictionary_TimeSeries_v_2014-04-25 (Excel)
# DOID=3725 : WVS_Longitudinal_1981-2014_rdata_v_2015_04_18
# DOID=3996 : WVS_Longitudinal_1981-2014_sas_v_2015_04_18
# DOID=3723 : WVS_Longitudinal_1981-2014_spss_v_2015_04_18
# DOID=3724 : WVS_Longitudinal_1981-2014_stata_dta_v_2015_04_18
getFileById(fileId)
Окончательный вариант рабочего сценария R
library(httr)
getFileById <- function(fileId) {
response <- GET(
url = "http://www.worldvaluessurvey.org/AJDocumentation.jsp?CndWAVE=-1",
add_headers(
`Accept` = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
`Accept-Encoding` = "gzip, deflate",
`Accept-Language` = "en-US,en;q=0.8",
`Cache-Control` = "max-age=0",
`Connection` = "keep-alive",
`Host` = "www.worldvaluessurvey.org",
`User-Agent` = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0",
`Content-type` = "application/x-www-form-urlencoded",
`Referer` = "http://www.worldvaluessurvey.org/AJDownloadLicense.jsp",
`Upgrade-Insecure-Requests` = "1"))
set_cookie <- headers(response)$`set-cookie`
cookies <- strsplit(set_cookie, ';')
cookie <- cookies[[1]][1]
response <- GET(
url = "http://www.worldvaluessurvey.org/jdsStatJD.jsp?ID=2.72.48.149%09IT%09undefined%0941.8902%2C12.4923%09Lazio%09Roma%09Orange%20SA%20Telecommunications%20Corporation&url=http%3A%2F%2Fwww.worldvaluessurvey.org%2FAJDocumentation.jsp&referer=null&cms=Documentation",
add_headers(
`Accept` = "*/*",
`Accept-Encoding` = "gzip, deflate",
`Accept-Language` = "en-US,en;q=0.8",
`Cache-Control` = "max-age=0",
`Connection` = "keep-alive",
`X-Requested-With` = "XMLHttpRequest",
`Host` = "www.worldvaluessurvey.org",
`User-Agent` = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0",
`Content-type` = "application/x-www-form-urlencoded",
`Referer` = "http://www.worldvaluessurvey.org/AJDocumentation.jsp?CndWAVE=-1",
`Cookie` = cookie))
post_data <- list(
ulthost = "WVS",
CMSID = "",
CndWAVE = "-1",
SAID = "-1",
DOID = fileId,
AJArchive = "WVS Data Archive",
EdFunction = "",
DOP = "",
PUB = "")
response <- POST(
url = "http://www.worldvaluessurvey.org/AJDownload.jsp",
config(followlocation = FALSE),
add_headers(
`Accept` = "*/*",
`Accept-Encoding` = "gzip, deflate",
`Accept-Language` = "en-US,en;q=0.8",
`Cache-Control` = "max-age=0",
`Connection` = "keep-alive",
`Host` = "www.worldvaluessurvey.org",
`User-Agent` = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0",
`Content-type` = "application/x-www-form-urlencoded",
`Referer` = "http://www.worldvaluessurvey.org/AJDocumentation.jsp?CndWAVE=-1",
`Cookie` = cookie),
body = post_data,
encode = "form")
location <- headers(response)$location
location
}
args <- commandArgs(TRUE)
if(length(args) == 0) {
print("No file id specified. Use './script.r ####'.")
quit("no")
}
fileId <- args[1]
# DOID=3843 : WVS_EVS_Integrated_Dictionary_Codebook v_2014_09_22 (Excel)
# DOID=3844 : WVS_Values Surveys Integrated Dictionary_TimeSeries_v_2014-04-25 (Excel)
# DOID=3725 : WVS_Longitudinal_1981-2014_rdata_v_2015_04_18
# DOID=3996 : WVS_Longitudinal_1981-2014_sas_v_2015_04_18
# DOID=3723 : WVS_Longitudinal_1981-2014_spss_v_2015_04_18
# DOID=3724 : WVS_Longitudinal_1981-2014_stata_dta_v_2015_04_18
getFileById(fileId)
person
Christos Lytras
schedule
02.12.2016