Сообщений 10    Оценка 171 [+0/-1]         Оценить  
Система Orphus

Взаимодействие с другими сайтами через HTTP (HttpWebRequest и HttpWebResponse)

Автор: Немиро Алексей
kbyte.ru/expert
Опубликовано: 31.07.2007
Исправлено: 10.12.2016
Версия текста: 1.0
Инструменты
HttpWebRequest и HttpWebResponse
Имитация работы браузера
Подопытный Яндекс. Авторизация на сайте.
Анализ
Код
Заключение

Исходные коды примеров VB, C#

В последнее время к нам на форум и в систему «Эксперт» поступает большое количество вопросов на тему взаимодействия с другими сайтами. Большие трудности у авторов таких вопросов вызывают проблемы программного заполнения и отправки Web-форм, причем многие из авторов идут, по их мнению, легким путем и пытаются использовать компонент WebBrowser, или всячески манипулировать «живыми» браузерами, и многие даже пытаются это делать при разработке Web-приложений! Помимо того, что подобный подход попросту не является правильным, так он еще и сложный.

В данной статье я расскажу о том, как можно программно заполнить и отправить Web-форму, а также получить результат с использованием довольно простых классов – HttpWebRequest и HttpWebResponse.

Инструменты

Для полноценной работы понадобится локальный прокси-сервер для анализа трафика, в данной статье я буду использовать Fiddler (http://www.fiddlertool.com). Все примеры будут приведены на языках VB и C#, под Framework .NET 2.x. В статье я буду все делать на примере консольного приложения, однако приведенные примеры кода можно легко использовать и в стандартных Windows-приложениях, и в Web-проектах, и в любых других проектах .NET без какой-либо особой модернизации.

HttpWebRequest и HttpWebResponse

Классы HttpWebRequest и HttpWebResponse принадлежат к пространству имен System.Net. Класс HttpWebRequest позволяет отправлять HTTP-запросы, а класс HttpWebResponse позволяет обрабатывать полученные ответы. Перед началом работы нам потребуется импортировать в проект пространства имен System.Net, System.Text и System.IO:

VB .NET
      Imports System.Net
Imports System.Text
Imports System.IO
C#
      using System.Net;
using System.Text;
using System.IO;

Имитация работы браузера

Вам может показаться, что имитация работы браузера – это что-то сверхъестественное и невыполнимое, но на самом деле это не так, более того, в .NET это делается довольно легко, при этом даже не надо знать основ протокола HTTP, хотя конечно подобные знания никому не повредят. Собственно, чтобы выполнить простейший HTTP-запрос, нужно всего две-три строчки кода:

VB .NET
      Dim myHttpWebRequest As HttpWebRequest = 
HttpWebRequest.Create("http://kbyte.ru")
Dim myHttpWebResponse As HttpWebResponse = 
myHttpWebRequest.GetResponse()
C#
HttpWebRequest myHttpWebRequest = 
  (HttpWebRequest) HttpWebRequest.Create("http://kbyte.ru");
HttpWebResponse myHttpWebResponse = 
  (HttpWebResponse)myHttpWebRequest.GetResponse();

В первой строке данного примера создается экземпляр класса HttpWebRequest для работы с сервером http://kbyte.ru. Во второй строке создается экземпляр класса HttpWebResponse, который получает результат выполнения GET-запроса к серверу http://kbyte.ru. Метод GET – это значение по умолчанию. Чтобы вывести полученный результат в консоль, достаточно добавить еще пару строчек кода:

VB .NET
      Dim myStreamReader AsNew StreamReader(myHttpWebResponse.GetResponseStream, _
Encoding.GetEncoding(1251))
Console.WriteLine(myStreamReader.ReadToEnd())
Console.ReadKey()
C#
StreamReader myStreamReader = 
  new StreamReader(
    myHttpWebResponse.GetResponseStream(), Encoding.GetEncoding(1251));
Console.WriteLine(myStreamReader.ReadToEnd());
Console.ReadKey();

В первой строке создается экземпляр StreamReader, который принимает данные из HttpWebResponse, при этом указывается кодировка Windows-1251, если ее не указать, получится «абракадабра». Во второй строке полученные данные выводятся в консоль. В третьей строке консоль ждет нажатия любой клавиши (чтобы работа программы не завершилась).

Чтобы посмотреть, какой запрос сформировал этот код, запустите локальный прокси-сервер (напомню, что я использую Fiddler, который по умолчанию прослушивает порт 8888). Чтобы наш экземпляр класса HttpWebRequest использовал прокси-сервер, необходимо указать параметры прокси-сервера в свойстве Proxy:

VB .NET
myHttpWebRequest.Proxy = New WebProxy("127.0.0.1", 8888)
C#
myHttpWebRequest.Proxy = new WebProxy("127.0.0.1", 8888);

В данном случае 127.0.0.1 – это локальный адрес компьютера, а 8888 – порт, который прослушивает прокси-сервер.

VB .NET
      Dim myHttpWebRequest As HttpWebRequest = 
  HttpWebRequest.Create("http://kbyte.ru")
myHttpWebRequest.Proxy = New WebProxy("127.0.0.1", 8888)
Dim myHttpWebResponse As HttpWebResponse = myHttpWebRequest.GetResponse()
C#
HttpWebRequest myHttpWebRequest = 
  (HttpWebRequest)HttpWebRequest.Create("http://kbyte.ru");
myHttpWebRequest.Proxy = new WebProxy("127.0.0.1", 8888);
HttpWebResponse myHttpWebResponse = 
  (HttpWebResponse)myHttpWebRequest.GetResponse();

После выполнения данного кода в отчете прокси-сервера вы должны увидеть что-то типа этого:

GET / HTTP/1.1
Host: kbyte.ru
Proxy-Connection: Keep-Alive

Теперь попробуйте подключить браузер к локальному прокси-серверу (см. параметры подключения браузера к сети), перейдите по ссылке http://kbyte.ru, и вы увидите немного другие заголовки:

GET / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, 
        application/x-shockwave-flash, application/vnd.ms-excel,
        application/vnd.ms-powerpoint, application/msword, */*
Accept-Language: ru
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2;
                         .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Host: kbyte.ru
Proxy-Connection: Keep-Alive
Cookie: Kbyte.Ru=XXX&Theme=XXX; ASP.NET_SessionId=XXX

Как видите, браузер передает гораздо больше заголовков серверу, главным образом это информация о себе (User-Agent), cookie (Cookies), предпочитаемый язык (Accept-Language) и тип данных (Accept). Все эти заголовки также можно создать программно через коллекцию Headers либо одноименные свойства объекта HttWebRequest. Конечно, объем кода придется увеличить, но сложнее он от этого точно не станет:

VB .NET
      Dim myHttpWebRequest As HttpWebRequest = 
  HttpWebRequest.Create("http://kbyte.ru")
myHttpWebRequest.Proxy = New WebProxy("127.0.0.1", 8888) 
myHttpWebRequest.UserAgent = "Mozila/4.0 (compatible; MSIE 6.0; 
                              Windows NT 5.1; SV1; MyIE2;"
myHttpWebRequest.Accept = "image/gif, image/x-xbitmap, image/jpeg, 
                           image/pjpeg, application/x-shockwave-flash,
                           application/vnd.ms-excel, 
                           application/vnd.ms-powerpoint,
                           application/msword, */*"
myHttpWebRequest.Headers.Add("Accept-Language", "ru")
Dim myHttpWebResponse As HttpWebResponse = myHttpWebRequest.GetResponse()
C#
HttpWebRequest myHttpWebRequest = 
  (HttpWebRequest)HttpWebRequest.Create("http://kbyte.ru");
myHttpWebRequest.Proxy = new WebProxy("127.0.0.1", 8888);
myHttpWebRequest.UserAgent = "Mozila/4.0 (compatible; MSIE 6.0; 
                              Windows NT 5.1; SV1; MyIE2;";
myHttpWebRequest.Accept = "image/gif, image/x-xbitmap, image/jpeg,
                           image/pjpeg, application/x-shockwave-flash, 
                           application/vnd.ms-excel, 
                           application/vnd.ms-powerpoint, 
                           application/msword, */*";
myHttpWebRequest.Headers.Add("Accept-Language", "ru");
HttpWebResponse myHttpWebResponse = 
  (HttpWebResponse)myHttpWebRequest.GetResponse();

Если теперь посмотреть на отчет прокси-сервера, то там будут видны все заголовки, которые мы передали. Таким образом, сервер будет «думать», что на сайт пришел пользователь с браузером Internet Explorer, для которого предпочитаемый язык – русский (ru). В данном примере я не стал передавать cookie (Cookies), поскольку для начала их надо бы получить, но об этом речь пойдет в следующей части статьи.

Подопытный Яндекс. Авторизация на сайте.

Анализ

В приведенных ранее примерах мы использовали GET-запросы, однако для того чтобы заполнить и отправить какую-либо Web-форму, потребуется использовать POST-запросы. Для примера попробуем пройти авторизацию на сайте http://yandex.ru. Да не будет в обиде на меня Яндекс, выбрал я его, потому что ничего другого в голову не пришло :)

Для тестирования я специально зарегистрировал себе новый логин. Для отправки запроса методом POST мы будем использовать уже знакомый нам класс HttpWebRequest. Метод запроса указывается в свойстве Method. Чтобы узнать, что и как нужно передавать, мы просто запустим локальный прокси-сервер, и пройдем процедуру авторизации на сайте через браузер (не забудьте настроить браузер), а затем детально изучим отчет прокси:

POST /passport?mode=auth HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, 
        application/x-shockwave-flash, application/vnd.ms-excel,
        application/vnd.ms-powerpoint, application/msword, */*
Referer: http://www.yandex.ru/
Accept-Language: ru
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2; 
                         .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Host: passport.yandex.ru
Content-Length: 90
Proxy-Connection: Keep-Alive
Pragma: no-cache
Cookie: yandexuid=1125763; yabs-frequency=/1/0G00; L=Twgqw==.; 
        my=Yw%3D; yandex_login=

retpath=http%3A%2F%2Fmail.yandex.ru%2F&timestamp=1185426616093&login=kbyte2007&passwd=****

В первой строке указан метод POST и адрес страницы, на которую отправляется форма. Указанный путь /passport?mode=auth – это путь относительно Host. В данном случае Host имеет значение passport.yandex.ru, следовательно, данные отправляются на страницу http://passport.yandex.ru/passport?mode=auth. Заголовок Referer содержит адрес страницы, с которой пришел пользователь, в данном случае это http://yandex.ru. Заголовок Content-Length содержит объем передаваемых данных в байтах. Заголовок Cookies содержит информацию о Cookies, которые передает браузер серверу. Далее, через одну пустую строку, начинается контент, который браузер передает серверу, т.е. данные формы. Мы видим, что передается 4 параметра: retpath, timestamp, login и passwd.

Судя по всему, параметр retpath содержит адрес страницы, на которую мы перейдем после успешной проверки логина и пароля. Параметр timestamp содержит отметку времени. Вообще, важной частью анализа является не только анализ заголовков, но и анализ всего остального трафика, который возвращает сервер (HTML и т.п). Если открыть HTML-код главной страницы Яндекса, то мы увидим, что все передаваемые параметры входят в состав формы «login», которая, собственно, и содержит в себе все передаваемые элементы (см. рис. 1).


Рис. 1. Просмотр HTML главной страницы http://yandex.ru.

Обратите внимание, при отправке формы (на рисунке это строка 75) происходит вызов функции settime() – это клиентская функция. Если вы попытаетесь найти ее на странице, то не найдете, так как она находится в отдельном файле JavaScript (см. рис. 2).


Рис. 2. Ссылка на файл JavaScrip.t

Чтобы узнать, как эта функция может повлиять на успех выполнения поставленной задачи, нужно просто открыть файл со скриптом, найти функцию settime() и посмотреть, что она делает (рис. 3).


Рис. 3. Функция settime()

Как видите, эта функция присваивает элементу timestamp (см. рис. 1. строка 79) текущее unix-время клиента (т.к. JavaScript выполняется на стороне клиента), т.е. это количество секунд прошедшее с 1 января 1970 года, нам придется сделать то же самое.

Все эти данные также должны находится в логах Fiddler-а, однако смотреть их там не очень удобно. :)

