是不有真的高手,都不来指导指导后辈的。(在线等)。。(100分)

  • 主题发起人 主题发起人 hlhhh
  • 开始时间 开始时间
H

hlhhh

Unregistered / Unconfirmed
GUEST, unregistred user!
我要做的是 一个只搜索网址的(网络蜘蛛)爬爬虫类工具。给你一个主页,按我们给出条件的搜索出它目录下的所有网页,然后存在数据库里。。
举个例子输入www.163.com 然后条件是music。那么搜索出来的网址必须是163.com目录下的,而且这些网址里必须包含有music字符。。一个网址 有很多层,所以需要进行循环搜索。我出的问题是在这循环上。。
我现在是把 所有记录都存在 一个字符串数组变量(urlstring)里的,记录少的话,还是可行的。。但是超过1万条以上,就差不多需要3个小时以上。最重要的问题是 内存飙升。。。如果记录达到10万以上或是更多会占满内存的,那样应该是死机了。大家替我想想办法,解决这占超大内存的问题。
我如今的程序是这样子的。
procedure TfrmGetInform.Button1Click(Sender: TObject);
var
i:Integer;
begin
if ADOConnection1.Connected then
ADOConnection1.Close;
ADOConnection1.Connected:= true;
Memo1.Lines.Clear;
Memo1.Lines.Add('开始时间'+DateTimeToStr(Now));
GetStrCondition;
CheckURLInform;
GetUrlType;
urlstring[0]:= RootUrl;
for i:=0 to length(urlstring)-1 do //
begin
if not searchFlag then break;
if urlstring = '' then break;
GetAllUrl(urlstring);
end;
//存为数据库中去
for i:=0 to length(urlstring)-1 do
begin
if urlstring = '' then break;
SavesToDataBase(urlstring);
end;
Memo1.Lines.Add('结束时间'+DateTimeToStr(Now));
Memo1.Lines.Add('总共条数'+InttoStr(i));
Button1.Enabled:= false;
Button2.Enabled:= true;
// Button2.Click;
end;
//执行获取下层连接
procedure TfrmGetInform.GetAllUrl(surl:string);
var
str,sStr:string;
i:Integer;
pstr:string;
furl:string;
sonarr:array of string;
begin
sStr:='';
pstr:= '';
furl:='';
setlength(sonarr,100000);
if strCondition = '' then exit;
sStr:= GetWebPage(surl);
str:= IncludeStr(sStr);
sonarr[0]:= surl;
while str <>'' do
begin
if pos('&quot;',str)>0 then
str:= copystr(str,'&quot;',-1);
furl:= UrlConfig(surl,str);
if furl <> '' then
begin
for i:=0 to length(sonarr)-1 do
begin
if furl = sonarr then break;
if sonarr='' then
begin
sonarr:= furl;
break;
end;
end;
end;
str:= IncludeStr(allStr);
end;
for i:= 1 to length(sonarr)-1 do
begin
if sonarr='' then exit;
CheckUrlIsExist(sonarr);
if not searchFlag then exit;
end;
end;
//比较是否有重复
procedure TfrmGetInform.CheckUrlIsExist(fstr:string);
var
i:Integer;
m,n:string;
begin
m:='';
n:='';
for i:=0 to length(urlstring)-1 do
begin
if (fstr = urlstring) then exit;
m:= urlstring+'/';
if (fstr= m)then exit;
n:= fstr + '/';
if (n = urlstring) then exit;
if urlstring ='' then
begin
urlstring:= fstr;
//SavesToDataBase(fstr);
Memo1.Lines.Add(InttoStr(i)+'.'+urlstring);
if urlstring[length(urlstring)-1] <> '' then
searchFlag:= false;
//停止搜索
exit;
end;
end;
end;


能具体请教的,希望留下QQ或者MSN,或是加我。可以吗?? QQ157647204---MSN:mzh198420@hotmail.com
谢谢 祝大家七夕快乐。
 
好长 好长
 
这位老兄 。。替小弟看看啊。。
 
其实问题的关键你已经找到了啊,对吧,就是记录多了,内存狂升。那么你先描述一下,你要做的是什么,而不是把代码贴上来,这样才好,如果你的代码有问题,才贴代码上来,别人看。这个是你解决问题的思想问题,不是代码问题。所以自己描述一下自己要做的是什么,你这里面怎么做的。
 
恩。。我想到过还有一种方法。就是直接跟数据库 进行存取。。一搜到新记录就存入数据库。同时开线程及时获取数据库的记录条数 传给 外面的那个搜索循环。可是频繁操作数据库 内存好象也一直升。还有 开线程获取数据库记录条数,怎么样一直在进行着。
 
哈哈,你还没有搞懂我要你说什么东西了。现在我要你描述的是你要做一个什么东西,连你要做什么都不知道,就直接看你的解决方案,怎么能看懂呢?对吧,先描述一下,你要做什么的问题!
 
