Остановлюсь на содержимом INI-файла. В секции MAIN разместим ссылку на сайт, который чаще всего проверяем и ключевые слова через разделитель. В секции SITE01 разместим информацию для парсинга Яндекса. Регулярное выражение для парсинга выдачи Яндекса составила, не особо заморачиваясь. Но оно недолговечно, может измениться, это надо помнить.
[MAIN]
DefSite=http://parsing-and-i.blogspot.com/
DefWords=парсинг|парсер на Delphi
[SITE01]
Name=Yandex.ru
NextPageTmpl=http://yandex.ru/yandsearch?p=[NumPage]&text=[Word]&numdoc=50
LinkRegExp=<a tabindex="\d{1,}".*href="(.*)" target="_blank">(.*)</a>(?:\x0D\x0A|\n|)</div>
Вместо [NumPage] при реализации алгоритма будем подставлять номер страницы в выдаче, вместо [Word] — поисковый запрос.
Алгоритм будет следующий: по очереди проходимся по списку поисковых систем, для каждой системы рассматриваем список ключевиков. Загружаем страницу результатов выдачи по запросу, выделяем все позиции сайтов, проверяем, есть ли сайт в выдаче. Если есть — смотрим место и переходим к следующему запросу. Если нет — переходим на следующую страницу (не заходя за рамки указанного для просмотра количества позиций). И так все операции в цикле. Результат выводим в грид.
Я намеренно не привела код на данном этапе. Алгоритм работает, все парсится. Оттестировав программу на Яндексе, я захотела продолжить вечеринку с Гуглем. Но...
Как в процессе любых разработок, со временем могут открываться новые детали, в соответствии с которыми нужно будет вносить изменения в код. К этому всегда надо быть готовым. Итак, начала заполнять данные по Google в ini-файле.
[SITE02]
Name=Google.ru
NextPageTmpl=http://www.google.com/search?q=[Word]&num=100&hl=ru&start=[NumPage]
Тут обнаружилось, что в Яндексе надо указать просто номер страницы, начиная с нуля, а в гугле надо указать номер позиции, с которой начинается отсчет (нумерация с нуля, как у всех программистов :) ). Похоже, придется делать заплату. Ввожу KoeffForPages. Внутри алгоритма буду умножать номер страницы на этот коэффициент. Для Яндекса он будет равен единице, а для Гугля — количеству выводимых позиций на странице.
В результате INI-файл содержит:
[MAIN]
DefSite=http://parsing-and-i.blogspot.com/
DefWords=парсинг|парсер на Delphi
[SITE01]
Name=Yandex.ru
NextPageTmpl=http://yandex.ru/yandsearch?p=[NumPage]&text=[Word]&numdoc=50
KoeffForPages=1
LinkRegExp=<a tabindex="\d{1,}".*href="(.*)" target="_blank">(.*)</a>(?:\x0D\x0A|\n|)</div>
[SITE02]
Name=Google.ru
NextPageTmpl=http://www.google.com/search?q=[Word]&num=100&hl=ru&start=[NumPage]
KoeffForPages=100
LinkRegExp=<h3 class=r><a href="(.*?)"
А класс в программе выглядит:
TSearcher = class
Name,
NextPageTmpl,
LinkRegExp : string;
KoeffForPages : integer;
end;
И так далее. Процесс программирования — вещь сама по себе очень интересная. Остальные поисковые системы я разбирать не буду.
После реализации алгоритма запускаю прогу:
Видали? По ключевику Парсер на Delphi я уже даже не самый лох в Google. А вот Яндекс этот блог в выдачу вообще не взял. Надеюсь, временно.
В исходниках можете посмотреть реализацию алгоритма. Но программа сырая — надо делать проверку позиций в отдельном потоке, чтобы главная форма не подвисала. Это будет домашним заданием тому, кому хоть как-то пригодилась эта моя статья. :)
Скачать: исходник парсера (6 кб), скомпиленный парсер (1,12 Мб).
А как нить, типа выложить готовый ini файл, с готовыми настройками можно. И если уж пишите про ini файл, может имеет смысл указать его имя, а то я его создал, а ваша программа ни фига не видит.
ОтветитьУдалитьДак выложена же прога полностью, там все есть: и экзешние, и ини-файл... какое у него там название - я уже не помню, сама прогой не пользуюсь, она была в качестве примера написана и там надо, если делать все по-правильному, кое-что переписать...
ОтветитьУдалитьСсылки на скачивание внизу статьи есть и вроде работают. Ini-файл должен лежать в одной директории с программой.
А мне понравилось. И пофик, что исходник открылся с ошибками (не нашел компонент грида и ещё что-то там). Не в этом дело. Главно, что можно просмотреть исходник и самому понять как должен называться файл и где он должен лежать) Думаю, что стоит продолжить эту тему :) Естественно с сохранением всех авторских прав на некоторые из функций
ОтветитьУдалитьда и ещё 1 момент. Если вдруг кто-то захочет воспользоваться исходниками. Регулярка для Яндекс срабатывает не всегда, т.е. она работает нормально но некоторые позиции не вытаскивает. Проблема кроется вот тута:
ОтветитьУдалить(?:\x0D\x0A|\n|) /div (див в треугольных скобках, с ними не дает коммент кинуть)
Если убрать эту подстроку, то вроде ьы всё нормально проходит. Вполне возможно, что чего-то Яндекс сменил в своей выдаче
Да, возможно, что Яндекс что-то поменял, я давно не проверяла)
ОтветитьУдалитьМаша, здравствуйте!
ОтветитьУдалитьВопрос к Вам по парсингу того же Гугла, но картинок. Странная вещь - написан кусок кода, который спокойно собирает картинки. В первый раз. Затем не выключая программы меняешь запрос - и все, гугл пишет didn't match any documents. Запускаешь программу заново - все опять находится. При этом idhttp cоздается динамически и даже никаких куки не хранит. Нужен хелп!
Заранее спасибо,
_dk_
_dk_, к сожалению, я не экстрасенс, по одному описанию, без кода, не могу вам помочь решить проблему :)
ОтветитьУдалитьСорри, не прикрепился(
ОтветитьУдалитьprocedure google;
var s: TStringstream; e,ssize,slink: string; jtmp,z:Byte; idhttp12:TIdHTTP;
begin
s:=TStringstream.Create('');
e:='';
goj:=0;
idhttp12:=tidhttp.Create(nil);
for jtmp:=1 to 21 do begin
go[jtmp].url:='';
go[jtmp].w:=0;
go[jtmp].h:=0;
end;
slink:='http://www.google.com/images?um=1&hl=en&newwindow=1&tbs=isch%3A1&sa=1&q='+sxnamepl+'+'+sxalbumpl+'&aq=f&aqi=&aql=&oq=&gs_rfai=';
repeat
try begin
IdHTTP12.Disconnect;
IdHTTP12.AllowCookies:=false;
idHTTP12.Response.KeepAlive:=true;
IdHTTP12.request.useragent:=useragents[Random(8)+1];IdHTTP12.Disconnect;
IdHTTP12.Get(slink,s);
end;
finally
idhttp12.Free;
end;
e:=s.DataString;
if e<>'' then Break;
until False;
repeat
if Pos('["/imgres?imgurl\x3d',e)=0 then begin
break;
end;
Delete(e,1,Pos('["/imgres?imgurl\x3d',e)+length('["/imgres?imgurl\x3d')-1);
inc(goj);
go[goj].url:=Copy(e,1,Pos('\',e)-1);
for jtmp:=1 to 18 do begin
Delete(e,1,pos('"',e));
end;
ssize:=Copy(e,1,Pos('×',e)-2);
z:=0;
while z0 then begin
delete(ssize,pos(' ',ssize),1);
dec(z);
end;
if pos(#$A,ssize)>0 then begin
delete(ssize,pos(#$A,ssize),1);
dec(z);
end;
if pos(#$D,ssize)>0 then begin
delete(ssize,pos(#$D,ssize),1);
dec(z);
end;
end;
go[goj].w:=StrToInt(ssize);
ssize:=Copy(e,Pos('×',e)+8, pos('-',e)-pos('×',e)-8);
z:=0;
while z0 then begin
delete(ssize,pos(' ',ssize),1);
dec(z);
end;
if pos(#$A,ssize)>0 then begin
delete(ssize,pos(#$A,ssize),1);
dec(z);
end;
if pos(#$D,ssize)>0 then begin
delete(ssize,pos(#$D,ssize),1);
dec(z);
end;
end;
go[goj].h:=StrToInt(ssize);
if (go[goj].h>picparam) or (go[goj].w>picparam) then
Dec(goj);
until False;
s.free;
end;
В первый раз все отлично находится, потом на вход подаются другие sxname и sxalbum, и Pos('["/imgres?imgurl\x3d',e)=0 и гугл выдает страницу с надписью did not match any documents, хотя на деле там все есть. Где мог какой хвост остаться? Или еще как?
Заранее спасибо,
_dk_
Ой, как много всего написано :) Мда... я сейчас на работе, мне пока некогда разбираться в этом коде. Как будет свободное время — посмотрю. Если, конечно, до этого времени вы сами не найдете, в чем там трабла.
ОтветитьУдалитьсмену юзерагентов он не любит почему-то..
ОтветитьУдалитьвсе заработало, в любом случае, спасибо)
_dk_
Мария и все читатели этого блога!!!)))
ОтветитьУдалитьПожалуйста,помогите написать похожий парсер для поисковиков на Objective-C !!! очень нужен!)))
Олег, думаю, ничего сложного... Но вряд ли кто прямо тут вам выдаст готовое решение) Если умеете программировать — программируйте... или можно на фрилансе поискать исполнителя)
ОтветитьУдалитьЕсли когото интересует могу дать или выложить исходник парсера google.com на C++.
ОтветитьУдалитьМой ICQ 553-189-009