当前位置:编程学习 > C#/ASP.NET >>

【二百分结贴】判断网页js是否全部加载执行完毕

--------------------编程问答-------------------- window.onload=function(){

  加载完闭
} --------------------编程问答-------------------- window.onload=function(){

   调用截图程序//  加载完闭

} --------------------编程问答--------------------   
最近写了个软件叫WebBrowser,目的用于,网页的自动操作处理,就是说,所有你在网页上面的操作,都可以录到一个脚本中,然后可以回放这个操作过程。。我是说任何过程。
程序是用C#写的,其中遇到了一个难题,对于网页,我是用C#内置的WebBrowser控件控制,但是这个控件有个问题,就是不能准确判断网页什 么时候最终装载完毕,如果这个不能判断的话,我根本不可以判断什么时候执行下一个动作,因为网页还没有打开,不可能去点击还没有出现的按钮等。。。 google了海内外,竟然没有人搞定过,除非不用这个控件,虽然有别的控件可以,如AxWebBrowser,但是用另外的控件,又会出现另外的问题, 所以最后决定还是用内置的WebBrowser,但是怎么解决这个难题呢。。。
为什么这个控件不能准确判断网页什么时候装载完毕呢,那是因为现在的网页一般都有多个frame,一个frame相当于另一个网页,在不断装载,消息不断的触发,所以难以判断触发完成的是那个网页。。。
网上一般都是说根据 Browser_DocumentCompleted,Browser_Navigated,Browser_Navigating这三个消息来判断的, 用什么计数器啦,还有判断IsBusy,StatusText等。。以上或多或少对于一些网页是可行的,对于另一些网页却又有另外的意外,所以总的来说, 不能通用准确。。。
总得来说,一个网页最终装载完毕,不管它里面多少个frame,最终完成只有一次,也是可以提供给程序可以执行下一步操作的消息。
怎么解决呢,其实,WebBrowser的工作机制大概是这样的,在url上打上www.163.com,这时候,WebBrowser会开始装载www.163.com这 个网页,触发一个Browser_Navigating,ReadyState置为非Complete,IsBusy置为true,StatusText 置为"请求的url内容",这个文档完毕后,触发一个Browser_DocumentCompleted,同时,ReadyState置为 Complete,IsBusy置为false,StatusText置为"完成",如果通常都会有frame,如www.163.com/kk.jsp#fsd什 么的,WebBrower就会触发Browser_Navigating,ReadyState置为非Complete,IsBusy置为 true,StatusText置为"请求的url内容",再去装载那个frame,完毕后,触发一个 Browser_DocumentCompleted,同时,ReadyState置为Complete,IsBusy置为 false,StatusText置为"完成",剩下的frame,余次类推。
上面的过程有一个特点,从主文档到frame的过程,ReadyState置为Complete,IsBusy置为 false,StatusText置为"完成",这个时间是很短的,Browser_DocumentCompleted触发一下就过去了,如果还有 frame,很快就会把状态搞成非完成,所以根据这个特点。。。我们可以找一种方法来判断什么时候才是最终完成。。。
我的方法是:在WebBrowser开始装载www.163.com这个网 页的时候,触发Browser_Navigating的时候,我打开一个timer,在那里监控,Interval为200ms,如果 MainBrowser的ReadyState == WebBrowserReadyState.Complete && IsBusy == false的话,证明现在有两种情况,WebBrowser已经最终装载完毕,或者是刚装载完结一个,很快就会装载另外一个frame,不管,先记录这时 候的DocumentText,DocumentTitle,DocumentTitle,Url,等到下一个200ms,timer再判断现在的 WebBrowser的ReadyState == WebBrowserReadyState.Complete && IsBusy == false,如果不成立,则把记录的状态清掉,那些DocumentText,现在肯定还没有到最终完成状态啦,但是,如果成立的话,把现在的 WebBrowser的状态和上一次timer记录的状态对比,如果不相等,那也只能说明还没有到达最终状态,如果相同,设置一个记数器,加1,就这样, 如果这个计数器最终能够达到5次,就说明WebBrowser最终完成装载了。。。简单的说,就是加多一个timer来监控WebBrowser几个重要 状态值,如果在5*200ms一秒内,其状态没有变化过,就证明,其已经最终装载完毕。。。
这种方式,百试百灵,没有遇到过误判的情况,呵呵,强吧,MS没有完善的地方,咱们自己想办法呗。。。

