2011-05-08 68 views
3

编辑 范围缩小到这个1号线,申请锁在尝试访问TWebbrowsers HTML

HTML := wb.OleObject.Document.documentElement.innerHTML; 

消耗的时间......这怎么可能加速?

使用下面的代码我的应用程序可能会挂起1-2秒,而它试图访问页面的HTML(Delphi XE)。

function Button1Click(Sender : TObject); 
begin 
    wb.navigate('http://10.0.0.154/stats'); 
    // Use a timer to poll the page - dont wait and process app messages 
    timer1.enabled := true; 
end; 

procedure Timer1Timer(Sender : TObject); 
var 
    HTML : WideString; 
begin 
    If GetHTML(HTML) = true then 
    begin 
     Timer1.enabled := false; 
     { do something } 
    end; 
end; 


function GetHTML(var HTML : WideString) : boolean; 
var 
    Document : IHTMLDocument2; 
begin 
    HTML := ''; 
    Result := false; 

    Document := wb.DOcument as IHTMLDocument2; 
    If Assigned(Document) then 
    begin 
    try 
     HTML := wb.OleObject.Document.documentElement.innerHTML; 
     Result := true; 
    except 
     Result := false; 
    end; 
    end; 
end; 

但是我在GetHTML方法注意可能需要1-2秒返回的东西,它锁定的用户界面。用Delphi XE来看AQTime,它说方法调用很慢(1-2秒)。这是spotered,我不知道当页面仍然是中等负载时它是否失败。

我正在加载的页面是一个内部页面,完整的JavaScript和500k大,我不能使用OnDocumentComplete,因为它在页面甚至准备好之前触发,即使我在ReadyState上检查它仍然会触发提前。

任何人都可以摆脱一些光,如果他们更快的方式,我可以访问TWebbrowser的HTML?

+0

wb.Navigate立即返回,所以它不是应用程序挂的原因。 TWebBrowser必须下载页面,然后渲染它才能显示,这就是获取HTML的延迟。如果你想要的只是原始HTML,为什么不使用Indy,ICS或TDownLoadURL(标准动作)? – crefird 2011-05-09 15:11:36

+0

我一旦JavaScript完成处理后的HTML,JavaScript也是为什么我需要使用TWebbrowser,因为Indy,ICS等不会运行JavaScript。 – Wizzard 2011-05-09 22:18:51

+0

您是否尝试使用'outerHtml'而不是'innerHtml'?也许它有所作为。此外,如果您正在托管TWebBrowser控件,可能有助于使用FEATURE_BROWSER_EMULATION来强制TWebBrowser使用最新版本进行显示(截至撰写本文时为止;托管控件的默认模式为7)。虽然我没有测试,但也许在这方面有速度优势。 – 2011-07-22 08:06:57

回答

2

您的问题似乎是,在您尝试获取HTML之前,您并未允许TWebBrowser完成页面的加载。这只是一个猜测,因为你没有展示你调用wb.Navigate的代码是怎么样的,而你不得不处理获取InnerHTML的异常。

你应该尝试以下操作:

procedure TForm1.GetHTML(URL: string; var HTML: string); 
begin 
    wb.Navigate(URL); 
    Application.ProcessMessages; 
    while wb.Busy do 
    Application.ProcessMessages; 
    HTML := wb.OleObject.Document.documentElement.innerHTML; 
end; 
+0

谢谢,我更新了我的例子。我发现使用.Busy和.ReadyState,即使页面可能没有准备好,它也会返回true/complete。 – Wizzard 2011-05-09 02:00:38

+0

@Wizzard - .Busy将返回True,直到TWebBrowser完成加载页面,然后.Busy更改为False。由于JavaScript,TWebBrowser可能会继续执行某些操作,但HTML将被加载。 – crefird 2011-05-09 14:53:13

+0

使用wb.Busy阅读繁忙状态有时会阻止整个应用程序一段时间。似乎wb.Busy不是一个简单的标志。 – 2013-08-12 04:52:33

0

与@ crefird的答案,我怀疑你正试图访问innerHTML的浏览器已完成其工作之前...

如果READSTATE /忙没有返回TWebBrowser繁忙状态的准确表示,你可以这样做:

1)创建一个全局变量,或者你的窗体的一个私有成员......比如“FBrowserBusy:Boolean”(不要忘记在初始化之前初始化它以实现CAL LING“。导航”) 2)正如@crefird在他的回答中所展示的那样,使用“while”循环,只将“wb.Busy”替换为“FBrowserBusy”。 3)将一个OnDocumentComplete事件添加到TWebBrowser实例中,并将此set FBusy:= False;

这将消除任何冲突,并确保TWebBrowser对象在外部例程继续进行询问之前完成加载文档。

希望你觉得这有帮助!

4

请注意,在浏览页面时,OnDocumentComplete可以触发多次(框架)。

如何正确地实现OnDocumentComplete:

procedure YourForm.OnDocumentComplete(
    Sender: TObject; 
    const pDisp: IDispatch; 
    var URL: OleVariant); 
var 
    currentBrowser: IWebBrowser; 
    topBrowser: IWebBrowser; 
    document: OleVariant; 
    windowName: string; 
begin 
    currentBrowser := pDisp as IWebBrowser; 
    topBrowser := (Sender as TWebBrowser).DefaultInterface; 
    if currentBrowser = topBrowser then 
    ShowMessage('Complete document was loaded') 
    else 
    begin 
    document := currentBrowser.Document; 
    windowName := document.ParentWindow.Name; 
    ShowMessage(Format('Frame "%s" was loaded', [windowName])); 
    end; 
end; 

来源:

http://www.cryer.co.uk/brian/delphi/twebbrowser/twebbrowser_events.htm#OnDocumentComplete