利用全局索引定位难缠的页面元素
前言
超级链接是网站中使用非常频繁的HTML元素,可以说超级链接是浏览者和服务器的交互的主要手段。
我们知道有点击链接时,大部分情况下都需要使用txt属性,因为链接没有其他属性可以用来匹配,但不是所有的超链接都支持txt属性特征串的,如果不支持,我们就只能通过索引+标签来定位唯一元素特征字符串了。
前言
咱们来举个栗子,比如我们想点击淘宝淘金币网址上的登陆查看金币明细这个页面元素,正常手动点击的话是会弹出账号登陆窗口的。
咱们启用网页分析工具按F9分析一下,发现这个肉眼看上去貌似是按钮的东西TAG标签属性上显示的是a,说明它也是个 超链接,所以它也只有TAG—标签属性、txt—文本属性和index—索引属性,且这个超链接就是不支持txt属性的,然后我们把它改成索引就正常定位到了,so-easy,我们高高兴兴码出如下代码:
Call Plugin.Web.Bind("WQM.exe")//启动wqm第一位就是要先绑定下wqm
Call Plugin.Web.Go("http://taojinbi.taobao.com/index.htm") //go命令跳转到淘金币页面,注意这个go命令会等页面正常加载完后再执行下面代码,所以不需要判断页面是否加载完成
Call Plugin.Web.HtmlClick("tag:A&index:135")//点击刚刚我们测试可以正常获取到的登陆位置的特征字符串
然后我们调试发现,根本没有我们预想到的会弹出账号登陆的窗口,而是直接跳转到其他页面去了,为什么会这样呢?
小编通过多台电脑测试发现,每台电脑打开时候分析到的全局索引值都是不一样的,比如小编这边分析到的是全局索引:135,其他电脑分析到的却是:144,或者有些更变态的网站每次刷新页面后索引值都会变化,那到底有没有办法能通过这种实时变化的索引值来点击元素特征串呢?
如何准确定位变化的全局索引值?
首先感谢下论坛18452大大发表的一篇文章,通过自带的web网页插件命令,用一个函数,就比较好的解决了这种问题。
//函数
Function 匹配文字获取全局索引值(获取类型, 特征串,匹配文字)
Num = Plugin.Web.HtmlExists(特征串)
For i = 1 To Num
Txt = Plugin.Web.HtmlGet(获取类型, 特征串&"&index:" & i)
If Txt = 匹配文字 Then
匹配文字获取全局索引值 = i
TracePrint 匹配文字获取全局索引值
//下面我加入了一个 匹配到全局索引后点击!
Call Plugin.Web.HtmlClick(特征串 & "&index:" & 匹配文字获取全局索引值)
End If
Next
End Function
思路:这个函数里面他用到了web网页插件里的俩个比较好用的命令,首先通过HtmlExists命令获取页面符合特征串的数量(这个特征串不仅仅局限于Tag—标签),然后通过for循环与HtmlGet命令搭配循环进行返回的文字匹配,如果与我们要找的文字匹配的话则返回全局索引值
HtmlGet命令
命令名称 HtmlExists 判断网页元素是否存在 命令功能 判断指定特征的网页元素是否存在,并返回匹配的个数 命令参数 参数1:字符串型,网页元素特征字符串 返 回 值 整数型,符合特征串的网页元素个数 这个命令主要用于判断符合特征串的页面元素是否存在,总共有多少个,比如我们可以用它来判断账号是否登陆了。
以我们按键论坛为例,很多论坛账号登陆界面都有且仅有一个自动登陆的选项,我们就可以用这个命令去获取这个自动登陆元素是否存在来判断当前状态是否登陆了,相关代码示例:
Call Plugin.Web.Bind("WQM.exe")
Call Plugin.Web.Go("http://bbs.anjian.com/forum.php")
元素个数 = Plugin.Web.HtmlExists("tag:LABEL&txt:自动登录")
If 元素个数 > 0 Then
Call Plugin.Web.Tips("您还没有登陆论坛,请在弹出的窗口上登陆下")
Call Plugin.Web.HtmlClick("tag:EM&txt:登录")
Else
Call Plugin.Web.Tips("您已经登陆论坛,点击签到按钮")
Call Plugin.Web.HtmlClick("id:pper_b")
End If
命令名称 HtmlGet 获取网页元素的信息 命令功能 获取网页元素指定属性的信息 命令参数 参数1:字符串型,网页元素属性类型:text、html、 outerHtml、value、 src、 href、 offset
参数2:字符串型,网页元素特征字符串这个命令主要用于页面某个元素的其他信息,比如文本内容等。
重新调试
言归正传,我们回到之前淘金币登陆点击的问题上,因为我们要获取的是元素文本内容,我们把"text"、"Tag:A"、"登录查看金币明细"分别代入函数后调试再看下,是不是就可以正确点击到了。
Call Plugin.Web.Bind("WQM.exe")
Call Plugin.Web.Go("http://taojinbi.taobao.com/index.htm")
Call 匹配文字获取全局索引值("text", "Tag:A", "登录查看金币明细")
'函数
Function 匹配文字获取全局索引值(获取类型, 特征串,匹配文字)
Num = Plugin.Web.HtmlExists(特征串)
For i = 1 To Num
Txt = Plugin.Web.HtmlGet(获取类型, 特征串&"&index:" & i)
If Txt = 匹配文字 Then
匹配文字获取全局索引值 = i
TracePrint 匹配文字获取全局索引值
//下面我加入了一个 匹配到全局索引后点击!
Call Plugin.Web.HtmlClick(特征串 & "&index:" & 匹配文字获取全局索引值)
End If
Next
End Function
后记
小编利用这个功能,勉强弄了个半成品的自动登陆领取淘金币的功能,不知道为什么第一次点击都会弹出验证码,验证码方面还没弄,有兴趣的童鞋可以自己研究看看。
Call Plugin.Web.Bind("WQM.EXE")
Call Plugin.Web.Go("http://taojinbi.taobao.com/index.htm")
网页源文件 = Lib.网络.获得网页源文件("http://taojinbi.taobao.com/index.htm")
If instr(网页源文件, "登录查看金币明细") > 0 Then
Call Plugin.Web.Tips("你未登录账号,请在弹出的窗口登陆下淘宝账号")
Call 匹配文字获取全局索引值("text", "Tag:A", "登录查看金币明细", 1, 8)
Call 判断是否登陆
Else
Call 判断是否登陆
End If
Function 匹配文字获取全局索引值(获取类型, 特征串,匹配文字,文字开始位置,文字结束位置)//相当于模糊搜索匹配文字
Num = Plugin.Web.HtmlExists(特征串)
TracePrint num
For i = 1 To Num
Txt = Plugin.Web.HtmlGet(获取类型, 特征串 & "&index:" & i)
If mid(txt,文字开始位置,文字结束位置) = 匹配文字 Then
// TracePrint txt
// If txt=匹配文字 Then
匹配文字获取全局索引值 = i
TracePrint 匹配文字获取全局索引值
//下面我加入了一个 匹配到全局索引后点击!
Call Plugin.Web.HtmlClick(特征串 & "&index:" & 匹配文字获取全局索引值)
Exit Function
End If
Next
End Function
Function 判断是否登陆()
TracePrint "开始进入循环"
Do
网页源文件 = Lib.网络.获得网页源文件("http://taojinbi.taobao.com/index.htm")
If instr(网页源文件, "今日可领") > 0 Then
Call Plugin.Web.Tips("您已经登陆账号,稍后帮您自动领取淘金币")
Call Plugin.Web.Go("http://taojinbi.taobao.com/index.htm")
// Delay 1000
Call 匹配文字获取全局索引值("text", "Tag:A", "今日可领", 1, 4)//只取今日可领这4个字,因为领取天数不同后面的数值会变,比如第一天是5金币,连续领取的话第二天就是10金币
Exit do
ElseIf instr(网页源文件, "今日已领") > 0 Then
Msgbox "逗我呢,该账号已领取过淘金币,请手动更换其他账号再领取"
ExitScript
End If
Delay 200
Loop
End Function