上面的看错问题了眼花了玩一天CSDN了
用TIMER来监控 还是比较实在的。 --------------------编程问答-------------------- 方法和思路有很多,但经过测试往往行不通(也有很多是高手帮我测试的),或者是我用的不对。
谁能直接给出可用的代码啊~~~ --------------------编程问答-------------------- 楼主是 万恶的标题党  大骗子 --------------------编程问答-------------------- 楼主是 万恶的标题党 大骗子 
~~·231 --------------------编程问答-------------------- 这是技术论坛,发水帖请到灌水乐园板块。
引用 5 楼  的回复:
楼主是 万恶的标题党  大骗子
--------------------编程问答-------------------- 你可以试着注入一个JS来判断试下 --------------------编程问答-------------------- 试过很多次,问题是该怎样注入?上下文中不存在window
引用 8 楼  的回复:
你可以试着注入一个JS来判断试下
--------------------编程问答-------------------- “System.Windows.Forms.WebBrowser”并不包含“onload”的定义
window也一样 --------------------编程问答-------------------- 我以为问题很高深  结果标题党啊 --------------------编程问答-------------------- 是否高深我不知道,但是已经找过很多高手了!
什么叫标题党?你仔细看过帖子吗?
引用 11 楼  的回复:
我以为问题很高深  结果标题党啊
--------------------编程问答-------------------- 你可以看下我的这个博客 http://blog.csdn.net/yonglaixiazaide/article/details/7919417
这个地方有个问题,如果这个页面时你自己的,你就可以写,如果这个页面不是你的,你还是判断不了,
如果是你的,在页面加载完毕后,最好用Jquery吧,比如 在页面加载完毕后给一个一个值或者怎么样的,表示加载完毕,如果是ajax的,不知道Jquery那个能判断不,如果能的话,就好办,如果不能,同理在ajax请求完毕后,设置加载完毕吧

注入一个JS 掉去那个值来判断,

webBrower你可以理解为一个浏览器,加载完毕事件是指html和JS都已经下载下来了,所以可以注入JS,

这个逻辑你要能理解,否则的话 还是不行的。

还有一个方法,就是你分析那个页面,当什么情况下,页面算是加载完毕了。比如注入一个JS,调取一个div的innerHtml,我的思路大概是这样了

引用 9 楼  的回复:
试过很多次,问题是该怎样注入?上下文中不存在window

引用 8 楼 的回复:

你可以试着注入一个JS来判断试下
--------------------编程问答-------------------- 论坛总打不开,现在终于好了!已经私信你了,能告诉我具体该怎么做吗?
谢谢!
引用 13 楼  的回复:
你可以看下我的这个博客 http://blog.csdn.net/yonglaixiazaide/article/details/7919417
这个地方有个问题,如果这个页面时你自己的,你就可以写,如果这个页面不是你的,你还是判断不了,
如果是你的,在页面加载完毕后,最好用Jquery吧,比如 在页面加载完毕后给一个一个值或者怎么样的,表示加载完毕,如果是ajax的,不知道Jquery那个……
--------------------编程问答-------------------- 之前 我是有点看错了,我看了你那个例子 可以截图的啊,你找个 你截图和页面不一样的地址 给我看下,
http://cn.bing.com/# 这个和截图是一样的吧? 

引用 14 楼  的回复:
论坛总打不开,现在终于好了!已经私信你了,能告诉我具体该怎么做吗?
谢谢!

引用 13 楼 的回复:

