delphi 编写一个采集网页的问题(100分)

  • 主题发起人 主题发起人 meme258
  • 开始时间 开始时间
M

meme258

Unregistered / Unconfirmed
GUEST, unregistred user!
delphi 编写一个采集网页的问题,
采集百度Index.baidu.com
在获取 index.baidu.com 的网页源代码的时候,遇到问题,找不到答案求教高手。

分别尝试了,用 indy 9, wininet,MSXML2 获得这个页面的代码,都遇到了问题,

代码 以及遇到的问题,下面详细描述,首先谢谢大家浏览这个帖子

1,wininet 获取 index.baidu.com 的源码 下面是代码,
一个 长循环中,比如要使用这个函数1000次获取1000个源码
http://index.baidu.com/main/word.php?word=delphi
执行2,3次以后每一次使用GetWebPage 获取都非常慢,需要很长时间1,2分钟这个函数才能执行完毕,返回值。
function GetWebPage(const url: string): string;
var
hInet: HINTERNET;
hFile: HINTERNET;
buffer: array[1..1024] of char;
bytesRead: DWORD;
begin
hInet := InternetOpen(PChar('Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.0)'),
INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);

hFile := InternetOpenURL(hInet,PChar(url),nil,0,0,0);
if Assigned(hFile) then
begin
repeat
InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead);
result := result + Copy(buffer,1,bytesRead);
until bytesRead = 0;
InternetCloseHandle(hFile);
end;
InternetCloseHandle(hInet);

end;





2,MSXML2, 用MSXML2.XMLHTTP获取的时候,速度倒是非常快,原因之一就是
第一次获取之后,以后每次获取不同的网址,得到的结果都是一样,
我考虑,是不是xmlHttp 创建以后 需要释放 vb里面的 set xmlhttp = nothing,
这里不知道该如何写,也不知道是不是这个原因。
function GetWebPage(const url: string): string;
var
xmlHttp:Olevariant;
responseText:Widestring;
a:Integer;
ay: array of byte;
begin
xmlHttp:=CreateOleObject('MSXML2.XMLHTTP');
xmlHttp.open('get',url,false);
xmlHttp.send;
ay := xmlHttp.responseBody;
//xmlHttp:='';

for a:=Low(ay) to High(ay) do //将字节转换成字符
Result:=Result+chr(ay[a]);
//ay:=nil;
end;



3,indy 9 在线程里面创建 使用idhttp,速度也非常快,但是过不了几次以后,就会出现 Connection Closed Gracefully 这个错误而获取不到源码了,搜索之后找到一个原因说 baidu 屏蔽了 userAgent indy 这个标志,于是加上下面的 UserAgent 还是出现同样的问题,最终还是没有解决。
function dThread.GetWebPage(const url: string): string;
begin

// idhp.Request.UserAgent := 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)';
Result := idhp.Get(url);
end;



期待高人。。。。
 
获取源码好像MSHTML.pas里面很多函数可以吧,配合WEBBROWSER足够了。。。
 
在线程里面 用WEBBROWSER 不好用把,
我试过 因为WEBBROWSER 必须要等到 downloadcomplete 事件 才能得到全部源码,
线程里面响应这个事件以后在得到源码,好像比较麻烦把

看看 mshtml.pas 去,谢谢
 
学习一下
 
看了下 mshtml.pas 里面,都是些 创建接口的函数把,好像
 
用你的第一个程序,执行了10次,正常返回啊。

我用的是D7,不会是说这问题吧?
for I := 0 to 9 do
memo1.lines.add(getwebpage('....URL'));
 
errorcode
执行 10次
url=http://index.baidu.com/main/word.php?word=delphi(这个地方 要换 10个不同的词)
http://index.baidu.com/main/word.php?word=delphi
http://index.baidu.com/main/word.php?word=c
http://index.baidu.com/main/word.php?word=java
http://index.baidu.com/main/word.php?word=vc
http://index.baidu.com/main/word.php?word=vb



memo1.lines.add(getwebpage('....URL'));

而不是同一个 url
 
1:那问题,我这边测试是InternetReadFile进入阻塞状态了,原因不知,可能是由于收到最后一个字节,但又进入读状态,没有数据返回,引起的,或者,Buffer太大,还没填充完Buffer,一直等待数据。
一般处理是给Inetnet加入ReadTimeout设置,这样不会有这个问题,不过这样就需要自己去检查Result的内容是否返回完成。
var
Timeout: Cardinal;

hInet := InternetOpen(nil, INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
Timeout := 1000; // 1s =>1000ms
WinInet.InternetSetOption(hInet, INTERNET_OPTION_RECEIVE_TIMEOUT, @Timeout, SizeOf(Timeout));

2: 没用过那玩意。

3:indy没用过。不过经常能看到那问题,好像是由于断开连接,但indy未检测到,所以indy组件的Connected属性未改,再加上调用一些send/read操作引起的,一般解决是在操作前,直接先close原来的connection(在indy不知怎么弄,自个研究下)
 
哦,忘了一个问题,我以前用过Inetnet这几个函数,好像同一URL,多次调用,它会将IE缓存的东西取出来返回的,很TNND不爽,以前就遇过,所以一直用SOCKET来搞。

所以最好你用INDY来搞,最简单的出现那异常,try一下,出现就重新GET,就完了。
 
谢谢 errorcode 兄

用indy 就出现Connection Closed Gracefully 这个,有人说是因为 baidu 屏蔽了 indy ,所有出现这个 。try 没用,我试过,
打算全面看一下Indy 的说明看看,谢谢

wininet 的问题,你发现了么
 
可用WEBCOPY控件试试
 
后退
顶部