С параметрами login и passwd, думаю, и так все понятно.

Теперь давайте ознакомимся с ответом сервера:

HTTP/1.1 302 Found
Date: Thu, 26 Jul 2007 05:10:41 GMT
Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e 
        mod_perl/1.29
P3P: policyref="/w3c/p3p.xml", 
     CP="NON DSP ADM DEV PSD IVDo OUR IND STP PHY PRE NAV UNI"
Set-Cookie: yandex_fio=%cf%f3%ef%ea%e8%ed%20%c2%e0%f1%e8%eb%e8%e9; 
            path=/; domain=.yandex.ru
Set-Cookie: yandex_login=kbyte2007; path=/; domain=.yandex.ru
Set-Cookie: yandex_nickname=; path=/; domain=.yandex.ru
Set-Cookie: yandex_mail=kbyte2007; path=/; domain=.yandex.ru
Set-Cookie: L=QU0Rg==.118; path=/; domain=.yandex.ru; 
            expires=Wednesday, 24-Oct-07 05:10:41 GMT
Set-Cookie: Session_id=111; path=/; domain=.yandex.ru
Location: /passport?mode=ckicheck&idkey=09w
Connection: close
Transfer-Encoding: chunked, chunked
Content-Type: text/plain

0

Как видите, сервер возвращает код 302(временно перемещено), т.е. это обычное перенаправление, причем если посмотреть на заголовок Location, то видно, что происходит перенаправление на страницу /passport?mode=ckicheck&idkey=09w. Помимо этого, сервер передает cookie (Set-Cookie) и идентификатор сессии. Нам придется получить все эти заголовки и передать в следующем запросе, чтобы сервер принял наши данные и выдал желаемый результат.