你可以看下我的这个博客 http://blog.csdn.net/yonglaixiazaide/article/details/7919417
这个地方有个问题,如果这个页面时你自己的,你就可以写,如果这个页面不是你的,你还是判断不了,
如果是你的,在页面加载完毕后,最好用Jq……
--------------------编程问答-------------------- http://cn.bing.com可以截图,但是截到的图没有背景图片,搜索按钮的图片也没加载上。
引用 15 楼  的回复:
之前 我是有点看错了,我看了你那个例子 可以截图的啊,你找个 你截图和页面不一样的地址 给我看下,
http://cn.bing.com/# 这个和截图是一样的吧? 

引用 14 楼  的回复:
论坛总打不开,现在终于好了!已经私信你了,能告诉我具体该怎么做吗?
谢谢!

引用 13 楼 的回复:

你可以看下我的这个博客 http://blog.csdn.net/yongl……
--------------------编程问答-------------------- 是的,我刚才看了,为什么没有截到呢,我刚才帮你看了下,你按钮和背景图片都是在样式表中加载的,
样式表中的背景只有当在解析这个css的时候才会去加载,所以这个完成事件中不会去加载背景图片的,只有当要显示出来的时候才会加载图片,所以截图看不到背景
引用 16 楼  的回复:
http://cn.bing.com可以截图,但是截到的图没有背景图片,搜索按钮的图片也没加载上。

引用 15 楼 的回复:

之前 我是有点看错了,我看了你那个例子 可以截图的啊,你找个 你截图和页面不一样的地址 给我看下,
http://cn.bing.com/# 这个和截图是一样的吧?

引用 14 楼 的回复:
论坛总打不开,现在终于好了!已经私信你了,能告诉我具体该怎么……
--------------------编程问答-------------------- 对,现在这样不等css以及js执行完毕就开始抓图了,能不能判断js执行完毕?很多人都说用window.onload,但都只是停留在口头上,不知道该怎么用,更不知道起不起作用。
引用 17 楼  的回复:
是的,我刚才看了,为什么没有截到呢,我刚才帮你看了下,你按钮和背景图片都是在样式表中加载的,
样式表中的背景只有当在解析这个css的时候才会去加载,所以这个完成事件中不会去加载背景图片的,只有当要显示出来的时候才会加载图片,所以截图看不到背景引用 16 楼  的回复:
http://cn.bing.com可以截图,但是截到的图没有背景图片,搜索按钮的图片也没加载上。

引用 15 楼 的……
--------------------编程问答-------------------- 根本就不是这样的,我刚才调试了,你会发现WebBrowser_DocumentCompleted只执行了2次,
当你把它放在winfrom中的时候,你就会发现
WebBrowser_DocumentCompleted会执行4次,之后的2次是在显示控件的时候才会去触发,下载的是2个背景,4个事件,e.Url都是不同的,我刚才看了,好像没有办法主动触发后面2次的事件,后面2次的都是在窗体显示的时候触发的
引用 18 楼  的回复:
对,现在这样不等css以及js执行完毕就开始抓图了,能不能判断js执行完毕?很多人都说用window.onload,但都只是停留在口头上,不知道该怎么用,更不知道起不起作用。

引用 17 楼 的回复:

是的,我刚才看了,为什么没有截到呢,我刚才帮你看了下,你按钮和背景图片都是在样式表中加载的,
样式表中的背景只有当在解析这个css的时候才会去加载,所以这个完成事件中不会去加载背景图片……
--------------------编程问答-------------------- 我上面说的也是错误的。。。。看错了,,不过 你在winform中等看到了也页面,再用个button事件中去截图,可以截到背景

引用 18 楼  的回复:
对,现在这样不等css以及js执行完毕就开始抓图了,能不能判断js执行完毕?很多人都说用window.onload,但都只是停留在口头上,不知道该怎么用,更不知道起不起作用。

引用 17 楼 的回复:

是的,我刚才看了,为什么没有截到呢,我刚才帮你看了下,你按钮和背景图片都是在样式表中加载的,
样式表中的背景只有当在解析这个css的时候才会去加载,所以这个完成事件中不会去加载背景图片……
--------------------编程问答-------------------- 啊?这就是说,没有办法判断目标页面的js是否执行完毕吗?看来很难办啊~~
引用 19 楼  的回复:
根本就不是这样的,我刚才调试了,你会发现WebBrowser_DocumentCompleted只执行了2次,
当你把它放在winfrom中的时候,你就会发现
WebBrowser_DocumentCompleted会执行4次,之后的2次是在显示控件的时候才会去触发,下载的是2个背景,4个事件,e.Url都是不同的,我刚才看了,好像没有办法主动触发后面2次的事件,后面2次的都是在窗体显示的时……
--------------------编程问答-------------------- 刚看到这条!是不是还有办法啊?具体该怎么做呢?
拜托了!
引用 20 楼  的回复:
我上面说的也是错误的。。。。看错了,,不过 你在winform中等看到了也页面,再用个button事件中去截图,可以截到背景

引用 18 楼  的回复:
对,现在这样不等css以及js执行完毕就开始抓图了,能不能判断js执行完毕?很多人都说用window.onload,但都只是停留在口头上,不知道该怎么用,更不知道起不起作用。

引用 17 楼 的回复:

是的,我刚才看了,为什……
--------------------编程问答-------------------- 你这个例子不是js有没有加载完毕的问题啊

引用 22 楼  的回复:
刚看到这条!是不是还有办法啊?具体该怎么做呢?
拜托了!

引用 20 楼 的回复:

我上面说的也是错误的。。。。看错了,,不过 你在winform中等看到了也页面,再用个button事件中去截图,可以截到背景

引用 18 楼 的回复:
对,现在这样不等css以及js执行完毕就开始抓图了,能不能判断js执行完毕?很多人都说用window.onload,但都只是停留在口头上,不知……
--------------------编程问答-------------------- 好吧,下午我再找一个js加载的页面。谢谢了!
引用 23 楼  的回复:
你这个例子不是js有没有加载完毕的问题啊

引用 22 楼  的回复:
刚看到这条!是不是还有办法啊?具体该怎么做呢?
拜托了!

引用 20 楼 的回复:

我上面说的也是错误的。。。。看错了,,不过 你在winform中等看到了也页面,再用个button事件中去截图,可以截到背景

引用 18 楼 的回复:
对,现在这样不等css以及js执行完毕就开始抓图了,能不能判断……
--------------------编程问答-------------------- 以前保存的js的例子页面删除了。

现在这个例子是css有没有加载完毕,请问可以解决吗? --------------------编程问答-------------------- 不知道啊,,我感觉 并不是CSS没有加载完毕,否则那些样式 怎么没问题,只是背景图片没有加载出来
引用 25 楼  的回复:
以前保存的js的例子页面删除了。

现在这个例子是css有没有加载完毕,请问可以解决吗?
--------------------编程问答-------------------- 我刚才又看了下cn.bing.com 的页面,发现并没有加载外部的css 所欲的css样式 都是在页面上的写,至于有的背景可以,有的背景不可以。。。我就不知道了

引用 25 楼  的回复:
以前保存的js的例子页面删除了。

现在这个例子是css有没有加载完毕,请问可以解决吗?
--------------------编程问答-------------------- 我刚才又看了下cn.bing.com 的页面,发现并没有加载外部的css 所欲的css样式 都是在页面上的写,至于有的背景可以,有的背景不可以。。。我就不知道了

引用 25 楼  的回复:
以前保存的js的例子页面删除了。

现在这个例子是css有没有加载完毕,请问可以解决吗?
--------------------编程问答-------------------- 谁写过类似程序? --------------------编程问答-------------------- 说了给200分结贴,结果给的是20分。你用这种下三滥的骗子手段,把大家骗进来帮你解决问题,是吧。 --------------------编程问答-------------------- 谁给你20分了?
每天回帖只给你10分,但也不是我给你的!CSDN应该清理这些不看帖乱回帖的人!
引用 30 楼  的回复:
说了给200分结贴,结果给的是20分。你用这种下三滥的骗子手段,把大家骗进来帮你解决问题,是吧。
--------------------编程问答--------------------
 private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
