2013-06-26 22 views
9

Najpierw zapytałem this question o wykonanie tego zadania z pakietem httr, ale nie sądzę, że jest to możliwe przy użyciu httr. więc ponownie napisałem mój kod, aby użyć zamiast niego RCurl - ale nadal potknę się na czymś prawdopodobnie związanym z writefunction .. ale naprawdę nie rozumiem dlaczego.jak pobrać duży plik binarny za pomocą RCurl * po * uwierzytelnieniu serwera *

powinieneś być w stanie odtworzyć moją pracę za pomocą 32-bitowej wersji R, więc trafisz w limity pamięci, jeśli czytasz cokolwiek do pamięci RAM. Potrzebuję rozwiązania, które pobiera bezpośrednio na dysk twardy.

na początek, ten kod do działa - spakowany plik jest odpowiednio zapisany na dysku.

library(RCurl) 
filename <- tempfile() 
f <- CFILE(filename, "wb") 
url <- "http://www2.census.gov/acs2011_5yr/pums/csv_pus.zip" 
curlPerform(url = url, writedata = [email protected]) 
close(f) 
# 2.1 GB file successfully written to disk 

Oto kod, który nie działa, ale zawiera kod RCurl. jak stwierdzono w the previous question, odtworzenie tego dokładnie będzie wymagało utworzenia ekstraktu na ipums.

your.email <- "[email protected]" 
your.password <- "password" 
extract.path <- "https://usa.ipums.org/usa-action/downloads/extract_files/some_file.csv.gz" 

library(RCurl) 

values <- 
    list(
     "login[email]" = your.email , 
     "login[password]" = your.password , 
     "login[is_for_login]" = 1 
    ) 

curl = getCurlHandle() 

curlSetOpt(
    cookiejar = 'cookies.txt', 
    followlocation = TRUE, 
    autoreferer = TRUE, 
    ssl.verifypeer = FALSE, 
    curl = curl 
) 

params <- 
    list(
     "login[email]" = your.email , 
     "login[password]" = your.password , 
     "login[is_for_login]" = 1 
    ) 

html <- postForm("https://usa.ipums.org/usa-action/users/validate_login", .params = params, curl = curl) 
dl <- getURL("https://usa.ipums.org/usa-action/extract_requests/download" , curl = curl) 

i teraz, że jestem zalogowany, spróbuj te same polecenia jak wyżej, ale z obiektu curl zachować cookie.

filename <- tempfile() 
f <- CFILE(filename, mode = "wb") 

ta linia breaks--

curlPerform(url = extract.path, writedata = [email protected], curl = curl) 
close(f) 

# the error is: 
Error in curlPerform(url = extract.path, writedata = [email protected], curl = curl) : 
    embedded nul in string: [[binary jibberish here]] 

odpowiedź na mój poprzedni post skierował mnie do this c-level writefunction odpowiedź, ale mam bladego pojęcia o tym, jak ponownie utworzyć ten program curl_writer C (w systemie Windows?) ..

dyn.load("curl_writer.so") 
writer <- getNativeSymbolInfo("writer", PACKAGE="curl_writer")$address 
curlPerform(URL=url, writefunction=writer) 

..or dlaczego jest to nawet konieczne, zważywszy, że pięć linii kodu na początku tej pracy zapytania bez niczego szalonego jak getNativeSymbolInfo. po prostu nie rozumiem, dlaczego przekazanie tego dodatkowego obiektu, który przechowuje uwierzytelnienie/pliki cookie i mówi mu, aby nie weryfikować SSL, spowodowałoby, że kod, który w przeciwnym razie działa, może się zepsuć?

+0

Co się dzieje, jeśli edytować kod, który działa dodanie 'curl = getCurlHandle()' i 'curlPerform (url = URL, writedata = F @ ref = curl, curl)'? i czy możesz pobrać inną zawartość po rozpoczęciu sesji? na przykład, używając 'curlPerform' i' writedata', aby zapisać 'https: //usa.ipums.org/usa-action/extract_requests/download' –

+0

O kodzie C, musisz skompilować go do biblioteki DLL, a następnie 'dyn.load (" curl_writer.dll ")' –

+0

