уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Пример использования событий для TTCPBlockSocket я уже рассматривал вкратце вот в этом посте. Но, как говориться, “Повторение – Мать учения”. Раз встречаются ещё вопросы, значит рассмотрим вопрос более подробно.

Итак, есть какая-либо абстрактная страница “Икс” на которой содержаться необходимые нам данные.

Наша цель: с минимумом затрат Интернет-траффика скачать необходимые нам данные с помощью THTTPSend и предоставить их пользователю…ну или отправить их на дальнейшую обработку в нашей программе.

Обращаю особое внимание на то, что “с минимумом затрат Интернет-траффика” НЕ времени, т.к. предложенный способ достаточно затратный с точки зрения потерь времени.

Итак, начнем.

Что нам может потребоваться для работы? В принципе, я бы определил свой набор “инструментов” следующим образом:

  1. любой браузер
  2. Synapse (само собой) – для скачивания данных
  3. Любая библиотека для работы с регулярными выражениями в Delphi, например нововведение Delphi XETRegExp – для парсинга данных.

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

Теперь о том, что будем искать. Искать будем, наверное, одно из самых популярных значений – заголовок веб-странички, например про социальную сеть Фейсбук (кстати, в последнее время частенько захожу в Facebook, так что, если что – милости прошу).

Результатом выполнения нашей программы будет строка “Facebook | BigCorp — от стартапа к корпорации”.

Теперь открываем Delphi, создаем новое приложение и подключаем в uses модули HTTPSend и blcksock.

Главное окно программы будет до ужаса простым:

Synapse

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

THookDataFilter = procedure(Sender: TObject; var Value: AnsiString)

 

Повторение пройденного материала: Value возвращает ту часть данных, которую сокет получил в результате последней операции чтения.

Поэтому определяем глобальную переменную, например:

var AllDocument: string;

 

И объявляем процедуру в разделе private/public главной формы приложения:

procedure MyFilter(Sender: TObject; var Value: AnsiString);

 

Сама процедура будет такой:

procedure TForm2.MyFilter(Sender: TObject; var Value: AnsiString);
begin
  AllDocument:=AllDocument+UTF8ToString(Value);
  if (pos('',AllDocument)>0) then
    begin
      Label3.Caption:=GetBetween('<title>',’</title>,AllDocument);
      label5.Caption:=IntToStr(Length(AllDocument))+' байт';
      TBlockSocket(Sender).CloseSocket;
    end;
end;

 

Здесь стоит обратить Ваше внимание на три вещи:

  1. UTF8ToString. Так как сайт в кодировке UTF-8, то перед тем как добавить скачанный текст к тому, что есть мы вначале меняем кодировку. Более подробно о работе с кодировками смотри в посте «3 варианта работы с кодировками веб-страниц в Delphi.«
  2. Функция GetBetween – возвращает строку, находящуюся между двумя подстроками, в нашем случае – это открывающий и закрывающий теги. Вообще таких функций в Сетке вагон и маленькая тележка. Но код метода рассмотрим чуть ниже.
  3. После того как нашли то, что искали – закрываем соединение, иначе смысл обработчика просто потеряется – качаться будет весь документ.

Теперь остается самая малость – правильно определить обработчик и проверить работу нашей программки. Пишем обработчик события OnClick кнопки:

procedure TForm2.Button1Click(Sender: TObject);
var HTTP: THTTPSend;
begin
  AllDocument:='';
  HTTP:=THTTPSend.Create;
  try
     HTTP.Sock.OnReadFilter:=MyFilter;//определили обработчик события
     if HTTP.HTTPMethod('GET',Edit1.Text) then
        ShowMessage('Документ скачан на 100%');
  finally
    HTTP.Free;
  end;
end;

И, наконец, специально для тех кто не в курсе как вытащить строку, находящуюся между двумя подстроками — листинг функции GetBetween:

function GetBetween(const PairBegin, PairEnd, Value: string): string;
var
  n: integer;
  x: integer;
  s: string;
  lenBegin: integer;
  lenEnd: integer;
  str: string;
  max: integer;
begin
  lenBegin := Length(PairBegin);
  lenEnd := Length(PairEnd);
  n := Length(Value);
  if (Value = PairBegin + PairEnd) then
  begin
    Result := '';//nothing between
    exit;
  end;
  if (n < lenBegin + lenEnd) then
  begin
    Result := Value;
    exit;
  end;
  s := SeparateRight(Value, PairBegin);
  if (s = Value) then
  begin
    Result := Value;
    exit;
  end;
  n := Pos(PairEnd, s);
  if (n = 0) then
  begin
    Result := Value;
    exit;
  end;
  Result := '';
  x := 1;
  max := Length(s) - lenEnd + 1;
  for n := 1 to max do
  begin
    str := copy(s, n, lenEnd);
    if (str = PairEnd) then
    begin
      Dec(x);
      if (x <= 0) then
        Break;
    end;
    str := copy(s, n, lenBegin);
    if (str = PairBegin) then
      Inc(x);
    Result := Result + s[n];
  end;
end;

 

Проверяем работу программы:

Synapse2

Как видите на поиск заголовка целевой странички мы потратили чуть больше 3-х килобайт трафика при весе страницы в 28 Кб.

Что можно сказать про предложенный выше способ частичного скачивания страницы?

  1. Обработчик события OnReadFilter хорош, когда в нем выполняется минимум операций – чем более громоздким он будет, тем больше времени “убьется” на фильтрацию и может случиться так, что быстрее будет скачать страницу целиком.
  2. Метод работает относительно быстро, когда необходимые данные находятся ближе к началу страницы и нет смысла его использовать, когда надо “стянуть” что-то с последних абзацев, футеров и т.д. – экономии пшик, а времени уйдет больше.
  3. Альтернативой этого события может служить событие OnMonitor, про которое можно прочитать тут.

Исходник рассмотренного в посте примера можно скачать по ссылке ниже:

Книжная полка

Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
купить книгу delphi на ЛитРес
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
купить книгу delphi на ЛитРес
0 0 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
6 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Andrey53
12/03/2011 02:42

Здравствуйте, статья понравилась, особенно, что расходуется меньше трафика, только мне больше нравится библиотека Indy, надо с ней попробовать. И что-то функция GetBetween слишком громоздкая, можно было сначала просто удалять все символы до искомой подстроки, а затем после искомой удалить все символы с помощью функции Delete

Александр
Александр
11/04/2011 00:58

Привет, а если сделать скачивание страницы с использованием range request, указав сколько нужно получить байт от начала страницы, такой вариант лучше использования парсеров

Poiree
Poiree
12/03/2013 16:53

Добрый день.
Помогите найти библиотеку synapse для delphiXE. Вот именно для этой версии ну никак не могу найти.
Спасибо.