2016-07-02 9 views
27

Próbuję naprawić download automation script że świadczenia publicznie tak, że każdy może łatwo ściągnąć świat R.Jak pobrać plik za pomocą badania ceni pół złamane funkcji javascript asp R

Na tej stronie internetowej - http://www.worldvaluessurvey.org/WVSDocumentationWV4.jsp - łącze do pliku PDF "WVS_2000_Questionnaire_Root" można łatwo pobrać w firefoxie i chrome. Nie mogę się dowiedzieć, jak zautomatyzować pobieranie za pomocą httr lub RCurl lub jakiegokolwiek innego pakietu R. zrzut ekranu poniżej zachowania Chrome Internet. To łącze PDF musi przejść do ostatecznego źródła http://www.worldvaluessurvey.org/wvsdc/DC00012/F00001316-WVS_2000_Questionnaire_Root.pdf, ale jeśli klikniesz ich bezpośrednio, wystąpił błąd połączenia. Jestem jasne, czy jest to związane z nagłówka żądania Upgrade-Insecure-Requests:1 lub kod statusu nagłówka odpowiedzi 302

klikając wokół nowej stronie worldvaluessurvey.org z Chrome Windows Sprawdź elementów otwarty kojarzy mi było kilka hacky decyzje kodowania wykonane tutaj, stąd tytuł semi-zepsute:/

enter image description here

+2

Wow, całkiem imponujące, aby poświęcić prawie całą swoją reputację na jedno pytanie! ;-) – agenis

+1

Heck; Byłbym szczęśliwy mogąc uzyskać pomocną odpowiedź na to pytanie. Jeśli nie otrzymasz rozwiązania i nie przyznasz go w wymaganym terminie, daj mi znać, a ja przygotuję kolejnego 500 przedstawicieli, aby upewnić się, że nie zostanie on wyróżniony. Dziękuję za całą pracę związaną z udostępnianiem publicznych zbiorów danych, Anthony. –

+0

@ 42- wielkie dzięki, doceniam to. odpowiedź "przeglądanie bezgłosu" jest dobra, ale plakat ma rację, że lepiej byłoby tylko w obrębie R. obawiam się, że ktoś da dobrą odpowiedź "RCurl", a następnie ludzie z ankiety światowej zmienią stronę ponownie .. ryzyko zawodowe;) –

Odpowiedz

4

Korzystając ze znakomitej wersji curlconverter, aby naśladować przeglądarkę, można bezpośrednio zażądać pliku pdf.

Najpierw musimy naśladować przeglądarki początkową GET żądanie (może nie być konieczne prosty GET i utrzymanie cookie może wystarczyć):

library(curlconverter) 
library(httr) 
browserGET <- "curl 'http://www.worldvaluessurvey.org/WVSDocumentationWV4.jsp' -H 'Host: www.worldvaluessurvey.org' -H 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1'" 
getDATA <- (straighten(browserGET) %>% make_req)[[1]]() 

JSESSIONID Cookie jest dostępny w getDATA$cookies$value

getPDF <- "curl 'http://www.worldvaluessurvey.org/wvsdc/DC00012/F00001316-WVS_2000_Questionnaire_Root.pdf' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' -H 'Cookie: JSESSIONID=59558DE631D107B61F528C952FC6E21F' -H 'Host: www.worldvaluessurvey.org' -H 'Referer: http://www.worldvaluessurvey.org/AJDocumentationSmpl.jsp' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0'" 
appIP <- straighten(getPDF) 
# replace cookie 
appIP[[1]]$cookies$JSESSIONID <- getDATA$cookies$value 
appReq <- make_req(appIP) 
response <- appReq[[1]]() 
writeBin(response$content, "test.pdf") 

The ciągi curl zostały wyrwane prosto z przeglądarki i curlconverter następnie wykonuje całą pracę.

+0

tak! dziękuję –

+0

@AnthonyDamico: Musimy uzupełnić twój przedstawiciel lub chronić nowego przedstawiciela. Jeśli chcesz, żebym sponsorował pytania, daj mi znać. e-mail, ponieważ zmieniłem moje SO-name z DWin. –

+0

wielkie dzięki! jeśli moje następne pytanie pojawi się zanim moja reputacja się odrodzi, wyślę ci notatkę: D –

0