Если посмотреть в отчете прокси-сервера, куда нас перенаправил Яндекс, то мы увидим нечто вроде следующего:

HTTP/1.1 200 OK
Date: Thu, 26 Jul 2007 06:24:00 GMT
Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e 
        mod_perl/1.29
Cache-Control: no-cache,no-store,max-age=0,must-revalidate
Pragma: no-cache
Expires: Thu, 26 Jul 2007 06:24:00 GMT
Transfer-Encoding: chunked
Content-Type: text/html; charset=windows-1251
Proxy-Connection: Close

247
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head><title>Яндекс: Паспорт</title>
<meta http-equiv="content-type" content="text/html; charset=windows-1251">
<script language="JavaScript">
<!--
window.location.replace("http://mail.yandex.ru/");
// -->
</script>
<meta http-equiv="refresh" content="0;url=http://mail.yandex.ru/">
</head>
<body>
<p>
Если вы видите эту страницу, это означает что ваш браузер не поддерживает автоматическое перенаправление.
</p>
<p>
Чтобы продолжить, нажмите на <a href="http://mail.yandex.ru/">эту ссылку</a>.
</p>
</body>
</html>

Обратите внимание на HTML. Здесь при помощи JavaScript производится перенаправление на страницу http://mail.yandex.ru/, которая была в первом запросе. Кроме этого, перенаправление указано в мета-теге «refresh». Нам придется вручную перенаправить пользователя на эту страницу, при этом очень важно не потерять cookie, которые мы получили в предыдущих запросах, иначе Яндекс нас просто не пустит.

