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

Пишу сейчас небольшое дополнение к «Блевантону» — включение в анализ страницы meta-тегов, заголовка, подписей к рисункам и т.д. в общем всего того текста, который учитывается поисковиками при индексации страницы.

Решил, не изобретая велосипед, воспользоваться уже готовыми решениями — форумов-то по Delphi в Рунете пруд пруди. Перерыл добрый полтинник сайтов и форумов в поисках подходящих процедур и функций — все не то. Может к концу первой сотни я бы и нашел чего-то стоящего, но терпения не хватило. Как обычно везде всё практически одно и то же с теми же недочетами в работе.

Больше всего улыбнула одна функция по разбору тегов страницы. Вот её код:

function GetNextTag(var Src:PChar; const Tag:string): string;
var PStart,PEnd: PChar;
begin
  Result := '';
  PStart := AnsiStrPos(Src,PChar('<'+Tag+#0));     
  if PStart = nil then     
    begin         
      Src := StrEnd(Src); 
      Exit;      
    end;     
  PStart := AnsiStrPos(PStart,PChar('>'+#0))+1;
  Src := PStart;
  PEnd := AnsiStrPos(Src,PChar('<!--'+Tag+'-->'+#0));
  if PEnd = nil then
    begin
      Src := StrEnd(Src); 
      Exit;
    end;
  Src := PEnd + Length(Tag) + 3;
  if PEnd = PStart then exit;
    SetLength(Result,PEnd - PStart);
  StrLCopy(@Result[1],PStart, Length(Result));
end;

Спору нет, функция написана по всем правилам и она корректно работает, но возникает одно «но» — но какое время займет чистка html-документа от тегов и при том чтение определенного набора атрибутов из этих тегов? Тем более, что функция не предусматривает чтения атрибутов, кстати сказать.
Остальные методы работы с html-документами, в принципе тоже недостаточно корректно работали с теми документами, которые я им давал на разбор. В числе прочих недостатков можно выделить следующие:

  • невозможность чтения данных из meta-тегов
  • игнорирование комментариев на странице
  • игнорирование конструкций вида
//<![CDATA[
addLoadEvent = function(func){if(typeof jQuery!="undefined")jQuery(document).ready(func);else if(typeof wpOnload!='function'){wpOnload=func;}else{var oldonload=wpOnload;wpOnload=function(){oldonload();func();}}};
var userSettings = {'url':'/','uid':'1','time':'1250247607'};
var ajaxurl = 'http://webdelphi.ru/wp-admin/admin-ajax.php', pagenow = 'post-new', adminpage = 'post-new-php';
//]]>

и ещё много разного рода недостатков. Вот я и решился на «изобретение». Представленный ниже способ очистки HTML-документа от служебной информации и html-тегов также не является панацеей от всех проблем, однако для меня он показал вполне удовлетворительные результаты.

Для работы нам понадобятся следующие компоненты: Edit, Button, Memo и idHTTP. Размещаете их на форме и подключаем дополнительно в uses два модуля: MSHTML и activex

Теперь на событие onClick у кнопки пишем следующий код:

procedure TForm1.Button1Click(Sender: TObject);
var Cache: string; 
   Doc: IHTMLDocument2;
   V: OleVariant;
   DocA: IHTMLElementCollection;
   DocElement: IHtmlElement;
   i:integer;
begin
  Memo1.Clear;
  Cache:=IdHTTP1.Get(Edit1.Text);
  Doc := coHTMLDocument.Create as IHTMLDocument2;
  V := VarArrayCreate([0, 0], varVariant);
  V[0]:=Cache;
  Doc.Write(PSafeArray(TVarData(v).VArray));
  DocA:=Doc.all.tags('meta')as IHTMLElementCollection;
  Memo1.Lines.Add(Doc.title);
  for i:=0 to DocA.length-1 do
    begin
      DocElement:=DocA.Item(i, 0) as IHtmlElement;
      Cache:=DocElement.getAttribute('name',0);
      if (LowerCase(Cache)='description')or(LowerCase(Cache)='keywords') then
        Memo1.Lines.Add(DocElement.getAttribute('content',0))
    end;
  Memo1.Lines.Add(Doc.body.innerText);
end;

Вот так в несколько строк мы получаем в Memo заголовок страницы, содержание мета-тегов keywords и description и основной текст со страницы.

Разберемся немного с тем, что написано в процедуре.

вначале загружаем весь документ в переменную Cache:

Cache:=IdHTTP1.Get(Edit1.Text);

теперь создаем новый экземпляр DOM страницы:

V := VarArrayCreate([0, 0], varVariant);
V[0]:=Cache;
Doc.Write(PSafeArray(TVarData(v).VArray));
Doc := coHTMLDocument.Create as IHTMLDocument2;

и применяем капельку знаний по работе с IHTMLDocument2 — создаем коллекцию всех meta-тегов страницы:

DocA:=Doc.all.tags('meta')as IHTMLElementCollection;

В цикле читаем атрибуты каждого элемента коллекции и, если аттрибут name удовлетворяет заданому условию — выписываем content мета-тега в Memo:

for i:=0 to DocA.length-1 do
begin
  DocElement:=DocA.Item(i, 0) as IHtmlElement;
  Cache:=DocElement.getAttribute('name',0);
  if (LowerCase(Cache)='description')or(LowerCase(Cache)='keywords') then
    Memo1.Lines.Add(DocElement.getAttribute('content',0))
end;

ну и в конце — вытаскиваем чистый текст из тела страницы (текст между тегами body):

Memo1.Lines.Add(Doc.body.innerText);

Это, можно сказать, даже не процедура, а заготовка для процедуры. Сейчас буду дорабатывать её в плане чтения атрибутов рисунков и прикручивать к «Блевантону«. Если у кого-нибудь есть более оригинальная идея по очистки html-документов — буду благодарен за идею.

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
3 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
Evgeniy
Evgeniy
10/11/2009 06:43

Привет,  работает то оно конечно хорошо но вот если сайт в виндовой колировке то получим не то что надо, как поправить?

trackback

[…] вопрос я рассматривал в статье про очистку HTML-документа от тегов. Единственная «сложноть» при работе с […]