Поиск по блогу

вторник, 12 мая 2009 г.

Для начинающих работать с компонентом idHTTP в Delphi

Найти компонент idHTTP можно на вкладке Indy Clients.

idHTTP

После того, как поместите его на форму, посмотрите его параметры и свойства в Object Inspector-е. Вы увидите, что работать с протоколом HTTP с помощью этого компонента достаточно просто. Для "составления" правильных заголовков запросов к серверу будем плотно работать с TIdHTTP.Request. Многие поля вам уже знакомы (я упоминала о них в вводной статье о протоколе HTTP и HTTP-заголовках). Там же есть возможность привязки к объекту idHTTP компонента для удобной работы с кукисами (компонент idCookieManager) и настройка работы через прокси.

Рассмотрим способы отправки запросов Get и Post. С такими названиями существуют и функции, и процедуры. Я уже упоминала про Get в вводной статье об Indy. Непосредственно перед отправкой запроса следует настроить свойства вышеупомянутого IdHTTP.Request-а, если есть необходимость. Например, UserAgent в idHTTP по умолчанию Mozilla/3.0 (compatible; Indy Library), и, чтобы не палиться, следует его заменить на что-нибудь более безобидное :) А если вы создаете экземпляры компонента idHTTP динамически для парсинга страниц какого-нибудь большого сайта, то юзерагента можно вообще брать рандомом из заранее подготовленного списка.

Пример использования процедуры idHTTP.Get без дополнительных настроек:

var
mStream: TMemoryStream;

mStream := TMemoryStream.Create;
try
idHttp := TIdHTTP.Create(nil);
{ тут следует "настроить" параметры idHTTP }
{ ... }
try
idHttp.Get(URL, mStream);
finally
idHttp.Free;
end;
finally
mStream.Free;
end;


Или с помощью функции получить содержимое страницы в строковую переменную:

Str := idHttp.Get(URL);


С POST-запросом дела обстоят аналогично, с одним отличием: при отправке POST-запроса передаются еще и параметры. Думаю, что более подробно рассмотрю POST-запрос в следующем посте, с примером авторизации на сайте (чтобы не пихать слишком много информации в одну запись).

Какие еще аспекты работы с idHTTP следует отметить?
После посылки запроса проверить ответ сервера можно, посмотрев содержимое свойства

idHTTP.Response.ResponseText


Стандартым ответом о том, что все прошло удачно, является HTTP/1.0 200 OK.

Бывают и другие ответы сервера (про коды ответов я упоминала в одной из предыдущих записей). Остановлю внимание только на двух наиболее часто встречающихся группах:
2хх: Успешно. Сигнал был успешно принят, понят и принят к обработке.
Зхх: Перемаршрутизация. Необходимо предпринять определенные действия, чтобы выполнить запрос.

Исключения, возникающие при работе компонентов Indy (тип EIdHTTPProtocolException), классифицируются особым образом.

Except
on E:EIdHTTPProtocolException do
ShowMessage(E.ErrorMessage);


Классификация исключений может пригодиться. У меня был случай, когда написанный парсер работал без проблем, но спустя какое-то время отказался работать. Помог анализ ответа сервера: на сайте временно поставили перенаправление (Код 302 Found: HTTP_FOUND — Запрошенный ресурс был временно перемещен на новый URI), возможность которого я в начальной версии не предусмотрела. С тех пор во всех своих парсерах я проверяю код ответа: не 302 ли случаем? (Если код ответа 301 (Moved Permanently: HTTP MOVED PERMANENTLY — Запрошенный документ был перенесен на новый URI), то информация берется без проблем, если у idHTTP свойство HandleRedirects := true, а вот с 302 это не прокатывает. Так же отдельно я обрабатываю код 404). Еще у компонента надо грамотно настроить все таймауты, чтобы, если обнаружится исключительная ситуация, запрос не "подвисал".

Пример кода для обработки исключений разного типа:
procedure TForm1.Button1Click(Sender: TObject);
begin
Memo1.Lines.Clear;
try
Memo1.Lines.Add(IdHTTP1.Get(Edit1.Text));
except on e : EIDHttpProtocolException do
Begin
if e.ErrorCode = 302 then
begin
try
// получаем новый адрес - адрес перенаправления
Memo1.lines.add(idhttp1.Get(IdHTTP1.Response.Location));
except on e:Exception do
// предусматриваем, что исключение может возникнуть и тут
ShowMessage('Ошибка при получении нового адреса.'+e.Message);
end;
end
else
//http 404, 501 и так далее
ShowMessage('Ошибка другого вида, не 302:'+e.Message);
end;
on e:Exception do
ShowMessage('Ошибка: ' + e.Message);
end;
end;



