Как Вы понимаете, этот пост никак не связан с домушничеством и воровством :). Сегодня я поделюсь с Вами ещё одним простым способом получения необходимой информации из Web-документов.
Однако, прежде, чем начинать программировать, я настоятельно рекомендую Вам ознакомиться со статьей Wiki о DOM, т.к. без понимания всей сути вопроса будет очень трудно понять как всё работает.
Теперь давайте разберемся, что нам необходимо получить из документа, чтобы провести его анализ на предмет поисковой оптимизации (SEO)? Самое основное, на мой взгляд, при анализе любой страницы это:
- Заголовок страницы (Title).
- Количество ссылок и их тип (внутренние/внешние ссылки).
- Содержимое мета-тегов keywords и description.
- Содержимое всех заголовков H1-H5 (ну, или H10 - кому какая глубина анализа нужна)
- Подписи к рисункам, если таковые имеются на странице.
- Длину текста страницы и сам текст.
Имея в своем распоряжении перечисленные выше данные, мы сможем провести простейший анализ HTML-документа, а именно:
- Определить список ключевых слов.
- Определить плотность каждого ключевого слова/фразы на странице.
- Определить расположение ключевых слов на странице.
- При необходимости предложить пользователю список. предположительных ключевых слов/фраз.
- Выявить недочеты и ошибки 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;
Теперь у Вас будут в руках все необходимые данные для анализа страницы. Анализируйте, ищите ошибки и недочеты, улучшайте свои сайты.
Мой блог находят по следующим фразам
- delphi 7 исходник напоминалка
- получение информации о заголовке сервера delphi
- lazarus уменьшить размер
- synapse get
- диаграмма в excel delphi
- облако тегов без интернета
| Делись! | Загружай! | Плюсуй! |
| | |









11 Дек 2009 в 10:33 пп
В javascript на странице используется переменная с нужным мне значением, можно ли средствами delphi как-то получить её значение?
12 Дек 2009 в 7:39 дп
Самому как-то такие действия не приходилось выполнять, но, думаю, что в принципе возможно. Нужен пример html-странички и этой переменной.
13 Дек 2009 в 1:23 пп
Для себя программу пишу, подгружаю в webbrowser страничку http://old.station.ru/player.aspx?radio_id=5404 например, и хочу вытянуть программно название песни и артиста….
13 Дек 2009 в 9:11 пп
Просто так загрузить страничку и получить песню — не получится однозначно, т.к. название песни и автор передаются по запросу GET на адрес http://old.station.ru/getsong.aspx?id=station01. В исходном тексте этой страницы содержится, интересующая вас информация. Достаточно просто немного проанализировать http-заголовки ;)
13 Дек 2009 в 10:00 пп
Vlad, Спасибо большое! Теперь все намного проще :-) Как с сессией разделаюсь то по вашим статьям думаю без проблем выдеру из кода эту информацию, хоть и не пробовал еще ни разу :-)
14 Дек 2009 в 7:37 дп
Не за что :) Главное держите на такой случай всегда под рукой какой-нибудь инструмент для просмотра HTTP-заголовков. Думаю, что статья про каптчи должна пригодиться — там как раз работа со скриптами рассматривалась
01 Мар 2010 в 5:19 дп
Так-то всё бы оно ничего, только вот нет самого главного: поиск по DOM-дереву. Если мне нужно добраться до отдельных тегов без классов и id в разных местах кода, то вот тут и начинается настоящий геморрой.
17 Мар 2010 в 10:51 пп
Извените за тупой вопрос IHTMLDocument2 что это такое как подключить ?
17 Мар 2010 в 11:11 пп
У меня делфи7 подскажите, пожалуйста, Doc.Write(PSafeArray(TVarData(v).VArray)); у меня выдает UndeclaredIdentifier PSafeArray. Хотя и в подсказке все верно, но упорно пишет неопределен. :(
17 Мар 2010 в 11:31 пп
Все спс не надо, забыл просто в uses добавить Activex ))
18 Мар 2010 в 12:14 дп
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(‘какойтоЮрл’,?); выдает ошибку соккет еррор. Что с этим делать ? я прально передаю параметры ?
18 Мар 2010 в 1:03 пп
Что-то пока до компа добрался, а уже и вопросов не осталось :) Рад, что сами разобрались. Компонент Indy idHTTP на форме лежит? В параметрах GetDom его передаете?
11 Дек 2010 в 12:27 дп
ЕДИНСТВЕННЫЙ НОРМАЛЬНЫЙ БЛОГ
11 Мар 2011 в 12:22 дп
2. Получение всех ссылок на странице
Links.Add(Doc.links.item(i));
[Error] Not enough actual parameters
26 Апр 2011 в 3:44 пп
Здравствуйте. Я не очень опытный программист, но мне нужно вытащить DOM с сайта. Можно вас попросить выложить элементарный код как это сделать. Адрес вводится через Edit, DOM выводится в поле MEMO. Или хотя бы объясните подробнее код представленный в самом начале. Очень нужно.
26 Апр 2011 в 4:30 пп
Так не проще тогда взять Indy и скачать сразу исходник страницы, чтоб TWebBrowser по форме не возить? Компонент idHTTP вроде бы там был. Делаете запрос GET и выгружаете исходник к себе в Memo
26 Апр 2011 в 5:20 пп
мне без разницы куда выводить, главное получить DOM в виде текста. мне получается нужно создать переменную, потом переменной придуть значение
IdHTTP.Get(url); и дальше просто в блокнот скинуть значение переменной?
26 Апр 2011 в 6:18 пп
ну да. Я Indy не пользую, но по-моему есть перегруженные метод GET где можно после урла вторым параметром воткнуть TStrings куда сохранять текст
26 Апр 2011 в 11:01 пп
я не могу понять что такое IHTMLDocument2, где это взять? где смотреть?
28 Апр 2011 в 4:09 пп
uses MSHTML;
30 мая 2011 в 6:41 пп
У меня всё получилось но при запуске вылетает табличка — типа
«во время выполнения произошла ошибка, запустить отладку?
Строка1. Синтаксическая ошибка»
Как исправить.
Программа работает но это окошко задолбало.
Doc.Write(PSafeArray(TVarData(v).VArray)); - убираю и ошибки нет, но и толку от проги нет тоже.
30 мая 2011 в 8:36 пп
Первую проблему решил. Теперь вторая
Links.Add(Doc.links.item(i)); - пишет not enough actual parameter
30 мая 2011 в 9:26 пп
Решил проблему так
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;
Правильно ли?
30 мая 2011 в 9:38 пп
Ну, если работает правильно — значит правильно.
12 Авг 2011 в 8:57 пп
IdHTTP.Get(url); и дальше просто в блокнот скинуть значение переменной?
var list:Tstringlist;
begin
list:=Tstringlist.Create;
list:=IdHTTP.Get(url);
list.SaveToFile(‘имя_файла’);
list.Destroy;
end;
18 Авг 2011 в 12:05 дп
поправка
list.text:=IdHTTP.Get(url);