本帖最后由 源理 于 2018-12-27 22:30 编辑
9处理等待 关于等待是一个难点,我也不知道如何下手写。想了很久,但我发现想得太多,不如先记下来我所了解的,以后再补充。 等待是不可避免的,因为网页中的js代码会从后台无刷新带来数据,然后再根据数据添加一些元素在网页上或是删除一些网页元素,这个就是Ajax,这个东西应用太多了。现在我们的遇到的网页基本上都是这种交互。 那么问题来了,一个网页程序在对一个元素进行创建或是删除,我们VBA主线程怎么知道浏览器怎么处理好这个元素。这个网页元素消失了完了吗?这个网页元素创建完了,我们能用了吗?(如果没有创建完,我们不能用就会报错,这个太讨厌了,大大降低了我们的信心)。 为了解决以上问题所以这个我研究了很久,也很肤浅,写出我查资料得出的几个方法。 - 用Wait方法
- 用webelement中wait的方法
Wait 说明:主程序等待指定的时间(毫秒)。这个我喜欢用,因为不用考虑太多,直接有效。但很明显,每次网络异步加载的数据时间是不一样的,我这样会取一个最大的值,这样会浪费很多时间。当然有时我们不在意这些时间,我们可以等待。 语法 instance.Wait(timems) instance:驱动,如chormDriv timems:毫秒、等待的时间 下面为不用Waiter的报错
01
加了wait后的代码效果
02
代码中加了一个等待1s Webelement的等待方法
WaitAttribute :等待元素的指定属性变为指定值 WaitNotAttribute:等待元素的指定的属性不等于指定的值
returnValue = instance.WaitAttribute(attribute, pattern,timeout) returnValue = instance.WaitNotAttribute(attribute,pattern, timeout) 其中attribute为属性名,pattern预期的值,timeout超时时间
WaitCssValue:等待元素指定的Css属性变为指定值 WaitNotCssValue: 等待元素指定的Css属性不等于指定值 returnValue = instance.WaitCssValue(propertyName, value,timeout) returnValue = instance.WaitNotCssValue(propertyName, value, timeout) 其中propertyName为css属性名,value为属性值,,timeout超时时间
WaitDisplayed:等待元素的可见性 returnValue = instance.WaitDisplayed(displayed, timeout) 其中displayed为布尔类型是否可见
returnValue = instance.WaitEnabled(enabled, timeout) 其中enabled为布尔类型是否可用
instance.WaitNotElement(by, timeout) 其中by 是by机制查找元素
instance.WaitRemoval(timeout) 等待元素出现其实就是FindElement开头一类的方法,只是注意一下最后一个raise参数,当为false时为不引发异常,给一个空值。可以利用这点来帮我们判断一个元素是否出现。第二个参数time默认是3秒,等3秒如果没有找到看第三个参数是否引发异常,如果这个响应时间长可以设置长一点。这样就能智能的判断不像wait是一个定值。
returnValue = instance.WaitNotText(pattern, timeout) returnValue = instance.WaitText(pattern, timeout) 其中pattern指定的值(可匹配正则)
returnValue = instance.WaitSelection(selected, timeout) 其中selected是否被选中布尔型,
这里我就做几个例子,其它的大同小意,当然这里很重要,自己去一个一个试吧。 - .FindElementByXPath("//div[@class='ivu-page-options-elevator']/input").WaitAttribute "value", "3", 60000
复制代码
03
- cd.FindElementByXPath("//ul[@class='ivu-page']").WaitNotElement by.XPath("//li[@title=2]"), 30000
复制代码
04
- cd.FindElementById("screenList").WaitText "下载版", 60000
复制代码
05
在实际案例中,需要分析出网站是那个元素是加载完后,你所要的数据就加载出来了。有的还要分析点击事件是否被js(得看网页原代码)响应完成,响应完成后那才能抓取,还得用到我没讲的waiter,这是一个回调的应用。我给出作者的代码,这块我也没有研究明白。 - Private Assert As New Selenium.Assert
- Private Waiter As New Selenium.Waiter
- Private Sub Should_Wait_For_Delegate()
- Dim driver As New FirefoxDriver
- ' without delegate
- While Waiter.Not(WaitDelegate1(), timeout:=2000): Wend
-
- ' without delegate with argument
- While Waiter.Not(WaitDelegate2(driver), timeout:=2000): Wend
- ' with delegate on the driver
- driver.Until AddressOf WaitDelegate1, timeout:=2000
-
- ' with delegate with argument
- Waiter.Until AddressOf WaitDelegate1, driver, timeout:=2000
-
- ' with delegate without argument
- Waiter.Until AddressOf WaitDelegate2, timeout:=2000
- End Sub
- Private Function WaitDelegate1()
- WaitDelegate1 = True
- End Function
- Private Function WaitDelegate2(driver As WebDriver)
- WaitDelegate2 = True
- End Function
复制代码小结:如果是想要重复的操作特别是异步的网页,这个必须要掌握,不然就是一个半自动化办工。异步需要对网页的响应进行全面的分析,花费时间长,不过一切都是值得的。我用这个解决了一无聊系统的无聊工作,大大减少了我的工作时间。这是爽点啊!!
10 js Selennium可以直接 在网页中响应js,包括网页引用的jquery,easyui什么什么的,可以打开网页原码自己爽。 这里就以最后一个有趣的例子结束这个帖子
通过js给自己改了一个徽章,当然只是页面上显示多了,实际没有什么用。不过很好玩是不是!
06
- Sub 示例19()
- Dim cd As New ChromeDriver
- cd.Get "http://club.excelhome.net/thread-1452021-1-1.html"
- Stop '请登录
- '通过script获得一个新徽章
- jsStr = "document.getElementById('g_up9762161').firstChild.setAttribute('src','static/image/common/medal20.gif');"
- jsStr = jsStr & "alert('恭喜你获得了新徽章')"
- cd.ExecuteScript jsStr
- Stop
- End Sub
复制代码结语:写了一个星期占用了很多业余时间,感觉也在写的过程中有所得。希望对大家有用吧!
|