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

четверг, 4 февраля 2010 г.

Работа с библиотекой Synapse в Delphi - начало

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

Первое, что я решила опробовать, это библиотека Synapse. Я уже не раз встречала упоминания о ней, но все как-то не доводилось поработать.

Скачиваем, устанавливаем.

Установка Synapse

(в моем случае на старенький Delphi 7).

1. Распаковать архив в какую-нибудь папку (в Source, например)
2. В меню идем Tools - Environment Options - Library и добавляем в Library Path путь к папке ..Source\SYNAPSE\LIB
3. В новосозданном проекте добавляем в Uses-ы httpsend и synacode (при надобности).

Пришло время "HelloWorld"-а.

Простые примеры кода с использованием Synapse


Давайте начнем с самых простых вещей - с получения содержимого страницы.

Поместим на форму кнопку и TMemo, добавим в uses httpsend, напишем обработчик нажатия кнопки:

procedure TMainF.Button1Click(Sender: TObject);
begin
if not HttpGetText('http://parsing-and-i.blogspot.com', Memo1.Lines) then
ShowMessage('Что-то не получилось.');
end;

После нажатия на кнопку в мемо появилось содержимое страниц. Старт взят: с помощью HttpGetText задачу выполнили.

Дальнейшее изучение библиотеки можно проводить так — заглянуть непосредственно в файл библиотеки (httpsend.pas). Главным классом является THTTPSend. Даже просто изучив его структуру, можно понять принципы работы и возможности.

Итак, HTTPSend.Document возвращает содержимое всего документа. Поэкспериментируем с использованием еще каких-нибудь элементарных функций. Например, получим заголовок страницы и отдельно код ответа.

procedure TMainF.Button2Click(Sender: TObject);
var
HTTP: THTTPSend;
Res : boolean;
begin
HTTP := THTTPSend.Create;
try
Res := HTTP.HTTPMethod('GET', Edit1.Text);
if Res then
begin
Memo1.Lines.AddStrings(HTTP.Headers);
Edit2.Text := IntToStr(HTTP.ResultCode);
end
finally
HTTP.Free;
end;
end;


synapse headers and resultcode

Задание было несложным. А сейчас попробуем в строке для ввода url набрать "http://yandex.ru". Как известно, если адрес яндекса набирать без "www", то перманентно будет произведен редирект на адрес с "www".

В indy есть удобное свойство. Там если

idHTTP.HandleRedirects := true;

то все редиректы будут обрабатываться автоматически (кто работает с php - в cURL такой параметр тоже есть). А здесь мы наблюдаем:

synapse redirect code 301

И никакого HandleRedirects.

Пробуем самостоятельно обработать ситуацию, когда код ответа совпадет с кодом редиректа. Знаем, что в заголовке есть параметр Location, в котором будет указано новое местоположение страницы. Определим новый location, распарсив заголовок.

procedure TMainF.Button2Click(Sender: TObject);
var
HTTP : THTTPSend;
Res : boolean;
n : integer;
NewUrl : string;
begin
HTTP := THTTPSend.Create;
// HTTP.UserAgent:= GetRandomUseragent;
try
Res := HTTP.HTTPMethod('GET', Edit1.Text);
if Res then
begin
Memo1.Lines.AddStrings(HTTP.Headers);
Edit2.Text := IntToStr(HTTP.ResultCode);
// если код ответа 3XX (т.е. есть редирект)
case HTTP.Resultcode of
301, 302, 307:
begin
n := FoundLocationStrNum(HTTP.Headers);
if (n >= 0) and (n <= HTTP.Headers.count) then // если в хэдере найдена строка с локейшеном
begin
NewUrl := StringReplace(HTTP.Headers.Strings[n],'Location: ','',[]);
Edit3.Text := NewURL;
end
else
ShowMessage('В заголовке не найдена ссылка для редиректа');
end;
end;
end
finally
HTTP.Free;
end;
end;

где

function FoundLocationStrNum(Headers: TStringlist): integer;
var
FoundStrPos, i : integer;
begin
Result:= -1;
// ищем в заголовке строку, начинающуюся с "Location: "
for i := 0 to Headers.Count do
begin
FoundStrPos := Pos('Location: ', Headers.Strings[i]);
if FoundStrPos > 0 then
begin
Result:= i; // номер строки, в которой указан Location
exit;
end;
end;
end;


По идее, в том месте, где я для примера вывела в edit3 новый URL, надо снова запрашивать страницу, проверять хэдер и так далее (и все это желательно с учетом максимального количества редиректов). Для этого понадобится написание рекурсивной функции или применение готовых "оберток". Наверняка в сети есть готовые библиотеки для облегчения использования Synapse. Попытаюсь к следующему разу собрать какой-нибудь материал и привести пример работы, сейчас уже не хочется с этим возиться. Главное, что сегодня произошло знакомство с библиотекой и базовыми принципами работы с ней.

synapse get redirect location code 301

Если вы знаете какие-нибудь удобные библиотеки для работы с Synapse — буду рада ссылкам на них в комментариях.

____

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

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