Twój problem jest prawdopodobnie spowodowany przez kod 302 stanu. Mogę wyjaśnić, co to jest kod 302, ale wygląda na to, że możesz skorzystać z wyjaśnienia całego procesu pobierania:

To właśnie dzieje się, gdy użytkownik kliknie na ten link do pliku PDF.

  1. Zdarzenie onclick javascript jest wyzwalane dla tego łącza. Jeśli klikniesz prawym przyciskiem myszy na link i klikniesz "Sprawdź element", zobaczysz, że istnieje zdarzenie onclick ustawione na "DocDownload ('1316')". inline javascript onclick event.
  2. Jeśli jednak wpiszemy DocDownload do konsoli javascript, przeglądarka poinformuje nas, że DocDownload nie istnieje jako funkcja. enter image description here
  3. Dzieje się tak dlatego, że link do pliku PDF znajduje się wewnątrz ramki iframe wewnątrz okna enter image description here. Konsola dev w przeglądarce dostęp tylko zmiennych/funkcji
+2

dzięki. Pytanie brzmi: w jaki sposób można pobrać plik za pomocą R? –

3

Patrząc na kod funkcji DocDownload, są one przede wszystkim właśnie robi Posta do /AJDownload.jsp z params post ulthost: WVS, CndWAVE: 4, SAID: 0, DOID: (tutaj id id), AJArchive: Archiwum danych WVS. Nie jestem pewien, czy niektóre z nich są wymagane, ale prawdopodobnie najlepiej je uwzględnić.

robi, że w R stosując httr, wyglądałby mniej więcej tak

r <- POST("http://www.worldvaluessurvey.org/AJDownload.jsp", body = list("ulthost" = "WVS", "CndWAVE" = 4, "SAID" = 0, "DOID" = 1316, "AJArchive" = "WVS Data Archive")) 

AJDownload.asp końcowy zwróci 302 (przekierowanie do rzeczywistego URL), a biblioteka httr powinien automatycznie podążają za przekierowanie ty. Dzięki próbom i błędom ustaliłem, że serwer wymaga zarówno nagłówków Content-Type, jak i Cookie, w przeciwnym razie zwróci pustą odpowiedź 400 (OK). Będziesz musiał pobrać prawidłowy plik cookie, który możesz znaleźć, sprawdzając ładowanie dowolnej strony do tego serwera i poszukaj nagłówka z plikiem Cookie: JSESSIONID = ....., będziesz chciał skopiować cały nagłówek

więc z tych, w, wygląda

r <- POST("http://www.worldvaluessurvey.org/AJDownload.jsp", body = list("ulthost" = "WVS", "CndWAVE" = 4, "SAID" = 0, "DOID" = 1316, "AJArchive" = "WVS Data Archive"), add_headers("Content-Type" = "application/x-www-form-urlencoded", "Cookie" = "[PASTE COOKIE VALUE HERE]")) 

odpowiedź będzie binarne dane pdf, więc trzeba będzie zapisać go do pliku, który ma być w stanie nic zrobić z nim.

bin <- content(r, "raw") 
writeBin(bin, "myfile.txt") 

EDIT:

Dobra, trochę czasu, aby faktycznie uruchomić kod. Odkryłem również minimalne wymagane parametry dla wywołań POST, czyli tylko docid, cookie JSESSIONID i nagłówek Referer.

library(httr) 
download_url <- "http://www.worldvaluessurvey.org/AJDownload.jsp" 
frame_url <- "http://www.worldvaluessurvey.org/AJDocumentationSmpl.jsp" 
body <- list("DOID" = "1316") 

file_r <- POST(download_url, body = body, encode = "form", 
      set_cookies("JSESSIONID" = "0E657C37FF030B41C33B7D2B1DCAB3D8"), 
      add_headers("Referer" = frame_url), 
      verbose()) 

To działało na moim komputerze i poprawnie zwraca dane binarne PDF.

Tak się dzieje, jeśli ręcznie ustawię plik cookie z mojej przeglądarki. Używam tylko części JSESSIONID pliku cookie i nic więcej. Jak wspomniałem wcześniej, JSESSIONID wygaśnie, prawdopodobnie z powodu wieku lub braku aktywności. success_image

+0