Код

Пожалуй, хватит анализировать, займемся самым интересным – написанием кода. Первым делом нужно сформировать запрос, причем для начала на главную страницу Яндекс, поскольку именно там нам выдаются cookie, без которых дальнейшая работа в данном направлении попросту может завести нас в тупик. Запрос вполняется методом GET:

VB .NET
        Dim myHttpWebRequest As HttpWebRequest = 
  HttpWebRequest.Create("http://yandex.ru")
myHttpWebRequest.Proxy = New WebProxy("127.0.0.1", 8888)
myHttpWebRequest.UserAgent = 
  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2;"
myHttpWebRequest.Accept = "image/gif, image/x-xbitmap, image/jpeg, 
                           image/pjpeg, application/x-shockwave-flash, 
                           application/vnd.ms-excel, 
                           application/vnd.ms-powerpoint, 
                           application/msword, */*"
myHttpWebRequest.Headers.Add("Accept-Language", "ru")
Dim myHttpWebResponse As HttpWebResponse = myHttpWebRequest.GetResponse()
myStream = myHttpWebResponse.GetResponseStream
Dim sCookies AsString = ""IfNotString.IsNullOrEmpty(myHttpWebResponse.Headers("Set-Cookie")) Then
  sCookies = myHttpWebResponse.Headers("Set-Cookie")
EndIf
C#
HttpWebRequest myHttpWebRequest = 
  (HttpWebRequest)HttpWebRequest.Create("http://yandex.ru");
myHttpWebRequest.Proxy = new WebProxy("127.0.0.1", 8888);
myHttpWebRequest.UserAgent = "Mozila/4.0 (compatible; MSIE 6.0; 
                              Windows NT 5.1; SV1; MyIE2;";
myHttpWebRequest.Accept = "image/gif, image/x-xbitmap, image/jpeg, 
                           image/pjpeg, application/x-shockwave-flash,
                           application/vnd.ms-excel, 
                           application/vnd.ms-powerpoint, 
                           application/msword, */*";