if (m_WebBrowser.IsBusy == false && m_WebBrowser.ReadyState == WebBrowserReadyState.Complete) //判断是否完全加载完成
{
        WebBrowser m_WebBrowser = (WebBrowser)sender;
        m_WebBrowser.ClientSize = new Size(this.m_BrowserWidth, this.m_BrowserHeight);
        m_WebBrowser.ScrollBarsEnabled = false;
        m_Bitmap = new Bitmap(m_WebBrowser.Bounds.Width, m_WebBrowser.Bounds.Height);
        m_WebBrowser.BringToFront();
        m_WebBrowser.DrawToBitmap(m_Bitmap, m_WebBrowser.Bounds);
        m_Bitmap = (Bitmap)m_Bitmap.GetThumbnailImage(m_ThumbnailWidth, m_ThumbnailHeight, null, IntPtr.Zero);
}
    }
}

--------------------编程问答-------------------- 谢谢!
运行出错:上下文中不存在m_WebBrowser
把条件语句放在这句后面可以运行,但没有效果:WebBrowser m_WebBrowser = (WebBrowser)sender;
关键是除了判断js文档加载完毕与否,还要判断js是不是执行完毕。
引用 32 楼  的回复:
 private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
if (m_WebBrowser.IsBusy == false && m_WebBrowser.ReadyState == WebBrowserReadyState.Co……
--------------------编程问答--------------------  “m_WebBrowser” 是WebBrowser_DocumentCompleted这个事件的控件ID。你按你实际的改成正确的。
还有一种方法,思路是:
向webbrower中注入一段客户端脚本:
   window.body.onload=function(){
     window.external.ClientResponse(3, '', 0); }; //ClientResponse为winform中定义的方法
}
//大意是向webbrowser中的网页注入一个页面的onload事件,等页面完一加载完后,调用winform中的一个方法来响应(并实现你的截图功能)

具体如何调用,你到网上搜索winform中js通过external对象如何与webbrowser交互?的相关资料 --------------------编程问答-------------------- ID没错,只是没有定义。以前也有高手帮我在这里加过两重条件语句,他调试过了还是不行。是不是要在定义之前加这个判断?但这样总是报错!
引用 34 楼  的回复:
 “m_WebBrowser” 是WebBrowser_DocumentCompleted这个事件的控件ID。你按你实际的改成正确的。
还有一种方法,思路是:
向webbrower中注入一段客户端脚本:
   window.body.onload=function(){
     window.external.ClientResponse(3, '', 0); }; //ClientR……
