浏览器自动化的一些体会2 webBrowser控件之ajax
上个帖子简要讨论了浏览器自动化的几种方法。现在讨论webBrowser控件使用中的一些问题。基本的操作就不详细说了,随便网上找个帖子或找本书都有介绍的。这里只写点网上似乎少有人总结过的内容,以及自己的一些实践体会。
1.ajax
首先,DocumentCompleted事件对于ajax无能为力,因为这个事件不能处理网页加载完成后执行javascript发出ajax请求。网上可以找到的方法,主要有两种,一种是利用onpropertychange事件,随便找了个参考链接:https://social.msdn.microsoft.com/Forums/ie/en-US/5fe3e7a1-b3c7-4083-9a00-7a72bf833a9c/ajax-detection-in-webbrowser-control?forum=ieextensiondevelopment , 另外一种就是用timer。
实践中的体会是onpropertychange也不好用,timer比较好使。timer在这里的本质就是延时。我一般有两种做法,一种是在DocumentCompleted事件处理代码里启动timer
即:
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
timer1.Stop();
timer1.Start();
}
这里先Stop再Start不过是个人的一个习惯,很多情况下没必要。但是如果一个timer已经启动了,则需要先Stop再Start。
另一种是在启动webbrowser.Navigate的代码里启动timer:
private void button1_Click(object sender, EventArgs e)
{
webBrowser1.Navigate(“foo.com");
timer1.Stop();
timer1.Start();
}
个人更喜欢第2种方式,理由是DocumentCompleted里面尽量不用很多代码,主要原因是有些情况下DocumentCompleted事件会被多次触发,所以如果没有正确处理好这种情况,有些代码就会被重复执行,造成意想不到的结果。但是,后一种做法也有缺点,因为不是在DocumentCompleted事件触发后再启动timer,如果网页加载较慢,timer可能会不必要地启动多次。所以还是要看情况处理。
timer1_Tick里的代码大致如此:
private int _waitCount = ; private void timer1_Tick(object sender, EventArgs e)
{
//先stop一般没有什么坏处,而且有些情况下是必要的,比如这里的操作所需时间超过了
//timer1的间隔(Interval),如果没有stop可能出现意想不到的结果。
timer1.Stop();
if (webBrowser1.Document == null
|| webBrowser1.Document.Body == null
|| webBrowser1.Document.GetElementById("foo") == null)
{
if (_waitCount > )
{
MessageBox.Show("网络有问题,请换个时间再试");
return;
}
_waitCount++;
timer1.Start();
return;//继续等
} _waitCount = ;//复原
//“foo”元素检测到,说明ajax请求已返回想要的结果,可以继续下一步处理
..............
}
这里用了一个_waitCount的全局变量,目的是为了避免网络有问题,永远加载不完,导致timer代码被反复触发,进入死循环。尝试4次,如果还不行,就提示失败。这里其实牵涉到浏览器自动化的一个重要问题:出错处理。因为网络情况无法预料,所以只有包含良好出错处理的程序,才比较健壮(robust)。网上很多程序,表面看起来work,但遇到出乎意外的网络状况时都会出错,就是因为出错处理做得不好的缘故。这个具体以后再讨论。
前面的if判断条件,如果用新版framework的?语法糖,或许还可写得简单些,这里就不改了。
实践中感到timer的方式主要问题是如果网页里的ajax过多,就需要很多timer,代码显得有点乱。既然timer在这里的作用是延时,那么应该也可用其他方式。
最简单的延时方式,就是Thread.Sleep()。缺点很明显,就是阻塞了主线程,造成假死机现象,用户体验不好。于是有人改良,可参考这个链接:
https://stackoverflow.com/questions/3794522/waiting-for-webbrowser-ajax-content
它用了Application.DoEvents()来避免阻塞。但是,Application.DoEvents()使用要小心,参考这个链接:
https://stackoverflow.com/questions/5181777/use-of-application-doevents
我的理解是,如果允许Application.DoEvents()的时间过长,就容易给用户有机会关掉应用等操作,有可能造成意想不到的结果。而在处理ajax请求时,有可能要等上几秒,几秒是显得有些长了。因此Application.DoEvents()也许在这里用,并不是太好的做法。
另外一种延时方式,虽然并不局限于浏览器自动化里的应用,但既然谈到了,不妨也说一下。这大概是游戏程序里用的较多的,就是类似下面的代码:
var start = Environment.TickCount;
while (Environment.TickCount - start < ) //延时100毫秒
{
Application.DoEvents();
}
写博客很费时间。webBrower控件还有许多要谈的问题,以后再写。
浏览器自动化的一些体会2 webBrowser控件之ajax的更多相关文章
- 浏览器自动化的一些体会9 webBrowser控件之零碎问题3
WebBrowser控件最大的优点是可以轻松嵌入win form程序中,但是微软好像对这个控件没什么兴趣,这么多年了还没有改进,结果造成一堆问题. 1. 不支持https 2. 缺省模拟ie 7,如果 ...
- 浏览器自动化的一些体会3 webBrowser控件之零碎问题
1. 一般需要执行这一句:webBrowser1.ScriptErrorsSuppressed = true; 主要目的是禁止跳出javascript错误的对话框,否则会导致程序无法正确地跑下去.缺点 ...
- 浏览器自动化的一些体会5 webBrowser控件之winform和webBrowser的交互
从winform访问webBrowser,大致就是利用webBrowser提供的解析dom的方法以及用InvokeScript方法执行javascript.这个相对比较简单. 从webBrowser访 ...
- 浏览器自动化的一些体会4 webBrowser控件之零碎问题2
1. DocumentCompleted的多次执行问题 有的网页,会多次触发DocumentCompleted事件,由于它是异步的,不会阻塞,所以如果不恰当处理,会造成某些代码被错误地多次执行,造成意 ...
- Webbrowser控件史上最强技巧全集
原文:Webbrowser控件史上最强技巧全集 Webbrowser控件史上最强技巧全集 VB调用webbrowser技巧集 1.获得浏览器信息: Private Sub Command1_Click ...
- WebBrowser控件使用详解
原文:WebBrowser控件使用详解 方法 说明 GoBack 相当于IE的“后退”按钮,使你在当前历史列表中后退一项 GoForward 相当于IE的“前进”按钮,使你在当前历史列表中前进一项 G ...
- 浏览器自动化的一些体会6 增强的webBrowser控件
这里谈两点 1.支持代理服务器切换 一种方法是修改注册表,不是太好的做法,而且,只能改全局设置,不能改局部(比如只让当前的webBrowser控件使用代理,而其他应用不用代理) 另外一个较好的方法,示 ...
- 浏览器自动化的一些体会9 访问angular页面的一个问题
发现浏览器自动化有一个重要方面没有提及,即所谓的无页面浏览器,不过最近没有需求,不想尝试,先记上一笔,以后有需求时,可以有个思路. 大约一两个月前(现在比较懒散,时间不知不觉过去,连今天是几号有时候都 ...
- PB打开ole控件IE浏览器版本问题_指定Webbrowser控件所用IE内核版本(转)
如果电脑上安装了IE8或者之后版本的IE浏览器,Webbrowser控件会使用IE7兼容模式来显示网页内容.解决方法是在注册表中为你的进程指定引用IE的版本号. 比如我的程序叫做a.exe 对于32位 ...
随机推荐
- 如何在Python对Excel进行读取
在python自动化中,经常会遇到对数据文件的操作,比如添加多名员工,但是直接将员工数据写在python文件中,不但工作量大,要是以后再次遇到类似批量数据操作还会写在python文件中吗? 应对这一问 ...
- CentOS7 安装nginx部署vue项目
简单描述:代码开发完了,需要环境来运行测试.服务器上没有nginx,搞起搞起. 在Centos下,yum源不提供nginx的安装,可以通过切换yum源的方法获取安装.也可以通过直接下载安装包的方法 ...
- Redis的各种数据类型到底能玩出什么花儿?
https://mp.weixin.qq.com/s/ZSQ9vCkWXYuLrKS0UJ4RIg 两个星期终于肝了出来,Redis相关问题脑图,终于整理完了!!! 文末无套路分享~~附获取方式 Re ...
- 使用matlab进行傅里叶分析和滤波
傅里叶分析 公式法 下例 是将振幅为1的5Hz正弦波和振幅为0.5的10Hz正弦波相加之后进行傅里叶分析. clear all N=512; dt=0.02; n=0:N-1; t=n*dt; x=s ...
- php提取xml配置参数
demo1.php <?php class AddressManager{ private $addresses = array("ip地址1","ip地址2&qu ...
- Day01_SpringBoot
学于黑马和传智播客联合做的教学项目 感谢 黑马官网 传智播客官网 微信搜索"艺术行者",关注并回复关键词"乐优商城"获取视频和教程资料! b站在线视频 0.学习 ...
- ARC 093 F Dark Horse 容斥 状压dp 组合计数
LINK:Dark Horse 首先考虑1所在位置. 假设1所在位置在1号点 对于此时剩下的其他点的方案来说. 把1移到另外一个点 对于刚才的所有方案来说 相对位置不变是另外的方案. 可以得到 1在任 ...
- python 操作元组 列表===python中三大宝刀(字典已经再上一遍 说过)
字典俗称,世界有多大就能装多大 列表俗称,你们决定 元组俗称,可远观而不可亵玩焉 列表的相关操作a=['1','2','3','5','6','7']# print(a[0])# print(a[0: ...
- 实验01——java模拟银行ATM系统
用java写的一个模拟银行系统,比较初级. ATM.java package cn.tedu.yinhang; import java.util.Scanner; /** * @author 赵瑞鑫 ...
- Python玩转各种多媒体,视频、音频到图片
我们经常会遇到一些对于多媒体文件修改的操作,像是对视频文件的操作:视频剪辑.字幕编辑.分离音频.视频音频混流等.又比如对音频文件的操作:音频剪辑,音频格式转换.再比如我们最常用的图片文件,格式转换.各 ...