myHttpWebRequest.Headers.Add("Accept-Language", "ru");
HttpWebResponse myHttpWebResponse = 
  (HttpWebResponse)myHttpWebRequest.GetResponse(); 
string sCookies = 
  String.IsNullOrEmpty(myHttpWebResponse.Headers["Set-Cookie"]))
  ? "" : myHttpWebResponse.Headers["Set-Cookie"];

Cookie мы получаем из заголовка Set-Cookies и записываем их в переменную sCookies (строки – 8-11).

Далее нам надо пройти процедуру авторизации на Яндекс, делать мы это будем уже методом POST:

VB .NET
myHttpWebRequest.Proxy = New WebProxy("127.0.0.1", 8888)
myHttpWebRequest.Method = "POST"
myHttpWebRequest.Referer = "http://yandex.ru"
myHttpWebRequest.UserAgent = 
  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2;"
myHttpWebRequest.Accept = "image/gif, image/x-xbitmap, image/jpeg, 
                           image/pjpeg, application/x-shockwave-flash, 
                           application/vnd.ms-excel, 
                           application/vnd.ms-powerpoint, 
                           application/msword, */*"
myHttpWebRequest.Headers.Add("Accept-Language", "ru")
myHttpWebRequest.ContentType = "application/x-www-form-urlencoded"'передаем Cookie, полученные в предыдущем запросеIfNotString.IsNullOrEmpty(sCookies) Then
  myHttpWebRequest.Headers.Add(HttpRequestHeader.Cookie, sCookies)
EndIf'ставим False, чтобы не делать автоматического перенаправления
myHttpWebRequest.AllowAutoRedirect = False'передаем параметрыDim sQueryString AsString = 
  "retpath=http%3A%2F%2Fmail.yandex.ru%2F&timestamp=" 
  & DateDiff(DateInterval.Second, NewDate(1970, 1, 1), Now) 
  & "&login=kbyte2007&passwd=****"Dim ByteArr AsByte() = Text.Encoding.GetEncoding(1251).GetBytes(sQueryString)
myHttpWebRequest.ContentLength = ByteArr.Length()
myHttpWebRequest.GetRequestStream().Write(ByteArr, 0, ByteArr.Length)

'делаем запрос
myHttpWebResponse = myHttpWebRequest.GetResponse()
C#
HttpWebRequest myHttpWebRequest =
  (HttpWebRequest)HttpWebRequest.Create(
    "http://passport.yandex.ru/passport?mode=auth");
myHttpWebRequest.Proxy = new WebProxy("127.0.0.1", 8888);
myHttpWebRequest.Method = "POST";
myHttpWebRequest.Referer = "http://yandex.ru";
myHttpWebRequest.UserAgent = "Mozila/4.0 (compatible; MSIE 6.0; 
                              Windows NT 5.1; SV1; MyIE2;";
myHttpWebRequest.Accept = "image/gif, image/x-xbitmap, image/jpeg,
                           image/pjpeg, application/x-shockwave-flash, 
                           application/vnd.ms-excel, 
                           application/vnd.ms-powerpoint, 
                           application/msword, */*";
myHttpWebRequest.Headers.Add("Accept-Language", "ru");
myHttpWebRequest.ContentType = "application/x-www-form-urlencoded";

// передаем cookie, полученные в предыдущем запросеif (!String.IsNullOrEmpty(sCookies))
  myHttpWebRequest.Headers.Add(HttpRequestHeader.Cookie, sCookies);

// ставим False, чтобы при получении кода 302 не делать // автоматического перенаправления
myHttpWebRequest.AllowAutoRedirect = false;

