WebClient зависает до истечения времени ожидания - PullRequest
0 голосов
/ 20 декабря 2018

Я пытаюсь загрузить веб-страницу с помощью WebClient, но она зависает, пока не истечет время ожидания в WebClient, а затем завершается с ошибкой.

Следующий код не будет работать

WebClient client = new WebClient();
string url = "https://www.nasdaq.com/de/symbol/aapl/dividend-history";
string page = client.DownloadString(url);

При использовании другого URL-адреса передача работает нормально.Например,

WebClient client = new WebClient();
string url = "https://www.ariva.de/apple-aktie";
string page = client.DownloadString(url);

завершается очень быстро и содержит весь html в переменной страницы.

Использование HttpClient или WebRequest / WebResponse дает тот же результат для первого URL: блок до исключения тайм-аута.

Оба URL-адреса нормально загружаются в браузере, примерно за 2-5 секунд.Любая идея, в чем заключается проблема и какое решение доступно?

Я заметил, что при использовании элемента управления WebBrowser в диалоговом окне Windows Forms первый URL-адрес загружается с более чем 20 ошибками JavaScript, которые необходимо нажать для подтверждения.То же самое можно наблюдать, когда инструменты разработчика открыты в браузере при доступе к первому URL.

Однако WebClient НЕ действует на возвращаемый им доход.Он не запускает JavaScript и не загружает ссылочные изображения, CSS или другие сценарии, поэтому это не должно быть проблемой.

Спасибо!

Ralf

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

Первый сайт, "https://www.nasdaq.com/de/symbol/aapl/dividend-history";, требует:

Значение User-agent здесь важно.Если в WebRequest.UserAgent указан недавний User-agent, веб-сайт активирует протокол Http 2.0 и HSTS (HTTP Strict Transport Security)), которые поддерживаются / понимаютсятолько недавними браузерами (например, FireFox 56 или новее).

Использование менее современного браузера в качестве User-agent необходимо, в противном случае веб-сайт будет ожидать (и ждать) динамическую 1039.* ответ.Используя старше User-agent, веб-сайт активирует протокол Http 1.1.

Второй сайт, "https://www.ariva.de/apple-aktie";, требует:

  • ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
  • Проверка сертификата сервера не требуется
  • Нет конкретного пользователя-требуется агент

Я предлагаю настроить WebRequest (или соответствующую настройку HttpClient) следующим образом:
(WebClient может работать, но, вероятно, потребуется производныйПользовательский элемент управления)

private async void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false;
    Uri uri = new Uri("https://www.nasdaq.com/de/symbol/aapl/dividend-history");
    string destinationFile = "[Some Local File]";
    await HTTPDownload(uri, destinationFile);
    button1.Enabled = true;
}


CookieContainer httpCookieJar = new CookieContainer();

//The 32bit IE11 header is the User-agent used here
public async Task HTTPDownload(Uri resourceURI, string filePath)
{
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
    ServicePointManager.ServerCertificateValidationCallback += (s, cert, ch, sec) => { return true; };
    ServicePointManager.DefaultConnectionLimit = 50;

    HttpWebRequest httpRequest = WebRequest.CreateHttp(resourceURI);

    try
    {
        httpRequest.CookieContainer = httpCookieJar;
        httpRequest.Timeout = (int)TimeSpan.FromSeconds(15).TotalMilliseconds;
        httpRequest.AllowAutoRedirect = true;
        httpRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
        httpRequest.ServicePoint.Expect100Continue = false;
        httpRequest.UserAgent = "Mozilla / 5.0(Windows NT 6.1; WOW32; Trident / 7.0; rv: 11.0) like Gecko";
        httpRequest.Accept = "ext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        httpRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate;q=0.8");
        httpRequest.Headers.Add(HttpRequestHeader.CacheControl, "no-cache");

        using (HttpWebResponse httpResponse = (HttpWebResponse)await httpRequest.GetResponseAsync())
        using (Stream responseStream = httpResponse.GetResponseStream())
        {
            if (httpResponse.StatusCode == HttpStatusCode.OK)
            {
                try
                {
                    int buffersize = 132072;
                    using (FileStream fileStream = File.Create(filePath, buffersize, FileOptions.Asynchronous))
                    {
                        int read;
                        byte[] buffer = new byte[buffersize];
                        while ((read = await responseStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
                        {
                            await fileStream.WriteAsync(buffer, 0, read);
                        }
                    };
                }
                catch (DirectoryNotFoundException) { /* Log or throw */}
                catch (PathTooLongException) { /* Log or throw */}
                catch (IOException) { /* Log or throw */}
            }
        };
    }
    catch (WebException) { /* Log and message */} 
    catch (Exception) { /* Log and message */}
}

Первый веб-сайт (nasdaq.com) возвратил длину полезной нагрузки 101.562 байт
Второй веб-сайт (www.ariva.de) возвратил длину полезной нагрузки 56.919 байт

0 голосов
/ 20 декабря 2018

Очевидно, что существует проблема с загрузкой этой ссылки (неверный URL, неавторизованный доступ, ...), однако вы можете использовать асинхронный метод для решения проблемы с носками:

  WebClient client = new WebClient();
  client.DownloadStringCompleted += (s, e) =>
  {
       //here deal with downloaded file
  };
  client.DownloadStringAsync(url);
...