В данной статье будет рассматриваться возможность парсинга текста в среде Delphi.
В программировании для SEO парсинг текста является важной состовляющей. Очень часто заказчику требуеться "слить" какой-либо ресурс, или данные для анализа.
Чтобы увидеть, как это выглядит на практике, попробуем произвести анализ выдачи Яндекса и сервиса wordstat.yandex.ru.
Для решения задачи в Delphi нам понадобятся два полезных класса: RegExp, для составления регулярных выражений и SwinHttp - для работы с протоколом http.
Создадим новый проект и подключим нужные модули. На основе SwinHttp создадим простенькую функцию, облегчающую создание запроса:

function QueryHttps(url: string): AnsiString;
var
http:TSwinHttp;
begin
 http:=TSwinHttp.Create(nil);
 http.InThread:=false; //Позволяет выводить запрос в отдельный поток.
 //Добавим заголовки
 http.Request.Agent:='Mozilla/5.0
        (Windows; U; Windows NT 5.1; ru; rv:1.9.0.15)
        Gecko/2009101601 Firefox/3.0.15'
;
 http.Request.Headers.Add('Accept:image/gif, image/jpeg, image/pjpeg,
            image/pjpeg,
            application/x-shockwave-flash, application/x-ms-application,
            application/x-ms-xbap, application/vnd.ms-xpsdocument,        
            application/xaml+xml, */*'
);
 http.Request.Headers.Add('Accept-Language:ru');
 http.Request.Headers.Add('Accept-Encoding:gzip, deflate');
    try
      http.Get(url);
      SetLength(result,http.Response.Content.Size);
      http.Response.Content.Read(result[1],http.Response.Content.Size);
    finally
      http.Free;
    end;
end;
 

Начнём с wordstat. Запрос за получение статистики выглядит следующим образом:
http://wordstat.yandex.ru/?cmd=words&page=1&text=Запрос&geo=&text_geo=
Наиболее важными для нас параметрами являются:
page - содержит номер просматриваемой страницы;
text - содержит ключевое слово, по которому осуществляется поиск.

Теперь создадим основную процедуру, которая вернёт динамический массив содержащий ключевое слово, и количество запросов по нему.
Для начала создадим тип данных, содержащий два поля: key и count

type TWordstat=record
  key: string;
  count: LongWord;
end;

type TWordstatArray=array of TWordstat; //тип данных динамического массива
 

Теперь посмотрим, как будет выглядеть запрос на страницу:

Utf8ToAnsi(QueryHttps('http://wordstat.yandex.ru/?cmd=words&page='+
        IntToStr(page)+'&text='+
        AnsiToUtf8(key)+'&geo=&text_geo='));
 

Страница в UTF, значит параметр мы должны закодировать, а результат перевести из UTF в ASNI.
Страница, которую возвращает wordstat, содержит несколько таблиц с данными. Нам нужна одна:

<table class="campaign" align="center" border="0" cellpadding="5" cellspacing="0" width="90%">
...
</table>

На основе класса RegExpr создадим простенькую функцию, возвращающую один элемент из множества:

 function regexp_value(pattern,text: string; index: integer=0): string;
 //pattern - шаблон, text - текст для анализа,
 //index - номер найденного шаблона
  var
  r: TRegExpr;
  begin
    result:='';
    r:=TRegExpr.Create;
      try
        r.Expression:=pattern;
        if(r.Exec(text))then
        result:=r.Match[index];
      finally
        r.Free;
      end;
  end;
 

Уберём весь контент, и оставим только нужную таблицу:

content:=regexp_value('<table class="campaign"
          align="center" border="0" cellpadding="5" cellspacing="0"
          width="90%">(.*?)</table>'
,content);
 

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

<tr class="tlist" [^>]+>.+?<a href=[^>]+>(.*?)</a>.+?<td align="right">([0-9]+)</td>.+?</tr>

В итоге получится следующая процедура:

procedure GetKey(var wArray: TWordstatArray; key: string; page: integer=1);
  var
    content: string;
    r: TRegExpr;
  begin
    SetLength(wArray,0); //Обнулим массив              
    content:=Utf8ToAnsi(QueryHttps('http://wordstat.yandex.ru/?cmd=words&
              page='
+IntToStr(page)+'&
              text='
+AnsiToUtf8(key)+'&geo=&text_geo='));
    content:=regexp_value('<table class="campaign"
          align="center" border="0" cellpadding="5"
          cellspacing="0" width="90%">(.*?)</table>'
,content);
      r:=TRegExpr.Create;
        try
          r.Expression:='<tr class="tlist" [^>]+>.+?<a href=[^>]+>(.*?)
          </a>.+?<td align="right">([0-9]+)
          </td>.+?</tr>'
;
          r.ModifierM:=true; //указываем что у нас многострочный текст
            if r.Exec(content) then
            //Если наш текст совпал с шаблоном,
            //то заберём весь результат в массив
              begin
               repeat
                  SetLength(wArray,length(wArray)+1);
                 //Увеличим размерность массива на 1
                  wArray[Length(wArray)-1].key:=r.Match[1];
                 //Запишем найденное ключевое слово
                  wArray[Length(wArray)-1].count:=StrToInt(r.Match[2]);
                 //Запишем количество запросов по найденному слову
                until not r.ExecNext;
              end;
        finally
          r.free;
        end;
    readln;
  end;
 

Теперь вызовем созданную процедуру, и выведем полученные элементы:

  GetKey(wArray{Массив},'hello'{Ключевое слово});
    for i:=0 to length(wArray)-1 do
      begin
        writeln(wArray[i].key,' - ',wArray[i].count);
      end;
    readln;
 

Парсинг выдачи Яндекса происходит аналогично. Небольшого изменения требует процедура GetKey:

procedure GetSearch(var sArray: TSearchArray;
          key: string; page: integer=0);
//Для большей ясности переименовали GetKey в GetSearch
  var
    content: string;
    r: TRegExpr;
  begin
    SetLength(sArray,0);
    content:=Utf8ToAnsi(
      QueryHttps('http://yandex.ru/yandsearch?text='
            +AnsiToUtf8(key)+'&
            p='
+IntToStr(page)));
      r:=TRegExpr.Create;
      r.ModifierM:=true;
        try
          r.Expression:='<li class="cr">.+?
          <a class="cs".+?href="(.+?)".+?
          <div class="kk">(.+?)</div>.+?</li>'
;
            if r.Exec(content) then
              begin
                repeat
                    SetLength(sArray,length(sArray)+1);
                    sArray[Length(sArray)-1].url:=r.Match[1];
                    //ссылка
                    sArray[Length(sArray)-1].description:=r.Match[2];
                    //описание ссылки
                until not r.ExecNext;
              end;
        finally
          r.Free;
        end;
  end;
 

Так же требуется убрать из заголовка параметр gzip, чтобы Яндекс отдавал нам страницу в чистом виде. Для этого заменим строку в функции QueryHttps

http.Request.Headers.Add('Accept-Encoding:gzip, deflate');
на
http.Request.Headers.Add('Accept-Encoding:deflate');

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

Скачать файлы проектов

Если Вас интересует восстановление флешки, обратитесь на сайт hetmanrecovery.com. Здесь Вы сможете купить программы для восстановления данных с флешек и жёстких дисков.