dziękuję, ale spróbowałem twojego przykładu na kilka różnych sposobów i żaden z nich nie zadziałał? 'biblioteka (httr); r <- POST ("http://www.worldvaluessurvey.org/AJDownload.jsp", body = list ("ulthost" = "WVS", "CndWAVE" = 4, "SAID" = 0, "DOID" = 1316 , "AJArchive" = "Archiwum danych WVS")); x <- POST ("http://www.worldvaluessurvey.org/AJDownload.jsp", body = list ("ulthost" = "WVS", "CndWAVE" = 4, "SAID" = 0, "DOID" = 1316 "AJArchive" = "Archiwum danych WVS"), add_headers ("Content-Type" = "application/x-www-form-urlencoded", "JSESSIONID" = cookie (r) $ value)); x $ content' –

+0

Zaktualizowałem kod, który uruchomiłem lokalnie i działałem. Wypróbuj zmiany. Należy również zauważyć, że plik cookie JSESSIONID może i wygaśnie. Więc będziesz chciał upewnić się, że używasz ostatnio używanego. Aby jeszcze bardziej zautomatyzować w przyszłości, możesz najpierw poprosić o stronę (np. Aukcję lub nawet stronę główną), a następnie wyodrębnić plik cookie z odpowiedzi. –

+0

Przykro mi, twój przykład wciąż nie działa dla mnie? czy mógłbyś poprawić swoją odpowiedź, aby zautomatyzować proces (w tym pobranie wartości 'r $ cookie $ value ') od początku do końca i działać czysto w świeżej sesji R? –

6

Miałem do czynienia z tego typu rzeczami w przeszłości. Moim rozwiązaniem było użycie programu headless browser do programowej nawigacji i manipulowania stronami internetowymi, które zawierały zasoby, którymi byłem zainteresowany. Wykonałem nawet nie proste zadania, takie jak logowanie i wypełnianie i przesyłanie formularzy przy użyciu tej metody.

Widzę, że próbujesz użyć czystej metody R, aby pobrać te pliki, modyfikując odwrotnie żądania GET/POST generowane przez łącze. Może to zadziałać, ale Twoja implementacja będzie bardzo podatna na wszelkie przyszłe zmiany w projekcie witryny, takie jak zmiany w obsłudze zdarzeń JavaScript, przekierowania adresów URL lub wymagania nagłówka.

Korzystając z przeglądarki bezgłowej, można ograniczyć ekspozycję na adres URL najwyższego poziomu i kilka minimalnych zapytań XPath, które umożliwiają nawigację do łącza docelowego. To prawda, że ​​nadal wiąże to twój kod z bezumownymi i dość wewnętrznymi szczegółami projektu strony, ale z pewnością jest mniej ekspozycji. Jest to zagrożenie związane ze skrobaniem wstęgi.


Zawsze używane biblioteki Java HtmlUnit dla mojego bezgłowe przeglądania, co mam okazało się być całkiem dobre. Oczywiście, aby skorzystać z rozwiązania opartego na języku Java z Rland, konieczne byłoby utworzenie procesu Java, który wymagałby (1) zainstalowania Javy na komputerze użytkownika, (2) $CLASSPATH, aby był poprawnie skonfigurowany w celu zlokalizowania JARów HtmlUnit jako jak również twoja niestandardowa główna biblioteka pobierania plików i (3) właściwe wywołanie komendy Java z poprawnymi argumentami za pomocą jednej z metod łuskania R do komendy systemowej. Nie trzeba dodawać, że jest to dość zaangażowane i niechlujne.

Czyste rozwiązanie do przeglądania bezgłowego R byłoby fajne, ale niestety wygląda na to, że R nie oferuje żadnego rozwiązania do przeglądania bezgłowego przeglądarki. Najbliższy jest RSelenium, który wydaje się być tylko wiązaniem R z biblioteką klienta Java oprogramowania automatyzacji przeglądarki Selenium. Oznacza to, że nie będzie działać niezależnie od przeglądarki GUI użytkownika i wymaga interakcji z zewnętrznym procesem Java (mimo że w tym przypadku szczegóły interakcji są wygodnie umieszczane pod interfejsem API RSelenium).


