2016-08-10 2 views
1

Ich versuche, die Wetterdaten von BOM Australia zu bekommen. Der manuelle Weg ist, zu gehen http://www.bom.gov.au/jsp/ncc/cdio/weatherData/av?p_nccObsCode=136&p_display_type=dailyDataFile&p_startYear=&p_c=&p_stn_num=2064 und klicken Sie auf "Alle Jahre der Daten", und es lädt die Datei herunter!Datei von einem dynamisch generierten Link herunterladen, der im Quellcode eines HTML liegt

Hier ist, was ich habe versucht, dies zu automatisieren:

using (WebClient client = new WebClient()) 
      { 

       string html = client.DownloadString("http://www.bom.gov.au/jsp/ncc/cdio/weatherData/av?p_nccObsCode=136&p_display_type=dailyDataFile&p_startYear=&p_c=&p_stn_num=2064"); 


       List<string> list = LinkExtractor.Extract(html); 
       foreach (var link in list) 
       { 
        if (link.StartsWith("/jsp/ncc/cdio/weatherData/av?p_display_type=dailyZippedDataFile")) 
        { 

         string resource = "http://www.bom.gov.au" + link; 
         MessageBox.Show(resource); 


         client.DownloadFileAsync(new Uri(resource), Dts.Connections["data.zip"].ConnectionString); 
         break; 
        } 
       } 




      } 

nicht über die linkExtractor Sorgen Sie sich, es funktioniert wie ich in der Lage bin den Link, um zu sehen, der die Datei gibt. Das Problem besteht darin, dass 'DownloadFileAsync' eine neue Anfrage erstellt, die die Datei nicht herunterladen lässt, da die Datei dieselbe Sitzung benötigt.

Gibt es eine Möglichkeit, das kann ich tun? Bitte wenden Sie sich für weitere Erläuterungen.

UPDATE:

Hier sind die Änderungen, die ich gemacht, Cookies von HttpWebRequest verwendet. Ich kann die Datei jedoch immer noch nicht herunterladen.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.bom.gov.au/jsp/ncc/cdio/weatherData/av?p_nccObsCode=136&p_display_type=dailyDataFile&p_startYear=&p_c=&p_stn_num=2064"); 
      request.CookieContainer = new CookieContainer(); 

      HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 

      foreach (Cookie cook in response.Cookies) 
      { 
       MessageBox.Show(cook.ToString()); 
      } 

      if (response.StatusCode == HttpStatusCode.OK) 
      { 
       Stream receiveStream = response.GetResponseStream(); 
       StreamReader readStream = null; 

       if (response.CharacterSet == null) 
       { 
        readStream = new StreamReader(receiveStream); 
       } 
       else 
       { 
        readStream = new StreamReader(receiveStream, Encoding.GetEncoding(response.CharacterSet)); 
       } 

       string data = readStream.ReadToEnd(); 



       using (WebClient client = new WebClient()) 
       { 
        foreach (Cookie cook in response.Cookies) 
        { 
         MessageBox.Show(cook.ToString()); 
         client.Headers.Add(HttpRequestHeader.Cookie, cook.ToString()); 
        } 

        List<string> list = LinkExtractor.Extract(data); 
        foreach (var link in list) 
        { 
         if (link.StartsWith("/jsp/ncc/cdio/weatherData/av?p_display_type=dailyZippedDataFile")) 
         { 

          string initial = "http://www.bom.gov.au" + link; 
          MessageBox.Show(initial); 

          //client.Headers.Add(HttpRequestHeader.Cookie, "JSESSIONID=2EBAFF7EFE2EEFE8140118CE5170B8F6"); 
          client.DownloadFile(new Uri(initial), Dts.Connections["data.zip"].ConnectionString); 
          break; 
         } 
        } 




       } 

       response.Close(); 
       readStream.Close(); 
      } 
+0

Können Sie bitte erläutern, wie die Verwendung von Cookies helfen würde, da keine Benutzeranmeldeinformationen zum Durchsuchen der Website erforderlich sind? –

+0

Da einige Websites sich um ihren Inhalt kümmern und einige Maßnahmen ergreifen, um das einfache Scraping zu verhindern. Einige benötigen möglicherweise einen Sitzungscookie, andere erzeugen eindeutige URLs auf jedem GET, einige benötigen einen Referrer, einige führen Javascript aus und führen einige Ajax-Anfragen aus. Wenn Sie die Datei mit einem Browser erfolgreich herunterladen können, müssen Sie dies nur nachahmen. Der Webclient wird das nicht alleine machen. Verwenden Sie die Entwicklerkonsole Ihres Browsers, um herauszufinden, was bei nachfolgenden http-Anrufen benötigt wird. – rene

+0

Die Konsole zeigt dies, wenn ich auf die Datei herunterlade: Ressource interpretiert als Dokument, aber mit MIME-Typ application/zip übertragen: "http://www.bom.gov.au/jsp/ncc/cdio/weatherData/av ? p_display_type = dailyZippedDataFile & p_stn_num = 2064 & p_c = -938623 & p_nccObsCode = 136 & p_startYear = 2016 ". –

Antwort

2

Der HTML-Code, den Sie erhalten, und die URLs, die darin enthalten sind, sind HtmlEncoded. Das macht, dass, wenn Sie die URL aus dem HTML-Teilstring subtrahieren, Sie es idealerweise decodieren müssen. Dies ist, was die Download-URL für die zip wie folgt aussieht:

/jsp/ncc/cdio/weatherData/av?p_display_type=dailyZippedDataFile&amp;p_stn_num=2064&amp;p_c=-938623&amp;p_nccObsCode=136&amp;p_startYear=2016 

Es Hilfsklasse ist die Decodierung für uns zu tun: WebUtility

Dieser Code die Zip-Datei nicht herunterladen:

using (var client = new WebClient()) 
{ 
    var url = "http://www.bom.gov.au/jsp/ncc/cdio/weatherData/av?p_nccObsCode=136&p_display_type=dailyDataFile&p_startYear=&p_c=&p_stn_num=2064";  
    string html = client.DownloadString(url); 

    var pos = html.IndexOf("/jsp/ncc/cdio/weatherData/av?p_display_type=dailyZippedDataFile"); 
    var endpos = html.IndexOf('"', pos); 
    string link = html.Substring(pos, endpos - pos); 

    var decodedLink = WebUtility.HtmlDecode(link); 
    string resource = "http://www.bom.gov.au" + decodedLink;      


    client.DownloadFile(new Uri(resource), @"c:\temp\bom2.zip"); 

} 

In diesem Fall müssen Sie die Cookies nicht behalten, aber Sie müssen vorsichtig mit den URLs sein, die Sie analysieren.

+0

Verdammt! Das habe ich nicht einmal bemerkt. Danke Mann, es funktioniert. –

Verwandte Themen