Чтобы быть в курсе обновлений блога, можно подписаться на RSS.

А еще, если вам интересно программирование на Delphi, можете подписаться на RSS-трубу Delphi, о которой подробнее можно прочитать здесь.

Статьи схожей тематики:



14 комментариев:

  1. В строке ...if e.ErrorCode = 302... вместо ErrorCode нужно ReplyErrorCode, во всяком случае в Indy 9.0

    ОтветитьУдалить
  2. Да, в девятой версии ErrorCode, спасибо за замечание) Но лучше поставить версию индей посвежее, там устранены кое-какие существенные баги.

    ОтветитьУдалить
  3. Спасибо за статью!
    Очень хотелось бы увидеть от вас статьи про распознавание капчи на Delphi.

    ОтветитьУдалить
  4. Анонимный, я когда-то писала подобную статью на другом блоге: http://www.blogok.ru/2008/07/13/algoritm-razgadyvaniya-prostoj-kapchi/. Новых капч мне разгадывать не приходилось, да и этот блог все-таки не просто о Delphi, а конкретно о парсинге, так что обещать не могу :)

    ОтветитьУдалить
  5. Маша, вы наверное представить себе не можете как тесно связано распознавание образов (капчи в часности) с парсингом :) Яркий пример - если парсить выдачу Google очень интенсивно, то появляется капча. Использовать прокси можно, но это решает проблему только временно. Вообщем надеюсь вы раскроете эту тему на блоге ;)

    ОтветитьУдалить
  6. Masha, пытался связаться с вами через почту, нет ответа... Хотел бы обговорить с вами несколько вопросом по заказу парсера... свяжитесь плз со мной через аську - 393 три два один 648

    ОтветитьУдалить
  7. Маша, а зачем обрабатывать еррор 302, если можно сделать так:
    Http.HandleRedirects:= True;
    и инди сам получит редирект

    ОтветитьУдалить
  8. Анонимный, задача статьи была продемонстрировать пример обработки кодов, а не познакомить читателей с обработкой редиректа в частности :)

    P.S. Интересно, почему так мало комментаторов, которые читают мое сообщение под "Оставьте комментарий"? :(

    ОтветитьУдалить
  9. добрый день... пытаюсь авторизоваться на сайте love.rambler.ru... получаю ошибку "Внутренняя ошибка сервера..."... не подскажите ли, с чем это связано?

    ОтветитьУдалить
  10. Анонимный, думаю, что это связано с внутренней ошибкой сервера :D

    P.S. Что вообще за вопросы? тут не шоу "Битва экстрасенсов"...

    ОтветитьУдалить
  11. Здравствуйте, спасибо за ваш блог (вроде я уже чего-то комментировал, но лишнее спасибо не помешает))! Скажите пожалуйста, а как справляться с кодировкой полученных этим компонентом страниц? После получения или, например, при записи их в базу. А то досталась мне сайтина в koi8-r, почти дописал уже парсер. Хоть стой, хоть падай, а база данных для вывода (mysql) то на utf8, да и отслеживать надо, что правильно наполняется. Пожалуйста, продублируйте ответ на isanbet@mail.ru , если нетрудно. На рабочем компе стоит Borland Development Studio 2006 (10 версия дельфи), но хотелось бы и как в 7-й это решать. Огромное спасибо!

    ОтветитьУдалить
  12. Анонимный, и вам спасибо за внимание к блогу :) Отвечаю с запозданием, так как работы очень много.

    Сейчас у меня под рукой нет, но существуют разные функции преобразования кодировок. В интернете все есть. Сама не люблю возиться с ними))

    ОтветитьУдалить
  13. доброго дня, мене звати Коля. сам програмую на С++ builder? але воно таке саме як і delphi (компоненти всі ті самі, але трохи відрізняється синтаксис). Скажіть, будь ласка, чи можна якось за допомогою idhttp чи інших компонентів з веб сторінок брати сам текст, а не повністю html код?

    ОтветитьУдалить
  14. Спасибо вам, Машенька, за столь полезные статьи!

    ОтветитьУдалить

Комментарии модерируются, вопросы не по теме удаляются, троллинг тоже.

К сожалению, у меня нет столько свободного времени, чтобы отвечать на все частные вопросы, так что, может, свой вопрос лучше задать на каком-нибудь форуме?

Поделиться