Korzystanie HtmlUnit, Utworzyłem dość ogólny główne klasy Java, które można wykorzystać, aby pobrać plik, klikając na link na stronie internetowej. Parametryzacja aplikacji wygląda następująco:

  • Adres URL strony.
  • Opcjonalna sekwencja wyrażeń XPath umożliwiająca zstępowanie do dowolnej liczby ramek zagnieżdżonych, począwszy od strony najwyższego poziomu.Uwaga: faktycznie sparowałem to z argumentem URL, dzieląc na \s*>\s*, który podoba mi się jako zwięzła składnia. Użyłem znaku >, ponieważ nie jest poprawny w adresach URL.
  • Pojedyncze wyrażenie XPath, które określa link zakotwiczenia do kliknięcia.
  • Opcjonalna nazwa pliku, pod którą należy zapisać pobrany plik. Jeśli zostanie pominięty, zostanie wyprowadzony z nagłówka Content-Disposition, którego wartość jest zgodna ze wzorcem filename="(.*)" (był to nietypowy przypadek, który napotkałem podczas skrobania ikon z powrotem) lub, w przeciwnym razie, nazwa podstawowego adresu URL żądania, który wywołał odpowiedź strumienia pliku . Metoda pochodna basename działa dla twojego linku docelowego.

Oto kod:

package com.bgoldst; 

import java.util.List; 
import java.util.ArrayList; 

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.IOException; 

import java.util.regex.Pattern; 
import java.util.regex.Matcher; 

import com.gargoylesoftware.htmlunit.WebClient; 
import com.gargoylesoftware.htmlunit.BrowserVersion; 
import com.gargoylesoftware.htmlunit.ConfirmHandler; 
import com.gargoylesoftware.htmlunit.WebWindowListener; 
import com.gargoylesoftware.htmlunit.WebWindowEvent; 
import com.gargoylesoftware.htmlunit.WebResponse; 
import com.gargoylesoftware.htmlunit.WebRequest; 
import com.gargoylesoftware.htmlunit.util.NameValuePair; 
import com.gargoylesoftware.htmlunit.Page; 
import com.gargoylesoftware.htmlunit.html.HtmlPage; 
import com.gargoylesoftware.htmlunit.html.HtmlAnchor; 
import com.gargoylesoftware.htmlunit.html.BaseFrameElement; 

public class DownloadFileByXPath { 

    public static ConfirmHandler s_downloadConfirmHandler = null; 
    public static WebWindowListener s_downloadWebWindowListener = null; 
    public static String s_saveFile = null; 

    public static void main(String[] args) throws Exception { 

     if (args.length < 2 || args.length > 3) { 
      System.err.println("usage: {url}[>{framexpath}*] {anchorxpath} [{filename}]"); 
      System.exit(1); 
     } // end if 
     String url = args[0]; 
     String anchorXPath = args[1]; 
     s_saveFile = args.length >= 3 ? args[2] : null; 

     // parse the url argument into the actual URL and optional subsequent frame xpaths 
     String[] fields = Pattern.compile("\\s*>\\s*").split(url); 
     List<String> frameXPaths = new ArrayList<String>(); 
     if (fields.length > 1) { 
      url = fields[0]; 
      for (int i = 1; i < fields.length; ++i) 
       frameXPaths.add(fields[i]); 
     } // end if 

     // prepare web client to handle download dialog and stream event 
     s_downloadConfirmHandler = new ConfirmHandler() { 
      public boolean handleConfirm(Page page, String message) { 
       return true; 
      } 
     }; 
     s_downloadWebWindowListener = new WebWindowListener() { 
      public void webWindowContentChanged(WebWindowEvent event) { 

       WebResponse response = event.getWebWindow().getEnclosedPage().getWebResponse(); 

       //System.out.println(response.getLoadTime()); 
       //System.out.println(response.getStatusCode()); 
       //System.out.println(response.getContentType()); 

       // filter for content type 
       // will apply simple rejection of spurious text/html responses; could enhance this with command-line option to whitelist 
       String contentType = response.getResponseHeaderValue("Content-Type"); 
       if (contentType.contains("text/html")) return; 

       // determine file name to use; derive dynamically from request or response headers if not specified by user 
       // 1: user 
       String saveFile = s_saveFile; 
       // 2: response Content-Disposition 
       if (saveFile == null) { 
        Pattern p = Pattern.compile("filename=\"(.*)\""); 
        Matcher m; 
        List<NameValuePair> headers = response.getResponseHeaders(); 
        for (NameValuePair header : headers) { 
         String name = header.getName(); 
         String value = header.getValue(); 
         //System.out.println(name+" : "+value); 
         if (name.equals("Content-Disposition")) { 
          m = p.matcher(value); 
          if (m.find()) 
           saveFile = m.group(1); 
         } // end if 
        } // end for 
        if (saveFile != null) saveFile = sanitizeForFileName(saveFile); 
        // 3: request URL 
        if (saveFile == null) { 
         WebRequest request = response.getWebRequest(); 
         File requestFile = new File(request.getUrl().getPath()); 
         saveFile = requestFile.getName(); // just basename 
        } // end if 
       } // end if 

       getFileResponse(response,saveFile); 

      } // end webWindowContentChanged() 
      public void webWindowOpened(WebWindowEvent event) {} 
      public void webWindowClosed(WebWindowEvent event) {} 
     }; 

     // initialize browser 
     WebClient webClient = new WebClient(BrowserVersion.FIREFOX_45); 
     webClient.getOptions().setCssEnabled(false); 
     webClient.getOptions().setJavaScriptEnabled(true); // required for JavaScript-powered links 
     webClient.getOptions().setThrowExceptionOnScriptError(false); 
     webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); 