--------------------编程问答-------------------- 不知道你那实际代码和情况。
1.
WebBrowser_DocumentCompleted事件里先switch case语法 判断那是不是那个页面(js脚本所在的aspx页在),再2重判断其实可以了,具体要实际调试才好写代码
2.向webbrower中注入一段客户端脚本绝对OK了,就看你会不会注入了。
window.onload=function(){
 window.external.ClientResponse(3, '', 0); }; //ClientR……
}
3.实在不会,你就弄一个定时器,每隔多长时间就判断页面上某一个元素是否存在,存在,就终止计时器,不存在就就让计时器一直运行并判断,直到元素存在为止再执行你的代码。 --------------------编程问答-------------------- 这么多天了,大侠还不上线啊~~
引用 36 楼  的回复:
不知道你那实际代码和情况。
1.
WebBrowser_DocumentCompleted事件里先switch case语法 判断那是不是那个页面(js脚本所在的aspx页在),再2重判断其实可以了,具体要实际调试才好写代码
2.向webbrower中注入一段客户端脚本绝对OK了,就看你会不会注入了。
window.onload=function(){
 window.external.……
--------------------编程问答-------------------- 不等css以及js执行完毕就开始抓图了?
这些东西不加载完毕,有时候页面不显示内容啊,或者内容显示不正确,尤其是大图片。一般情况下,css和js都在页面的前面的,页面加载完,这些一般都应该是加载完毕的,比较麻烦的是ajax产生的页面 --------------------编程问答--------------------
引用 38 楼  的回复:
不等css以及js执行完毕就开始抓图了?
这些东西不加载完毕,有时候页面不显示内容啊,或者内容显示不正确,尤其是大图片。一般情况下,css和js都在页面的前面的,页面加载完,这些一般都应该是加载完毕的,比较麻烦的是ajax产生的页面

已经放弃考虑ajax产生的页面了,现在的问题是不等css以及js执行完毕就开始抓图了,这是我抓的必应,没有背景图: --------------------编程问答-------------------- http://topic.csdn.net/u/20120916/04/84e69921-ce15-48c9-86c4-d3f862aba3b3.html?35139 --------------------编程问答-------------------- 如果你想做的完美,你可以先遍历页面DOM对象

HtmlElementCollection img = WebBrowser1.Document.GetElementsByTagName("img")
判断每一个图片是否加载完毕


HtmlElementCollection script= WebBrowser1.Document.GetElementsByTagName("script")
判断是否加载完毕

还有背景图片,

这些都是很复杂的问题,

所谓的定时器,就是等待一定的时间再去执行你的截图代码 --------------------编程问答-------------------- 谢谢孟老师!
我把WebBrowser1改成自己代码里的m_WebBrowser,反复试了好几个地方也没成功。
我不是程序员,但是这个问题已经在论坛里找很多人调试过(有的还打包文件过去),可以麻烦您帮我把判断写到一楼的代码里吗?
退一步说,如果很复杂不好实现,能否帮我加个定时器(就是我说的延迟吧?)只要稍微等待几百毫秒,大部分问题也能解决。(之前找几个人弄过延迟截图,但是好像他们的代码也不对,尽管加了多重条件判断,程序运行延迟了,但是截图效果没有改观。)
几个月也没解决,只有拜托孟老师了!
引用 41 楼  的回复:
如果你想做的完美,你可以先遍历页面DOM对象

HtmlElementCollection img = WebBrowser1.Document.GetElementsByTagName("img")
判断每一个图片是否加载完毕


HtmlElementCollection script= WebBrowser1.Document.GetElementsByTagName("scr……
--------------------编程问答-------------------- 延迟执行,你可以
System.Threading.Thred.Sleep(10000) --------------------编程问答-------------------- 孟老师好:
主要是这句该加在什么位置啊?我试过很多地方,也找高手帮我延迟过,但都不成功。
引用 43 楼  的回复:
延迟执行,你可以
System.Threading.Thred.Sleep(10000)
--------------------编程问答-------------------- --------------------编程问答-------------------- <body onload="调用js">

抓bing的图片,好像不是现成的.jpg等格式的图片哦,都是流图片? --------------------编程问答-------------------- 测试了下System.Threading.Thred.Sleep(10000)不行 --------------------编程问答-------------------- --------------------编程问答-------------------- System.Threading.Thred.Sleep(10000);未定义
不怕老师笑话,笨办法:以前用System.Threading.Thread.Sleep(3000);在所有位置试过(也找过高手),不起作用;刚才又用System.Threading.Thread.Sleep(10000);在所有位置试了一遍,依旧没有截到必应的背景图。
请问孟老师,这个代码具体该怎么用?
引用 45 楼  的回复:
System.Threading.Thred.Sleep(10000)
//截图代码
--------------------编程问答-------------------- 哦,一直在用笨办法测试,没有刷新帖子,原来老师也测试过了~~
以前我在一个直接打开页面抓图的文章里看到过这句代码,在那种环境下是管用的,不知为什么在这里不管用。
孟老师,还有好一点的办法吗?
引用 47 楼  的回复:
测试了下System.Threading.Thred.Sleep(10000)不行
补充:.NET技术 ,  ASP.NET
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,