1) nie rozumiem jak twoja edycja getCurlHandle() różni się od mojego kodu? 2) tak, jestem w stanie pobrać inną zawartość po rozpoczęciu sesji. 'z <- getBinaryURL (extract.path, curl = curl)' działa, ale czyta wszystko do pamięci RAM, więc nie rozwiązuje mojego problemu. 3) czy można to zrobić w R na oknach? dzięki!! :) –

Odpowiedz

2
  1. Od this link utwórz plik o nazwie curl_writer.c i zapisać go do C:\<folder where you save your R files>

    #include <stdio.h> 
    
    /** 
    * Original code just sent some message to stderr 
    */ 
    size_t writer(void *buffer, size_t size, size_t nmemb, void *stream) { 
        fwrite(buffer,size,nmemb,(FILE *)stream); 
        return size * nmemb; 
    } 
    
  2. otworzyć okno poleceń, przejdź do folderu, w którym został zapisany curl_writer.c i uruchomić kompilator R

    c:> cd "C:\<folder where you save your R files>" 
    c:> R CMD SHLIB -o curl_writer.dll curl_writer.c 
    
  3. Otwórz R i uruchom skrypt

    C:> R 
    
    your.email <- "[email protected]" 
    your.password <- "password" 
    extract.path <- "https://usa.ipums.org/usa-action/downloads/extract_files/some_file.csv.gz" 
    
    library(RCurl) 
    
    values <- 
        list(
         "login[email]" = your.email , 
         "login[password]" = your.password , 
         "login[is_for_login]" = 1 
        ) 
    
    curl = getCurlHandle() 
    
    curlSetOpt(
        cookiejar = 'cookies.txt', 
        followlocation = TRUE, 
        autoreferer = TRUE, 
        ssl.verifypeer = FALSE, 
        curl = curl 
    ) 
    
    params <- 
        list(
         "login[email]" = your.email , 
         "login[password]" = your.password , 
         "login[is_for_login]" = 1 
        ) 
    
    html <- postForm("https://usa.ipums.org/usa-action/users/validate_login", .params = params, curl = curl) 
    dl <- getURL("https://usa.ipums.org/usa-action/extract_requests/download" , curl = curl) 
    
    # Load the DLL you created 
    # "writer" is the name of the function 
    # "curl_writer" is the name of the dll 
    dyn.load("curl_writer.dll") 
    writer <- getNativeSymbolInfo("writer", PACKAGE="curl_writer")$address 
    
    # Note that "URL" parameter is upper case, in your code it is lowercase 
    # I'm not sure if that has something to do 
    # "writer" is the symbol defined above 
    f <- CFILE(filename <- tempfile(), "wb") 
    curlPerform(URL=url, [email protected], writefunction=writer, curl=curl) 
    close(f) 
    
+0

dzięki! .., ale gdy uruchomię to w windows - 'setwd (" C:/My Directory "); cwr <- "#include \ n \ nsize_t writer (void * buffer, size_t size, size_t nmemb, void * stream) {\ nfwrite (bufor, size, nmemb, (FILE *) stream); \ ntreściowy rozmiar * nmemb; \ n} "; writeLines (cwr, "curl_writer.c"); shell ("'C: \\ Program Files \\ R \\ R-3.0.0 \\ bin \\ x64 \\ Rcmd.exe' SHLIB -o 'C: \\ Mój katalog \\ curl_writer.dll' 'C : \\ Mój katalog \\ curl_writer.c '")' - otrzymuję 'Nazwa pliku, nazwa katalogu lub składnia etykiety woluminu jest niepoprawna. [[Snip]] wykonanie nie powiodło się z kodem błędu 1' jaki jest pomysł, co jest nie tak? Chcę zachować go w R :) –

+0

'system2 (polecenie =" R ", args =" CMD SHLIB -o curl_writer.dll curl_writer.c ")' zamiast 'powłoki (...)' –

+0

dziękuję jeszcze raz, i przepraszam, jeśli brakuje mi czegoś oczywistego tutaj. 'R' nie jest w mojej PATH, więc użyłem' system2 (command = "C: \\ Program Files \\ R \\ R-3.0.0 \\ bin \\ x64 \\ R.exe ", args =" CMD SHLIB -o curl_writer.dll curl_writer.c ")' ale to dało ostrzeżenie 'działające polecenie '" C: \ Program Files \ R \ R-3.0.0 \ bin \ x64 \ R.exe "CMD SHLIB -o curl_writer.dll curl_writer.c 'miał status 1' i nie utworzył pliku' .dll':/ –