Поиск по блогу

четверг, 22 января 2009 г.

Относительные ссылки при использовании coHTMLDocument

Задавшись вопросом, поднятым в комментариях к предыдущей записи, решила порыскать в сети. Да, в большинстве случаев люди обрабатывают ссылки вручную. Но есть еще один выход: добавить в HTML-код элемента тег "BASE" с указанием адреса страницы.

Изменим код, приведенный в качестве примера к предыдущей записи.
Вместо
v[0] := SLBody.Text;

Напишем:
v[0] := AddBASE(SLBody.Text,'http://adresa.yandex.ru/');


И отдельно процедурка, добавляющая тег BASE сразу после тега HEAD.

function AddBASE(PageText, BASEURL: String) : String;
var
Str : String;
begin
Str := '<base href="' + BASEURL + '">';
Result := StringReplace(PageText,'<head>',Str,[rfIgnoreCase]);
end;


Конечно, не совсем красиво, но зато работает, я проверила. DocElement.getAttribute('href',0) выдает ссылки в красивом виде:

parser yandex adresa

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

Чтобы быть в курсе обновлений блога, можно подписаться на RSS.
___

После переноса фида на Google, счетчик совсем сошел с ума :) Адрес фида немного изменился, так что желательно изменить адрес подписки на http://feeds2.feedburner.com/parsing-lessons. А если еще не подписались на обновления, но тематика блога вам интересна — подписывайтесь! :)

пятница, 16 января 2009 г.

Когда на форме нет места TWebBrowser-у

Еще один пост из серии для начинающих осваивать работу с интернетом в среде Delphi.

Как вы уже поняли, работать с DOM html-страницы гораздо удобнее, чем работать непосредственно с html с помощью регулярных выражений. Но компонент TWebBrowser на форме нам совсем не нужен. Можно просто скачать страницу, а потом создать экземпляр класса coHTMLDocument и работать с ним.

Код, иллюстрирующий сказанное:

uses
... MSHTML, UrlMon, activex;

function DownloadFile(SourceFile, DestFile: string): Boolean;
begin
try
Result := UrlDownloadToFile(nil, PChar(SourceFile), PChar(DestFile), 0,
nil) = 0;
except
Result := False;
end;
end;

procedure TMainF.cxButton1Click(Sender: TObject);
var
sFileName : string;
i: integer;
v : OleVariant;
Doc : IHTMLDocument2;
DocAll,
DocA : IHTMLElementCollection;
AParentElement,
DocElement : IHtmlElement;
SLBody : TStringList;
begin
// загружаем страницу
try
SLBody:=TStringList.Create;

sFileName:=ExtractFilePath(Application.ExeName) + 'cache.txt';
if DownloadFile(RegionURL,sFileName) then
SLBody.LoadFromFile(sFileName);
DeleteFile(sFileName);

Doc := coHTMLDocument.Create as IHTMLDocument2;
if Doc = nil then
begin
ShowMessage('Ошибка создания IHTMLDocument2');
exit;
end;

v := VarArrayCreate([0,0],VarVariant);
v[0] := SLBody.Text;
Doc.write(PSafeArray(TVarData(v).VArray));
DocAll := Doc.all;
DocA := DocAll.Tags('A') as IHTMLElementCollection;

for i := 0 to DocA.length-1 do
begin
DocElement := DocA.Item(i, 0) as IHtmlElement;
AParentElement := DocElement.parentElement;

if LowerCase(AParentElement.tagName) = 'li' then
begin
S := DocElement.innerHTML + ' ['+ DocElement.getAttribute('href',0) +']';
mRequest.Lines.Add(S);
end;
end;
finally
begin
SLBody.Free;
Doc.Close;
Doc := nil;
end;
end;
end;


Как видите, все просто.
В примере показана работа с атрибутом href ссылки. Отличие от работы с атрибутом href ссылок кода, предварительно загруженного в TWebBrowser, будет состоять в том, что относительные ссылки отражаются немного по-другому. Например, если в коде есть ссылка "href=/?region=1", то результатом кода
DocElement.getAttribute('href',0)

будет "about:blank/?region=1". Это связано с тем, что страницей по умолчанию объекта является about:blank. Но это не страшно. Можно их обработать и привести к нужному виду.

Удачных разработок!
___

А сама я помимо программирования решила попробовать поработать с биржей ссылок Nahaa.ru. Если еще не знаете, что это такое и с чем это едят, то можете почитать историю о моем освоении этого сервиса.

Чтобы быть в курсе обновлений блога, можно подписаться на RSS.

понедельник, 12 января 2009 г.

Как запретить окна "Script Error" в TWebBrowser

Хозяйке на заметку :)
How to Suppress / Disable Script Errors in WebBrowser ControlБывает, что в жизни случается всякая фигня, например, при работе в TWebBrowser внезапно вылазят сообщения об ошибках сценария. Наглядный пример — слева. Убрать/предотвратить появление этих сообщений можно так:
WebBrowser.Silent := true;


Чтобы быть в курсе обновлений блога, можно подписаться на RSS.

вторник, 6 января 2009 г.

Создание карты блога на blogspot.com своими руками

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

Чтобы создать карту блога на blogspot.com (я рассматриваю в качестве примера свой лытдыбровый блог), можно воспользоваться головой и данными из виджета "Архив блога". Изучим код страницы. Виджет оформлен как div с id='ArchiveList'. Внутри дива — ненумерованный список. Элементы UL, группирующие ссылки по месяцам, имеют classname='posts'. Сразу становится понятно, что для создания карты сайта достаточно будет выбрать все элементы LI, находящиеся внутри упомянутых UL. Это делается в два счета при работе с MSHTML.

Обработчик кнопки "Start":

procedure TBlogspotSiteMapF.btnStartClick(Sender: TObject);
var
Doc : IHTMLDocument2;
DocAll,
DocLi : IHTMLElementCollection;
ParentElement,
DocElement : IHtmlElement;

i : integer;
begin
WebBrowser.Navigate(edtURL.Text);
while WebBrowser.ReadyState <> READYSTATE_COMPLETE do
begin
Application.ProcessMessages;
end;

Doc := WebBrowser.Document as IHTMLDocument2;
if Assigned(Doc) then
begin
DocAll := Doc.all;
DocLi := DocAll.Tags('LI') as IHTMLElementCollection;

for i := 0 to DocLi.length-1 do
begin
DocElement := DocLi.Item(i, 0) as IHtmlElement;
ParentElement := DocElement.parentElement;

if ParentElement.className = 'posts' then
Memo.Lines.Add(DocElement.innerHTML);
end;
end;
end;


В результате получаем такую картину:



После парсинга первоначального списка обнаружились некоторые ньюансы. А именно: записи, имеющие слишком длинные названия, обрезаются по количеству символов (на рисунке для примера я обвела красным ссылку и пример заголовка одного из таких сообщений). Но это не страшно и вопрос решается очень просто: надо скачать страницу по ссылке и достать из html-кода полный заголовок (внутри h3 с classname = 'post-title entry-title'). В принципе, я думаю, что данная процедура необязательна, так как карты сайтов используются в основном поисковиками. Тем более, что если записей в блоге очень много — это мероприятие может оказаться затратным :)



Чтобы быть в курсе обновлений блога, можно подписаться на RSS.

Поделиться