Подписка

добавить на Яндекс

Наши проекты

Delphi+Google

Google API

Google API в Delphi - проект с открытым исходным кодом.

Chrono

Chrono

Хронометр - программа для ведения списка задач.

ODFProc

ODFProc

ODFProc - работа с документами OpenOffice в Lazarus и FreePascal.

Поддержка блога

А тут я коплю на лицензию Delphi XE на iPad =).
Сумма пожертвования не фиксирована.

Публикации

Год назад

Случайный пост

Последние

Сообщения форума

Комментарии

Социальные сети

Google

Facebook

Twitter

Опрос

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



Loading ... Loading ...

Блоги и сообщества

Статьи по Delphi DelphiFeeds.ru - Все Delphi-блоги Рунета Сообщество умных людей VR-Online.RU Бесплатный журнал для программистов и всех, кто интересуется IT Статьи и уроки по Delphi Новостной блог о высоких технологиях
Система Orphus
Опубликовал Vlad 21 августа 2009 в 08:36.
Категории: Delphi в Web.


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

Однако, прежде, чем начинать программировать, я настоятельно рекомендую Вам ознакомиться со статьей Wiki о DOM, т.к. без понимания всей сути вопроса будет очень трудно понять как всё работает.

Теперь давайте разберемся, что нам необходимо получить из документа, чтобы провести его анализ на предмет поисковой оптимизации (SEO)? Самое основное, на мой взгляд, при анализе любой страницы это:

  1. Заголовок страницы (Title).
  2. Количество ссылок и их тип (внутренние/внешние ссылки).
  3. Содержимое мета-тегов keywords и description.
  4. Содержимое всех заголовков H1-H5 (ну, или H10 - кому какая глубина анализа нужна)
  5. Подписи к рисункам, если таковые имеются на странице.
  6. Длину текста страницы и сам текст.

Имея в своем распоряжении перечисленные выше данные, мы сможем провести простейший анализ HTML-документа, а именно:

  1. Определить список ключевых слов.
  2. Определить плотность каждого ключевого слова/фразы на странице.
  3. Определить расположение ключевых слов на странице.
  4. При необходимости предложить пользователю список. предположительных ключевых слов/фраз.
  5. Выявить недочеты и ошибки SEO на странице.

Теперь давайте попробуем вытащить все необходимые данные.  Сегодня я не буду Вам советовать какие компоненты использовать, какой интерфейс придумать для программы, т.к. это все субъективные детали, а сосредоточусь именно на программном коде. Единственное, что следует сказать - это то, что для получения содержимого HTML-страницы я использую компонент Indy - idHTTP.

Итак, первое, что нам необходимо - это получить экземпляр DOM в свое распоряжении. Сделать это можно следующим образом:

var Doc: IHTMLDocument2; //экземпляр документа
procedure GetDom(const URL: string; idHTTP: TIdHTTP);
var Cache: string;
    V: OleVariant;
begin
  Cache:=IdHTTP.Get(url);
  Doc:=coHTMLDocument.Create as IHTMLDocument2; //создали экземпляр документа
  V:=VarArrayCreate([0,0], varVariant);
  V[0]:=Cache;
  Doc.Write(PSafeArray(TVarData(v).VArray)); //записали полученные данные
end;

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

1. Получение заголовка страницы (Title)

var Str: string;
begin
...
  Str:=Doc.title;
...
end;

2. Получение всех ссылок на странице

var Links: TStringList;
begin
...
  Links:=TStringList.Create;
  for i:=0 to Doc.links.length-1 do
    Links.Add(Doc.links.item(i));
...
end;

Если Вам необходимо получить анкоры ссылок, например, чтобы определить, что контекстная реклама, которую Вы заказывали у веб-мастера правильно проставлена на странице, то это делается следующим образом:

var DocA: IHTMLElementCollection; //коллекция элементов
    DocElement: IHtmlElement; //один элемент
    i: integer;
begin
...
  Links:=TStringList.Create;
  DocA:=Doc.all.tags('A') as IHTMLElementCollection;
  for i:=0 to DocA.length-1 do
    begin
      DocElement:=DocA.item(i,0)as IHTMLElement;
      Links.Add(DocElement.innerText) //читаем текст внутри тега
    end;
...
end;

3.  Получение содержимого мета-тегов keywords и description

Этот вопрос я рассматривал в статье про очистку HTML-документа от тегов. Единственная "сложноть" при работе с мета-тегами заключается в чтении не текста внутри тега, а атрибута content.