     // 1: get home page 
     HtmlPage page; 
     try { page = webClient.getPage(url); } catch (IOException e) { throw new Exception("error: could not get URL \""+url+"\".",e); } 
     //page.getEnclosingWindow().setName("main window"); 

     // 2: navigate through frames as specified by the user 
     for (int i = 0; i < frameXPaths.size(); ++i) { 
      String frameXPath = frameXPaths.get(i); 
      List<?> elemList = page.getByXPath(frameXPath); 
      if (elemList.size() != 1) throw new Exception("error: frame "+(i+1)+" xpath \""+frameXPath+"\" returned "+elemList.size()+" elements on page \""+page.getTitleText()+"\" >>>\n"+page.asXml()+"\n<<<."); 
      if (!(elemList.get(0) instanceof BaseFrameElement)) throw new Exception("error: frame "+(i+1)+" xpath \""+frameXPath+"\" returned a non-frame element on page \""+page.getTitleText()+"\" >>>\n"+page.asXml()+"\n<<<."); 
      BaseFrameElement frame = (BaseFrameElement)elemList.get(0); 
      Page enclosedPage = frame.getEnclosedPage(); 
      if (!(enclosedPage instanceof HtmlPage)) throw new Exception("error: frame "+(i+1)+" encloses a non-HTML page."); 
      page = (HtmlPage)enclosedPage; 
     } // end for 

     // 3: get the target anchor element by xpath 
     List<?> elemList = page.getByXPath(anchorXPath); 
     if (elemList.size() != 1) throw new Exception("error: anchor xpath \""+anchorXPath+"\" returned "+elemList.size()+" elements on page \""+page.getTitleText()+"\" >>>\n"+page.asXml()+"\n<<<."); 
     if (!(elemList.get(0) instanceof HtmlAnchor)) throw new Exception("error: anchor xpath \""+anchorXPath+"\" returned a non-anchor element on page \""+page.getTitleText()+"\" >>>\n"+page.asXml()+"\n<<<."); 
     HtmlAnchor anchor = (HtmlAnchor)elemList.get(0); 

     // 4: click the target anchor with the appropriate confirmation dialog handler and content handler 
     webClient.setConfirmHandler(s_downloadConfirmHandler); 
     webClient.addWebWindowListener(s_downloadWebWindowListener); 
     anchor.click(); 
     webClient.setConfirmHandler(null); 
     webClient.removeWebWindowListener(s_downloadWebWindowListener); 

     System.exit(0); 

    } // end main() 

    public static void getFileResponse(WebResponse response, String fileName) { 

     InputStream inputStream = null; 
     OutputStream outputStream = null; 

     // write the inputStream to a FileOutputStream 
     try { 

      System.out.print("streaming file to disk..."); 

      inputStream = response.getContentAsStream(); 

      // write the inputStream to a FileOutputStream 
      outputStream = new FileOutputStream(new File(fileName)); 

      int read = 0; 
      byte[] bytes = new byte[1024]; 

      while ((read = inputStream.read(bytes)) != -1) 
       outputStream.write(bytes, 0, read); 

      System.out.println("done"); 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (inputStream != null) { 
       try { 
        inputStream.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } // end try-catch 
      } // end if 
      if (outputStream != null) { 
       try { 
        //outputStream.flush(); 
        outputStream.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } // end try-catch 
      } // end if 
     } // end try-catch 

    } // end getFileResponse() 

    public static String sanitizeForFileName(String unsanitizedStr) { 
     return unsanitizedStr.replaceAll("[^\040-\176]","_").replaceAll("[/\\<>|:*?]","_"); 
    } // end sanitizeForFileName() 

} // end class DownloadFileByXPath 