// передаем параметры
TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1);
string sQueryString = 
  "retpath=http%3A%2F%2Fmail.yandex.ru%2F&timestamp=" 
  + Math.Floor(ts.TotalSeconds).ToString() 
  + "&login=kbyte2007&passwd=***";
byte[] ByteArr = 
  System.Text.Encoding.GetEncoding(1251).GetBytes(sQueryString);
myHttpWebRequest.ContentLength = ByteArr.Length;
myHttpWebRequest.GetRequestStream().Write(ByteArr, 0, ByteArr.Length);

// делаем запрос
HttpWebResponse myHttpWebResponse = 
  (HttpWebResponse)myHttpWebRequest.GetResponse();

Очень важно не забыть указать значение False свойства AllowAutoRedirect. Если этого не сделать, то, при получении кода 301/302, HttpWebRequest автоматически перейдет на указанную в заголовках страницу, при этом могут потеряться важные данные, например, cookie, и, следовательно, сервер не пустит нас на нужную страницу. Также не забудьте указать в строке запроса (переменная sQueryString) параметры login и passwd. Если вы сделаете все правильно, то сервер возвратит код 302, в противном случае – код 200, со страницей, содержащей информацию об ошибке, либо форму авторизации. После этого надо получить адрес страницы, на которую нас перенаправляет сервер. Эта информация содержится в заголовке Location. Все последующие запросы будут выполняться методом GET:

VB .NET
        Dim sLocation AsString = myHttpWebResponse.Headers("Location")

'получам cookie
sCookies = ""IfNotString.IsNullOrEmpty(myHttpWebResponse.Headers("Set-Cookie")) Then
  sCookies = myHttpWebResponse.Headers("Set-Cookie")
EndIf'формируем запрос
myHttpWebRequest = 
  HttpWebRequest.Create("http://passport.yandex.ru" & sLocation)
myHttpWebRequest.Proxy = New WebProxy("127.0.0.1", 8888)
myHttpWebRequest.Referer = "http://passport.yandex.ru/passport?mode=auth"
myHttpWebRequest.UserAgent = 
  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2;"
myHttpWebRequest.Accept = 
  "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, 
  application/x-shockwave-flash, application/vnd.ms-excel,
  application/vnd.ms-powerpoint, application/msword, */*"
myHttpWebRequest.Headers.Add("Accept-Language", "ru")
myHttpWebRequest.ContentType = "text/plain"IfNotString.IsNullOrEmpty(sCookies) Then
  myHttpWebRequest.Headers.Add(HttpRequestHeader.Cookie, sCookies)
EndIf'выполняем запрос
myHttpWebResponse = myHttpWebRequest.GetResponse()
C#
        string sLocation = myHttpWebResponse.Headers["Location"];

// получам cookie
sCookies = "";
if (!String.IsNullOrEmpty(myHttpWebResponse.Headers["Set-Cookie"]))
{
  sCookies = myHttpWebResponse.Headers["Set-Cookie"];
}

// формируем запрос
myHttpWebRequest = 
  (HttpWebRequest)HttpWebRequest.Create(
    "http://passport.yandex.ru" + sLocation);
myHttpWebRequest.Proxy = new WebProxy("127.0.0.1", 8888);
myHttpWebRequest.Referer = "http://passport.yandex.ru/passport?mode=auth";
myHttpWebRequest.UserAgent = 
  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2;";
myHttpWebRequest.Accept = 
  "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, 
  application/x-shockwave-flash, application/vnd.ms-excel, 
  application/vnd.ms-powerpoint, application/msword, */*";
myHttpWebRequest.Headers.Add("Accept-Language", "ru");
myHttpWebRequest.ContentType = "text/plain";

if (!String.IsNullOrEmpty(sCookies))
{
  myHttpWebRequest.Headers.Add(HttpRequestHeader.Cookie, sCookies);
}

// выполняем запрос
myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();

Вот мы и приблизились к нашей цели, следующая страница, которую возвратит сервер, будет содержать информацию о том, что наш браузер не поддерживает автоматической переадресации, и предложение нажать на ссылку, для входа в ящик. Переадресация производится при помощи JavaScript, а также через мета-теги. Мы будем отталкиваться от JavaScript, хотя принципиального значения это не имеет. Собственно адрес, на который нужно перейти, был указан в самом первом шаге, когда мы отправляли POST-запрос, вот туда мы и будем сейчас переходить. Здесь очень важно не потерять cookie, поскольку в них содержится идентификатор сессии (Session), если мы потеряем cookie, то сервер перенаправит нас на страницу авторизации.

