1 Востаннє редагувалося Chemist-i (16.05.2018 21:21:20)

Тема: [Вирішено] проблема з парсингом веб-сторінки

Привіт усім. Допоможіть вирішити проблему.
Є код на C#, це відкриття доступу до web-сторінки та закачка кода в стрингову змінну. Все добре працювало з 2012 року. Але тиждень тому програма почала виснути на рядку з GetResponse. Чи може це буди пов'язаено з тим, что на сайті встановили якийсь захист від ботів, як це перевірити?
Ось код:
URL - це стринговая зміння, яка змінюється в циклі. Для приміру URL = "https://www.accuweather.com/en/us/st-pa … view=table"

КОД:

HttpWebRequest proxy_request = (HttpWebRequest)WebRequest.Create(URL);
proxy_request.Credentials = System.Net.CredentialCache.DefaultCredentials;
proxy_request.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
proxy_request.Method = "GET";
proxy_request.ContentType = "application/x-www-form-urlencoded";
proxy_request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/532.5
(KHTML, like Gecko)  Chrome/4.0.249.89 Safari/532.5";
proxy_request.KeepAlive = true;
HttpWebResponse resp = proxy_request.GetResponse() as HttpWebResponse; // <--
string html = "";
using (StreamReader sr = new StreamReader(resp.GetResponseStream(), Encoding.GetEncoding(1251)))
html = sr.ReadToEnd();
resp.Close();

Chemist-i: Для коду, використовуйте будь ласка теґ code

Подякували: leofun011

2 Востаннє редагувалося Chemist-i (16.05.2018 21:21:47)

Re: [Вирішено] проблема з парсингом веб-сторінки

Я також для перевірки спробувала закачати код сторінки через WebClient в richTextBox1. Та сторінка, яка мені потрібна не завантажується (https://www.accuweather.com/en/us/st-pa … view=table), а інші нормально завантажуються. Хтось може допомогти розібратися?

WebClient wc = new WebClient();
string answer = wc.DownloadString(
    "https://www.accuweather.com/en/us/st-paul-mn/55102/may-weather/348795?monyr=5/1/2018&view=table"
);
richTextBox1.AppendText(answer);

Chemist-i: Для коду, використовуйте будь ласка теґ code

3

Re: [Вирішено] проблема з парсингом веб-сторінки

в клієнті є підтримка HTTPS?
Взагалі важко щось сказати. Дайте, будь ласка, більше інформації: код (модуль цілком), які повідомлення виводяться (замість "не завантажується"), до яких серверів ви намагаєтеся підключитися крім того який "не завантажується"?
Як я розумію ваш HTTP-клієнт надсилає запит і просто зберігає відповідь (html-файл, наприклад)?

4

Re: [Вирішено] проблема з парсингом веб-сторінки

Ольга написав:

Все добре працювало з 2012 року. Але тиждень тому програма почала виснути на рядку з GetResponse.
Для приміру URL = "https://www.accuweather.com/en/us/st-pa … view=table"

За вказаним URL'ом клієнт отримує не валідний html. Це камінь в сторону розробників того сайту. Але схоже, що проблема не в цьому.

LoganRoss написав:

в клієнті є підтримка HTTPS?
Взагалі важко щось сказати. Дайте, будь ласка, більше інформації: код (модуль цілком), які повідомлення виводяться (замість "не завантажується"), до яких серверів ви намагаєтеся підключитися крім того який "не завантажується"?

Я спробував розібратися, в чому проблема і ще не розібрався, але :

  1. .NET по замовчуванню дозволяє працювати з HTTPS. Сертифікат дійсний. Проблема не тут.

  2. Весь необхідний для відтворення зависання код Ольга надала.

  3. Повідомлення не виводяться. Exception'ів немає. Воно реально "не завантажується", просто висить на функції GetResponse() так, наче вона успішно працює і не може завершити роботу.

LoganRoss написав:

Як я розумію ваш HTTP-клієнт надсилає запит і просто зберігає відповідь (html-файл, наприклад)?

Правильно. Але до ReadToEnd() діло не доходить.

Шукаю рішення...

Подякували: LoganRoss1

5

Re: [Вирішено] проблема з парсингом веб-сторінки

На сервері, ймовірно, працює модуль, який змушує сервер ігнорувати запити, які не схожі на запити сучасних браузерів.
Несхожість може проявлятись в { наявності | відсутності | послідовності } деяких заголовків запиту.
System.Net.HttpWebRequest зберігає заголовки запиту в тій послідовності, в якій вони були задані в ході виконання програми.
В прикладі нижче я впорядкував заголовки так, як це робить Opera і воно запрацювало.

Робочий код :

var proxy_request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(
    "https://www.accuweather.com/en/us/st-paul-mn/55102/may-weather/348795?monyr=5/1/2018&view=table"
);
proxy_request.Credentials = System.Net.CredentialCache.DefaultCredentials;
proxy_request.Method = "GET";
proxy_request.ProtocolVersion = System.Net.HttpVersion.Version11;
proxy_request.Timeout = 5000;    // <-- щоб не було зависання.
proxy_request.KeepAlive = true;
proxy_request.Headers.Add("Upgrade-Insecure-Requests", "1");
proxy_request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36"
    + " (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36 OPR/52.0.2871.42";
proxy_request.Accept = "application/xhtml+xml;q=1,text/html;q=0.9,application/xml;q=0.8,*/*;q=0.7";
proxy_request.Headers.Add("Accept-Encoding", "gzip, deflate, br");
proxy_request.Headers.Add("Accept-Language", "uk,en;q=0.8,en-US;q=0.7");
// Щоб можна було переглянути вміст :
proxy_request.AutomaticDecompression = System.Net.DecompressionMethods.GZip;
// Щоб не було проблем з сертифікатом :
System.Net.ServicePointManager.ServerCertificateValidationCallback = (
    object sender,
    System.Security.Cryptography.X509Certificates.X509Certificate certificate,
    System.Security.Cryptography.X509Certificates.X509Chain chain,
    System.Net.Security.SslPolicyErrors sslPolicyErrors
    ) => true;
//
string html = "";
try {
    using(var resp = proxy_request.GetResponse() as System.Net.HttpWebResponse) {
        using(var sr = new System.IO.StreamReader(
                resp.GetResponseStream(), System.Text.Encoding.GetEncoding(1251)
            )) {
            html = sr.ReadToEnd();
            sr.Close();
        }
        resp.Close();
    }
}
catch(System.Net.WebException webEx) {
    MessageBox.Show(webEx.Message, "WebException");
}

Повідомте, чи це допомогло.

І ще кілька порад :
1) Завжди встановлюйте Timeout.
2) Обгортайте IDisposable елементи using'ом.
3) Закривайте потоки після читання.
4) Використовуйте try, щоб обгорнути місця, де можуть вискочити Exception'и.

Подякували: FakiNyan, PRY2

6

Re: [Вирішено] проблема з парсингом веб-сторінки

Вставила останній код замість мого, програма запрацювала. Дуже дякую за допомогу:)