浏览器自动化的一些体会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位 ...
随机推荐
- three.js 数学方法之Plane
今天郭先生就来继续说一说three.js数学方法中的plane(平面).在三维空间中无限延伸的二维平面,平面方程用单位长度的法向量和常数表示.构造器为Plane( normal : Vector3, ...
- Oracle常见错误以及解决方法
前言: 本博客为博主在开发中遇到的问题,为大家提供解决方法,如需转载,请注明来源,谢谢! 问题一: 第一次用PLSQL Developer连接数据库,若用sys用户登录并操作则正常,若用普通用户比如x ...
- JavaSE基础知识之修饰符和使用场景,你真的了解嘛
修饰符的作用是啥? 用来定义类.方法或者变量的访问权限 两大类 访问修饰符 限定类.属性或方法是否可以被程序里的其他部分访问和调用的修饰符 private<default<protecte ...
- rpm -ivh vsftpd-3.0.2-22.el7.x86_64.rpm出现error: open of vsftpd-3.0.2-22.el7.x86_64.rpm failed: No such file or directory的解决方法
情况一: 出现如图问题, 我当时的问题是通过安装rpmbuild工具软件解决的 以前制作rpm时,没有遇到过这个问题,几经搜索也没有解决.后来发现当前的centos没有安装 rpmbuild 工具软件 ...
- 《Python游戏编程快速上手》|百度网盘免费下载|Python基础编程
<Python游戏编程快速上手>|百度网盘免费下载| 提取码:luy6 Python是一种高级程序设计语言,因其简洁.易读及可扩展性日渐成为程序设计领域备受推崇的语言. 本书通过编写一个个 ...
- MacOS下ElasticSearch学习(第二天)
ElasticSearch第二天 学于黑马和传智播客联合做的教学项目 感谢 黑马官网 传智播客官网 微信搜索"艺术行者",关注并回复关键词"elasticsearch&q ...
- Python 数字类型转换
Python数字类型转换: int(x):将 x 转换为一个整数 float(x):将 x 转换为一个浮点数 complex(x,y):将 x 和 y 转换为一个复数.x 为复数的实部,y 为复数的虚 ...
- Python os.lchmod() 方法
概述 os.lchmod() 方法用于修改连接文件权限.高佣联盟 www.cgewang.com 只支持在 Unix 下使用. 语法 lchmod()方法语法格式如下: os.lchmod(path, ...
- PHP children() 函数
实例 查找 note 节点的子节点: <?php$note=<<<XML<note><to>Tove</to>高佣联盟 www.cgewan ...
- 4.23 子集 分数规划 二分 贪心 set 单峰函数 三分
思维题. 显然考虑爆搜.然后考虑n^2能做不能. 容易想到枚举中间的数字mid 然后往mid两边加数字 使其整个集合权值最大. 这里有一个比较显然的贪心就不再赘述了. 可以发现这样做对于集合是奇数的时 ...