4. Получение содержимого всех заголовков H1-H5

Здесь всё аналогично работе с анкорами ссылок:

var DocA: IHTMLElementCollection; //коллекция элементов
    DocElement: IHtmlElement; //один элемент
    i: integer;
begin
...
  Links:=TStringList.Create;
  DocA:=Doc.all.tags('H1') as IHTMLElementCollection;
  for i:=0 to DocA.length-1 do
    begin
      DocElement:=DocA.item(i,0)as IHTMLElement;
      Links.Add(DocElement.innerText) //читаем текст внутри тега
    end;
...
end;

Аналогично, изменяя имя тега на Н2, Н3 и т.д. получаем содержимое всех тегов заголовков.

5.  Получение подписей к рисункам.

Немного посмотрев на исходные коды различных html-документов можно выделить следующие атрибуты тега IMG:

  • alt - короткое описание
  • title - заголовок для рисунка (такой атрибут используется, например, при вставке рисунка в пост WordPress)
  • longdesc - подробное описание рисунка (такой атрибут использует, например, редактор Front Page)

Таким образом, при чтении подписи к рисункам нам необходимо проверить наличие всех трех атрибутов и прочитать их:

var  img_alt : TStringList;
     DocA: IHTMLElementCollection; //коллекция элементов
     DocElement: IHtmlElement; //один элемент
     i: integer;
...
begin
...
  img_alt:=TStringList.Create;
  DocA:=Doc.all.tags('img')as IHTMLElementCollection;
  for i:=0 to DocA.length-1 do
    begin
      DocElement:=DocA.Item(i, 0) as IHtmlElement;//получили элемент коллекции
      //проверяем тег на наличие атрибута
      if length(DocElement.getAttribute('alt',0))>0 then
         img_alt.Add(DocElement.getAttribute('alt',0));
      else
        if length(DocElement.getAttribute('title',0))>0 then
          img_alt.Add(DocElement.getAttribute('title',0));
        else
          if length(DocElement.getAttribute('longdesc',0))>0 then
            img_alt.Add(DocElement.getAttribute('longdesc',0));
    end;
...
end;

6. Получение текста страницы

Здесь опять же все просто и понятно:

var body_html: string;
...
begin
...
  body_html:=Doc.Body.innerText;
...
end;

Теперь у Вас будут в руках все необходимые данные для анализа страницы. Анализируйте, ищите ошибки и недочеты, улучшайте свои сайты.

Мой блог находят по следующим фразам

Понравилась статья? Тогда:
Делись! Загружай! Плюсуй!
   Отправить PDF на   
Читай ещё статьи на WebDelphi.ru

Комментарии (26)