Poniżej znajduje się demo mnie działa główne klasy w moim systemie. Wycinałem większość pełnych wyników HtmlUnit. Wyjaśnię później argumenty wiersza poleceń.

ls; 
## bin/ src/ 
CLASSPATH="bin;C:/cygwin/usr/local/share/htmlunit-latest/*" java com.bgoldst.DownloadFileByXPath "http://www.worldvaluessurvey.org/WVSDocumentationWV4.jsp > //iframe[@id='frame1'] > //iframe[@id='frameDoc']" "//a[contains(text(),'WVS_2000_Questionnaire_Root')]"; 
## Jul 10, 2016 1:34:34 PM com.gargoylesoftware.htmlunit.IncorrectnessListenerImpl notify 
## WARNING: Obsolete content type encountered: 'application/x-javascript'. 
## Jul 10, 2016 1:34:34 PM com.gargoylesoftware.htmlunit.IncorrectnessListenerImpl notify 
## WARNING: Obsolete content type encountered: 'application/x-javascript'. 
## 
## ... snip ... 
## 
## Jul 10, 2016 1:34:45 PM com.gargoylesoftware.htmlunit.IncorrectnessListenerImpl notify 
## WARNING: Obsolete content type encountered: 'text/javascript'. 
## streaming file to disk...done 
## 
ls; 
## bin/ F00001316-WVS_2000_Questionnaire_Root.pdf* src/ 
  • CLASSPATH="bin;C:/cygwin/usr/local/share/htmlunit-latest/*" Tutaj ustawić $CLASSPATH dla mojego systemu za pomocą prefiksu zmiennej przypisania (uwaga: byłem uruchomiony w powłoki bash Cygwin). Plik .class skompilowałem do bin i zainstalowałem JARy HtmlUnit w mojej strukturze katalogów systemu Cygwin, co jest prawdopodobnie nieco niezwykłe.
  • java com.bgoldst.DownloadFileByXPath Oczywiście jest to słowo polecenia i nazwa głównej klasy do wykonania.
  • "http://www.worldvaluessurvey.org/WVSDocumentationWV4.jsp > //iframe[@id='frame1'] > //iframe[@id='frameDoc']" To jest wyrażenie XPath i ramki. Twój link docelowy jest zagnieżdżony w dwóch elementach iframe, co wymaga dwóch wyrażeń XPath. Możesz znaleźć atrybuty id w źródle, przeglądając surowy HTML lub używając narzędzia do tworzenia stron internetowych (Firebug jest moim ulubionym).
  • "//a[contains(text(),'WVS_2000_Questionnaire_Root')]" Wreszcie, jest to rzeczywiste wyrażenie XPath dla linku docelowego wewnątrz wewnętrznego elementu iframe.

Pominąłem argument nazwy pliku. Jak widać, kod poprawnie wyprowadził nazwę pliku z adresu URL żądania.


uznaję, że jest to dużo trudu, aby przejść, aby pobrać plik, ale dla sieci skrobanie w ogóle, naprawdę myślę tylko solidne i opłacalne podejście jest iść Jak ugryźć i używać pełny bezgłowy silnik przeglądarki. Najlepiej jest całkowicie oddzielić zadanie pobierania tych plików od Rlanda, a zamiast tego zaimplementować cały system skrobania przy użyciu aplikacji Java, może być uzupełniony o kilka skryptów powłoki dla bardziej elastycznego interfejsu. Jeśli nie pracujesz z adresami URL pobierania, które zostały zaprojektowane z myślą o prostych żądaniach HTTP klientów takich jak curl, wget i R, używanie R do skrobania w sieci prawdopodobnie nie jest dobrym pomysłem. To są moje dwa centy.

Powiązane problemy