Прежде чем начать хотелось бы сразу обратить внимание, что данная статья содержит лишь ознакомительный характер и не предназначена для получения базы E-mail адресов в корыстных целях(Spam‘a). Хотя в целом, наша программа спокойно может бродить по просторам интернета без нашего вмешательства и собирать ту или иную информацию, в моем случае это e-mail адреса. Итак для того чтобы приступить к изучению учебного материала, потребуется установленный пакет Indy или Synapse.
В своей программе я использовал следующие компоненты:
- TIdHTTP
- IdAntiFreeze
Остальные компоненты входят в стандартный набор Lazarus.
Для обеспечения производительности программы для работы с HTTP запросами, я создал отдельный класс. В результате чего теперь можно регулировать количество создаваемых потоков из самой программы.
Задумка была такова: Даем программе несколько начальных адресов сайтов. Программа заходит на эти адреса, ищет различные ссылки на другие сайты, а также e-mail адреса, проверяет их уникальность и записывает их. Для записи ссылок и E-mail я создал 2-ва Memo, чтобы избежать зависания программы, обращения к ним происходит через главный поток с помощью Synchronize. Вынес StatusBar для отображения хода выполнения и в результате получил нечто следующие:
Как видно на картинках, с помощью компонента PageControl добавил 2-ве страницы. На первой странице: наша рабочая область, на второй: настройки для производительность нашей программы, а так же настройка прокси.
Весь исходный код описывать в статье не буду, готовую работу можно будет скачать в конце данной статьи. Разберем наиболее интересные части программы.
И так. На форме присутствует 2-ве кнопки. Первая это Start и вторая Х кнопка аварийно завершающая(убивающая) все потоки в программе.
Кнопка Start:
procedure TForm1.ButtonStartClick(Sender: TObject);
var i:Integer;
begin
CountURL:=0; //Переменная которая говорит с какой ссылки начать
SleepTimes:=StrToIntDef(EditSleep.Text,0); //Время ожидания перед новым сайтом
SetLength(T1,StrToIntDef(EditCountTh.Text,1)); //Колличество потоков
For i:=0 to Length(T1) do
begin
T1[i]:=TGo.Create(False); //Создание потока
T1[i].Priority:=tpLowest; //Приоритет потока
end;
ButtonStart.Enabled:=False;
end;
T1 описан выше как массив созданного мною класса потока. В коде имеет следующий вид:
TGO = Class(TThread)
Private
URL,NewURLs, //Текущие адрес и новый адрес страниц
NewEmails:String; //E-mail адрес
Procedure GetURL; //Ко всем процедурам ниже в программе обращаюсь через Synchronize
Procedure IncURL;
Procedure NewURL;
Procedure NewEmail;
Procedure StatusBar;
Public
procedure Execute; override; //Основная процедура, запускается при создании потока.
end;
var
T1: array of TGO; //Динамический массив. Размер определяем при нажатии на кнопку Start
Хочу обратить ваше внимание, что работать с динамическим массивом мы не можем, пока не определим его размер. Пока размер не определен, программа не выделяет под него место в памяти.
Для того чтобы остановить выполняющийся поток, нужно:
procedure TForm1.ButtonThreadStopClick(Sender: TObject);
var i:integer;
begin
for i:=0 to Length(T1) do
KillThread(T1[i].Handle); //Остановить работающие потоки
ButtonStart.Enabled:=True;
end;
А теперь самая интересная часть, основной код процедуры потоков:
procedure TGO.Execute;
var
Http:TidHttp;
Result,ResultNewURL:String;
i:Integer;
S:String=''''; //Так мне было проще понять что я ищу. Здесь записана одинарная кавычка: '
begin
try
Http:=TIdHTTP.Create;
http.ConnectTimeout:=StrToIntDef(Form1.EditHttpTime.Text,3)*1000; //TimeOut соединения
http.ReadTimeout:=StrToIntDef(Form1.EditHttpTime.Text,3)*1000; //TimeOut соединения
while Form1.CountURL<Form1.MemoURL.Lines.Count do //Пока не последняя строка в Memo продолжаем.
begin //Строки постоянно добавляются....
Synchronize(@GetUrl); //Обращаемся к Memo на форме для получения ссылки
try
Synchronize(@StatusBar); //Обновляем информацию
Synchronize(@IncURL); //Увеличиваем счетчик ссылки
Result:=http.Get(URL); //Получаем Html страницу
ResultNewURL:=Result; //Дублируем ее для парсинга
//Поиск Email
while Ansipos('mailto:',Result)<>0 do
begin
Delete(Result,1,Ansipos('mailto:',Result)+length('mailto:')-1);
I:=1;
While (Result[I]<>'>') and (Result[I]<>'?')
and (Result[I]<>'"') and (Result[I]<>S) do inc(I);
NewEmails:=copy(Result,1,I-1);
if pos(NewEmails,Form1.MemoEmail.Text)=0 then Synchronize(@NewEmail); //Проверяем уникальность и добавляем емаил
end;
//Поиск ссылок
while Ansipos('<a href=',ResultNewURL)<>0 do
begin
Delete(ResultNewURL,1,Ansipos('<a href=',ResultNewURL)+length('<a href=')-1);
I:=2;
While (ResultNewURL[I]<>'>') and (ResultNewURL[I]<>'"')
and (ResultNewURL[I]<>S) do inc(I);
I:=I-2;
if Copy(ResultNewURL,2,8)='https://' then Continue; //В данной программе я не стал реализовывать работу с https
if Copy(ResultNewURL,2,7)='http://' then
NewURLs:=copy(ResultNewURL,2,I) else
NewURLs:='http://'+http.URL.Host+'/'+copy(ResultNewURL,2,I);
if pos(NewURLs,Form1.MemoURL.Text)=0 then Synchronize(@NewURL); //Аналогично емаил проверяем уникальность и добавляем в список.
end;
except
//Битая ссылка. Можно удалять ссылку из мемо, но тогда она может вторично там появится
//поэтому оставлю данный блок на ваше усмотрение.
end;
Sleep(SleepTimes*1000);
end;
finally
http.Free;
end;
end;
Вот в принципе и все. Я описал основную часто программы. Далее вам остается лишь дописать процедуры по добавлению ссылок в список, обновлению информации о ходе выполнения и так по мелочи +)
С помощью данной программы можете попробовать написать свой поисковик(А ты создал свой Google?), сохраняя html страниц, после чего написать свой код поиска по сохраненным данным. 
Конечно это не полностью готовый проект, и в нем есть маленькие недочеты. Но я думаю вам не составит труда довести ее до ума. Если возникнут вопросы, буду рад помочь. 
Скачать исходники: E-mail to web




никак не поставить indy, вроде все как все делаю при пересборке пишет IdAntiFreeze.pas(78,15) Error: Forward declaration not solved «Process;»