VB .NET
myHttpWebRequest = HttpWebRequest.Create("http://mail.yandex.ru/")
myHttpWebRequest.Proxy = New WebProxy("127.0.0.1", 8888)
myHttpWebRequest.Referer = "http://passport.yandex.ru" & sLocation
myHttpWebRequest.UserAgent = 
  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2;"
myHttpWebRequest.Accept = 
  "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, 
  application/x-shockwave-flash, application/vnd.ms-excel, 
  application/vnd.ms-powerpoint, application/msword, */*"
myHttpWebRequest.Headers.Add("Accept-Language", "ru")
myHttpWebRequest.ContentType = "text/plain"IfNotString.IsNullOrEmpty(sCookies) Then
  myHttpWebRequest.Headers.Add(HttpRequestHeader.Cookie, sCookies)
EndIf'выполняем запрос
myHttpWebResponse = myHttpWebRequest.GetResponse()

'выводим результат в консольDim myStreamReader AsNew StreamReader(
  myHttpWebResponse.GetResponseStream, Encoding.GetEncoding(1251))
Console.WriteLine(myStreamReader.ReadToEnd())
Console.WriteLine("Нажмите любую клавишу для завершения.")
Console.ReadKey()
C#
myHttpWebRequest = 
  (HttpWebRequest)HttpWebRequest.Create("http://mail.yandex.ru/");
myHttpWebRequest.Proxy = new WebProxy("127.0.0.1", 8888);
myHttpWebRequest.Referer ="http://passport.yandex.ru" & sLocation;
myHttpWebRequest.UserAgent = 
  "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; MyIE2;";
myHttpWebRequest.Accept = 
  "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, 
  application/x-shockwave-flash, application/vnd.ms-excel, 
  application/vnd.ms-powerpoint, application/msword, */*";
myHttpWebRequest.Headers.Add("Accept-Language", "ru");
myHttpWebRequest.ContentType = "text/plain";
if (!String.IsNullOrEmpty(sCookies))
{
  myHttpWebRequest.Headers.Add(HttpRequestHeader.Cookie, sCookies);
}

// выполняем запрос
myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();

// выводим результат в консоль
StreamReader myStreamReader = 
  new StreamReader(myHttpWebResponse.GetResponseStream(), 
  Encoding.GetEncoding(1251));
Console.WriteLine(myStreamReader.ReadToEnd());
Console.WriteLine("Нажмите любую клавишу для завершения.");
Console.ReadKey();

Вот, собственно, и все. Если запустить данный код и посмотреть на отчет прокси-сервера, будет видно, что при первом запросе сервер выдает код 200, затем 302 и опять два раза 200, т.е. все точно так же, как если бы мы прошли процедуру авторизации через браузер. В окне консоли должно появиться содержимое страницы сервиса работы с почтовым ящиком на Яндекс.Ру.

Заключение

Признаюсь честно, с первого раза написанный мой код не сработал, и со второго тоже, и даже с третьего раза Яндекс не принял мои запросы :). Несмотря на то, что программно выполнить POST-запрос несложно, иногда все же приходится помучиться. По большому счету, все трудности возникают из-за некачественного анализа трафика или потери некоторых важных параметров при выполнении запросов. Если вы вдруг столкнетесь с подобными проблемами, то попробуйте просто передавать все полученные через обычный браузер заголовки один к одному, даже несмотря на то, что многие из них попросту не нужны.

Продолжая данную тему, можно запросто при помощи регулярных выражений (вместо регулярных выражений для разбора HTML лучше использовать SgmlReader – прим.ред.) получить список сообщений в ящике, и даже написать новое сообщение, но работа с почтой – это уже другая история, совершенно никак не связанная с HttpWebRequest и HttpWebResponse, поскольку в .NET существуют другие, более мощные, специально созданные для этого средства. Пример с Яндексом я выбрал совершенно случайно, на его основе вы можете создать автоматическую «заполнялку» форм и «бродилку» по страницам любой степени сложности и вложенности.

И помните, никто не решит ваши проблемы лучше, чем вы сами.

Удачи!


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
    Сообщений 10    Оценка 171 [+0/-1]         Оценить