24 комментария:

  1. Штука, конечно, не плохая, но Вас не смутило, что дата последнего ченджлога 2007 год?

    проект больше мертв чем жив.

    а инди развивается и развивается...

    стремно использовать в своих проектах либы у которых нет будущего.
    брать их как базис и дописывать? хм... как вариант, но стоит ли оно того?

    ОтветитьУдалить
  2. to Homolibere
    А Вы уверены, что смотрели Synapse на правильном сайте
    http://www.synapse.ararat.cz
    последний стабильный релиз 2009-10-09 - release no. 39

    ОтветитьУдалить
  3. Я - Ваш поклонник отныне и вовеки веков!!! Спасибо за этот блог!

    ОтветитьУдалить
  4. Уверен, я смотрел сюда http://synapse.ararat.cz/doc/Synapse_history.htm

    Но и ошибся я тоже. В свн коммиты по новее. Надо будет попробовать.

    ОтветитьУдалить
  5. Вот моя обертка
    http://narod.ru/disk/17696081000/IngHTTPSend.7z.html

    ОтветитьУдалить
  6. Сергей, большое спасибо! Погляжу :)

    ОтветитьУдалить
  7. Если будут вопросы, пишите на pikhovkins[соб-ка]yandex[тчк]ru

    ОтветитьУдалить
  8. Здравствуйте, у меня на get возвращается код 200, т.е. всё ок, но в Headers нету Location, но нужен редирект по ссылке, там на этой странице есть кнопка по нажанию которой происходит скачивание файла, так вот у меня возник вопрос, это я что то делаю не так или это косяк сайта? получается нужна переадресация, но в получаемом ответе её нет, хотя в теле возвращаемой страницы ссылка на файл есть

    получается мне нужно вручную парсить возвращаемый результат что бы получить ссылку на файл?

    ps извините если не понятно объяснил, я ещё новичок :)

    ОтветитьУдалить
  9. Доброго времени суток! У меня вопрос по "синапсу" и парсерам... страничку мы открываем, а как в свое приложение загрузить ее определенную часть, т.е. определенные данные?

    ОтветитьУдалить
  10. Распарсить данные. Разобрать DOM или с помощью регулярных выражений. Большая часть материалов на блоге именно об этом.

    ОтветитьУдалить
  11. Весь день провел за поиском и чтением информации о DOM'е и регулярных вырожениях и всетаки не понятно! Как можно достать например цифру в динамичесски создаваемой странице. А если еще и в тексте поподаются ява теги... На ум приходит только Pos('(('***********', Memo1.Text); Пожалуйста обьясните чайнику как это можно сделать!

    ОтветитьУдалить
  12. Используй регулярные выражения.

    ОтветитьУдалить
  13. Доброго времени суток Мария! Нашел в вашем блоге много интересного для себя, до этого и понятия не имел что такое парсер и как его использовать )) Спасибо! При освоении этой области программирования сталкнулся с проблемой, а именно: Используя Synapse загружаю исходный текст веб странички, все нормально до тех пор пока в URL нету кириллицы. При использовании URL.Encode функции (Для проверки запускаю через шелл страничка открывается!!) ничего не получается как быть???

    ОтветитьУдалить
  14. Анонимный, я не сталкивалась с кириллицей в URL-ах, не приходилось, так что сходу ответить на вопрос не могу, а пробовать сейчас некогда. Но, может, кто-нибудь из читающих эту статью уже сталкивался и поможет. :)

    ОтветитьУдалить
  15. >При использовании URL.Encode функции (Для проверки запускаю через шелл страничка открывается!!) ничего не получается как быть???

    Точнее вот так:
    EncodeURL(AnsiToUtf8(Stroka с кириллицей))

    ОтветитьУдалить
  16. Маша а что нужно добавить в Uses чтобы не выдавала ошибку для "GetRandomUserAgent" и т.д. ?
    У меня там стоит только HTTPSEND!

    ОтветитьУдалить
  17. Имя, ну и имя у вас :)
    Закомментируйте эту строку вообще, она не обязательная. Это у меня функция для подстановки рандомного UserAgent-а. Можно и статически какое-нибудь значение задать.

    Что-то я упустила, в листинге в посте сейчас закомментирую, спасибо, что обратили внимание.)

    ОтветитьУдалить
  18. И еще хотел бы дать маленький совет для начинающих парсеров таких как я. Прежде чем анализировать страницу лучше для начала воспользуйтесь утилой HTTP Analyzers 5x. чтоб можно было по быстрому копировать значение GET/POST запросов. Это не только удобно но и с экономит вам много времени. Думаю автор уже в курсе подобных утилит, и мне это кажется лучшим способом.

    пысы - если не найдете ключ или программу обращайтесь вышлю полную версию.

    ОтветитьУдалить
  19. Подскажите, пожалуйста, как можно средствами Synapse, организовать отправку файла на сервер. Раньше использовал инди (TIdMultipartFormDataStream+Post), решил отказаться, перейти на синапс. Все просто освоилось, только это. Подскажите, пожалуйста, как это использовать в синапсе.

    ОтветитьУдалить
  20. Shaddy, я еще не настолько хорошо знаю эту библиотеку. Боюсь, что помочь не могу. Может, кто-нибудь из читателей ответит. На всякий случай продублирую вопрос на http://help.sander.su/.

    ОтветитьУдалить
  21. Про Synopse много написано на webdelphi.ru, и есть довольно много хороших практических примеров!

    ОтветитьУдалить
  22. Маша, доброго дня.
    У меня возникла следующая проблема (покажу на примерах):
    1.HTTPMethod('GET','213.180.193.3')
    2.HTTPMethod('GET','http://www.yandex.ru')

    1-ый способ обращения к Яндесу (по IP) работает на ура.
    2-ой способ возвращает ошибку 500, и HTML, соответственно, не скачивается.
    ps. Использую из-под Анроида, но отлаживаюсь в Lazarus в Win.
    Помогите пожалуйста.

    ОтветитьУдалить
  23. Спасибо за статью! Помогла разобраться с ответом от сервера - 301!

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

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

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

Поделиться