我要做的是 一个搜索网址。给你一个主页,按我们给出条件的搜索出它目录下的所有网页,然后存在数据库里。。
 
搜索条件是怎么给出的?从数据库读?对于搜索的记录你可以先存在本地啊,然后搜索完了之后再保存回数据库啊,为什么在这个过程中需要一直和数据库连接呢?
 
那我搜一条存一条是要经常跟数据库操作。还有我要对新搜索出来的网址也要进行再一次搜索,直到搜索出来的网址 数据库里都已经存在了 并且数据库里的记录都已经对它操作过了就算搜索完成了。
你可以告诉我QQ或者MSN吗? 我好仔细向你讨教呢。
 
我的qq:185973142
 
不用数据库,那你将数据加到文本文件中去啊,按照结构建立多个文件夹和文本文件,只要你自己注意不要晕就行了
 
我仔细看了你的代码知道你要做的事情了
但是你这个程序有两点我认为很不好
1.使用一个大数组,虽然编程比较方便,但是存在大量消耗内存,而且当你的电脑死机或者你的程序异常那么前面的搜索结果前功尽弃
2.每添加一条新的搜索结果都要和以前的所有数据比较一下,这样做效率非常低
上面也有朋友提到了实时保存到数据库,这当然是一种解决方法,但走了节省内存却消耗速度的另一个极端,我们可以采用折衷的方法解决
1.使用Array of string或者直接使用TStringList或者TList作为容器保存搜索结果
2.设定一个常数MAX_LIMIT,比如等于100,当你的容器中的数据达到这个限制常数则做一次保存工作(保存到数据库)并清空容器内的数据。
3.保存到数据库:使用一定的规则保存数据,比如字母排序,这样就提高了查询的速度。在保存的同时做比较操作,看是否与以前的网页相同,因为数据表已经进行了索引,查询效率就非常高
 
可以具体说吗??
我的问题是 我把这些数据存到了 定义好的字符串数组(也就是内存中),所以会造成了内存耗尽的问题。如果不存在内存中的话, 循环搜索 能够继续进行吗?
 
to muhx
如果第一次搜索,就到了限制数MAX_LIMIT,然后清除容器,那么进行第二层搜索时,不是要到数据库里去获取了吗?
就象这样 www.163.com 搜索出了 3条数据
http://www.163.com/fadfa.htm
http://www.163.com/fadfafadda.htm
http://www.163.com/fadfafgdsags.htm
最大限制是3。然后把这三条存到数据库里,清除了容器里的内容。
进行第二层搜索,即对这个http://www.163.com/fadfa.htm搜索,那内存里就找不到数据了,要到数据库里去获取。那是要对数据库进行频繁的操作呢。
 
你内存中找数据干嘛呢?
无非是比较是否相同啊
先不要比较,等容器满的时候加入数据库的时候再比较

可能对最大限制你没有明白我的意思,比如是100
MAX_LIMIT = 100;
那么你的容器可以这样定义
sonarr:array[0..MAX_LIMIT - 1] of string;
你上面的程序其他地方都不需要改,在下面的函数做修改
procedure TfrmGetInform.GetAllUrl(surl:string);
const
MAX_LIMIT = 100;
var
str,sStr:string;
i:Integer;
pstr:string;
furl:string;
sonarr:array[0..MAX_LIMIT - 1] of string;//////////
begin
sStr:='';
pstr:= '';
furl:='';
//setlength(sonarr,100000);
if strCondition = '' then exit;
sStr:= GetWebPage(surl);
str:= IncludeStr(sStr);
sonarr[0]:= surl;
while str <>'' do
begin
if pos('&quot;',str)>0 then
str:= copystr(str,'&quot;',-1);
furl:= UrlConfig(surl,str);
if furl <> '' then
begin
for i:=0 to length(sonarr)-1 do
begin
if furl = sonarr then break;
if sonarr='' then
begin
sonarr:= furl;
////////////////////////////////////////////////////////
if i = MAX_LIMIT - 1 do
begin
//将内容写到数据库
FillChar(sonarr, SizeOf(sonarr), 0);
end;
///////////////////////////////////////////////////////
break;
end;
end;
end;
str:= IncludeStr(allStr);
end;
for i:= 1 to length(sonarr)-1 do
begin
if sonarr='' then exit;
CheckUrlIsExist(sonarr);
if not searchFlag then exit;
end;
end;
 
1.搜索过程和保存过程分开
2.如果有把握就使用递归算法
 
恩。。我试试看呢。
 
还有个问题,就是频繁对数据库操作,它的内存会无限制增加吗?
我测试时,看了 sqlserver.exe这个进程所使用的内存会增加的。最多时看到了它到达100多M。
 
降内存
这个函数可以试试
procedure ClearMemory;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
Application.ProcessMessages;
end;
end;
 
恩。谢谢。。
to muhx : 有时间吗? 加我QQ。明天替我看看一个问题呢。
行吗?
哪位高手有时间帮忙的话,在这留下QQ或者加我。谢谢喔。
 
后退
顶部