WP_Cloudy
  • Курский бомж пишет:

    В javascript на странице используется переменная с нужным мне значением, можно ли средствами delphi как-то получить её значение?

  • Vlad пишет:

    Самому как-то такие действия не приходилось выполнять, но, думаю, что в принципе возможно. Нужен пример html-странички и этой переменной.

  • Курский бомж пишет:

    Для себя программу пишу, подгружаю в webbrowser страничку http://old.station.ru/player.aspx?radio_id=5404 например, и хочу вытянуть программно название песни и артиста….

  • Vlad пишет:

    Просто так загрузить страничку и получить песню — не получится однозначно, т.к. название песни и автор передаются по запросу GET на адрес http://old.station.ru/getsong.aspx?id=station01. В исходном тексте этой страницы содержится, интересующая вас информация. Достаточно просто немного проанализировать http-заголовки ;)

  • Курский бомж пишет:

    Vlad, Спасибо большое! Теперь все намного проще :-) Как с сессией разделаюсь то по вашим статьям думаю без проблем выдеру из кода эту информацию, хоть и не пробовал еще ни разу :-)

  • Vlad пишет:

    Не за что :) Главное держите на такой случай всегда под рукой какой-нибудь инструмент для просмотра HTTP-заголовков. Думаю, что статья про каптчи должна пригодиться — там как раз работа со скриптами рассматривалась

  • Андрей пишет:

    Так-то всё бы оно ничего, только вот нет самого главного: поиск по DOM-дереву. Если мне нужно добраться до отдельных тегов без классов и id в разных местах кода, то вот тут и начинается настоящий геморрой.

  • sever пишет:

    Извените за тупой вопрос IHTMLDocument2 что это такое как подключить ?

  • sever пишет:

    У меня делфи7 подскажите, пожалуйста, Doc.Write(PSafeArray(TVarData(v).VArray)); у меня выдает UndeclaredIdentifier PSafeArray. Хотя и в подсказке все верно, но упорно пишет неопределен. :(

  • sever пишет:

    Все спс не надо, забыл просто в uses добавить Activex ))

  • sever пишет:
    var Doc: IHTMLDocument2; //экземпляр документа
    procedure GetDom(const URL: string; idHTTP: TIdHTTP);
    var Cache: string;
    V: OleVariant;
    begin
    Cache:=IdHTTP.Get(url);
    Doc:=coHTMLDocument.Create as IHTMLDocument2; //создали экземпляр документа
    V:=VarArrayCreate([0,0], varVariant);
    V[0]:=Cache;
    Doc.Write(PSafeArray(TVarData(v).VArray)); //записали полученные данные
    end;

    .

    Как обратиться к этой процедуре ? GetDom(‘какойтоЮрл’,?); выдает ошибку соккет еррор. Что с этим делать ? я прально передаю параметры ?

  • Vlad пишет:

    Что-то пока до компа добрался, а уже и вопросов не осталось :) Рад, что сами разобрались. Компонент Indy idHTTP на форме лежит? В параметрах GetDom его передаете?

  • Александр пишет:

    ЕДИНСТВЕННЫЙ НОРМАЛЬНЫЙ БЛОГ

  • Надежда пишет:

    2. Получение всех ссылок на странице
    Links.Add(Doc.links.item(i));

    [Error] Not enough actual parameters

  • damir пишет:

    Здравствуйте. Я не очень опытный программист, но мне нужно вытащить DOM с сайта. Можно вас попросить выложить элементарный код как это сделать. Адрес вводится через Edit, DOM выводится в поле MEMO. Или хотя бы объясните подробнее код представленный в самом начале. Очень нужно.

  • Vlad пишет:

    Так не проще тогда взять Indy и скачать сразу исходник страницы, чтоб TWebBrowser по форме не возить? Компонент idHTTP вроде бы там был. Делаете запрос GET и выгружаете исходник к себе в Memo

  • damir пишет:

    мне без разницы куда выводить, главное получить DOM в виде текста. мне получается нужно создать переменную, потом переменной придуть значение IdHTTP.Get(url); и дальше просто в блокнот скинуть значение переменной?

  • Vlad пишет:

    ну да. Я Indy не пользую, но по-моему есть перегруженные метод GET где можно после урла вторым параметром воткнуть TStrings куда сохранять текст

  • damir пишет:

    я не могу понять что такое IHTMLDocument2, где это взять? где смотреть?

  • Alexo пишет:

    uses MSHTML;

  • Андрей пишет:

    У меня всё получилось но при запуске вылетает табличка — типа
    «во время выполнения произошла ошибка, запустить отладку?
    Строка1. Синтаксическая ошибка»
     
    Как исправить.
    Программа работает но это окошко задолбало.
    Doc.Write(PSafeArray(TVarData(v).VArray));  - убираю и ошибки нет, но и толку от проги нет тоже.

  • Андрей пишет:

    Первую проблему решил. Теперь вторая
     
    Links.Add(Doc.links.item(i));  - пишет not enough actual parameter

  • Андрей пишет:

    Решил проблему так
     
    for i:=0 to Doc.links.length-1 do
    begin
    firstLink:=Doc.links.item(i,») as IHTMLElement;
    mmo2.Lines.Add(firstLink.toString) ;
    end; a:=a+1;
    until a=mmo1.lines.count-1;
     
    Правильно ли?

  • Vlad пишет:

    Ну, если работает правильно — значит правильно.

  • viRUS пишет:

    IdHTTP.Get(url); и дальше просто в блокнот скинуть значение переменной?

    var list:Tstringlist;
    begin
    list:=Tstringlist.Create;
    list:=IdHTTP.Get(url);
    list.SaveToFile(‘имя_файла’);
    list.Destroy;
    end;

  • viRUS пишет:

    поправка
    list.text:=IdHTTP.Get(url);

Ваш ответ

Внимание: Все комментарии модерируются, и это может вызвать задержку их публикации. Отправлять комментарий заново не требуется.

Пожалуйста, заключайте исходный код в тэги [code][/code].
Если код большой, то воспользуйтесь Вставкой кода на отдельной странице и оставьте в комментарии ссылку на исходник

   


ремонт автокранов