2023年11月25日发(作者:)
⽹页⾃动化——VBA和ation
⽹页⾃动化——VBA和ation
VBA⾃动化⽹页的多种⽅式
其实并不知道有多少种⽅式,下⾯随便罗列了⼀些:
wer⽅式
ation⽅式,需要引⼊接⼝:'在VBA编辑器窗⼝依次点击 ⼯具==引⽤ 勾选Microsoft Internet Controls 确定,再运
⾏,OK!
P 学习资料如下:
链接已死!
4.
ation⽅式
创建ation
Set ie = CreateObject("ation")
e = True
连接ation
如果能直接链接到已经打开⾄特定⽹页的浏览器,这就可以省略掉许多如登录等⾮重复⼯作的编码⼯作,但愿如此。
1. 或许可使⽤此函数GetObject实现(似乎实现不了)
set ie = GetObject(“”, “ation”)
这条语句并不会链接到已经打开的IE上,⽽是重新打开⼀个IE,更坑的是,它还是隐藏的,是个空⽩页。
32 API⽅式
Function FindWin(ByVal strRef As String) As Object
'找寻已打开的、以strRef为开头⽹址的⽹页
Dim objWin As Object
For Each objWin In CreateObject("ation").Windows
Do While tate <> 4 Or
DoEvents
Loop
If LCase(TypeName(nt)) = "htmldocument" Then
If onURL Like strRef & "*" Then
Set FindWin = objWin
Exit For
End If
End If
Next
Set objWin = Nothing
End Function
3.未知原理⽅式,简洁有效
1. 注意的是,此种情况下IE不具有焦点,可以⽤如下语句将其设为活动窗⼝:
SetForegroundWindow()
此时由于IE为活动窗⼝,将其上的控件设为具有焦点后,则可接受按键信息
SendKeys "{enter}"
点连接出现新选项卡的处理
ation中没有选择选项卡的功能,或许可以⽤GetObject功能来获得新选项卡中的⽂档?未知。
另⼀个⽅式:在点击前,改变中的target值为_SELF,让它在当前窗⼝当前选项卡中打开,处理完毕后返回历史记录获得之前的ie⽂档。待 另⼀个⽅式:在点击前,改变中的target值为_SELF,让它在当前窗⼝当前选项卡中打开,处理完毕后返回历史记录获得之前的ie⽂档。待 证实 事件驱动 要利⽤事件驱动,必须有WithEvent语句,⽽此语句不能⽤在通⽤模块中,只能⽤在窗体模块或类模块中。 DimWithEvents ie As etExplorer Private Subie_NavigateComplete2(ByVal pDisp As Object, URL As Variant) ript "=functionmyalert(msg){};" End Sub 待验证 页⾯加载完成判断和框架页⾯加载完成判断 ⽅法⼀: Do Until tate = READYSTATE_COMPLETE And = False DoEvents Loop 其中READYSTATE_COMPLETE的值为4. document亦具有readystate状态,其值为四种字符串,感兴趣的当为”complete”。 ⽅法⼆:NavigateComplete2事件判断。 ⽅法三:页⾯特殊字眼判断。 时间等待 ⽅法⼀: t1 = Timer Do Until Timer > t1 + 5 '需要时间触发⽹页上的onblur函数 DoEvents Loop ⽅法⼆: 在VBA中使⽤Sleep函数,需要添加: Private Declare Sub Sleep Lib "kernel32" (ByValdwMilliseconds As Long) ' Sleep (53000) ⽅法三: '如下,可以暫停10秒.实现类似于Sleep函数的功能 'newHour = Hour(Now()) 'newMinute = Minute(Now()) 'newSecond = Second(Now()) + 10 'waitTime = TimeSerial(newHour, newMinute, newSecond) ' waitTime 处理Alert等弹出式窗⼝ ⽅法⼀: 利⽤事件驱动⽅式将相关函数预设为空函数。待证实 'ript "m=null;" 'ript "dalDialog=null;" 'ript "=null;" 'End Sub ' ⽅法⼆: 原理和上⾯的相似,但不需要⽤到事件驱动⽅式。待证实,可能不适合动态产⽣的信息窗⼝ Set objscr = .Element_x("script") '创建⼀个脚本元素 = "m=function(x){return true;};" 'true是点击“确定”,false是点击“取消” .Child objscr '将脚本元素添加到body⾥ .mentByIdx_x("submit").Click ‘会产⽣弹出窗⼝的执⾏语句 ⽅法三: 感觉此⽅法与ation不协调,但是我唯⼀成功使⽤过的⽅法。这种⽅法应该算是软件⾃动化的⼀个基础,例如编写游戏外 挂。 找到弹出窗⼝的窗⼝句柄,并向其上的按钮发送单击事件从⽽关闭窗⼝。已证实可⽤,可应付动态产⽣的信息窗⼝ MicrosoftSpy++:⼯具,⽤于取得窗⼝类名、名称,控件类名、名称和WM信息等。 FindWindow:Win32 API函数,功能为取得窗⼝句柄 FindWindowEx: Win32 API函数,功能为取得窗⼝中控件的句柄 SendMessage: Win32 API函数,发送WM信息 声明部分: Private Declare PtrSafe Function FindWindowEx Lib"user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByValhWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As Any) As Long 'API抓窗⼝函数 Private Declare PtrSafe Function GetWindowText Lib"user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVallpString As String, ByVal cch As Long) As Long 'api取窗⼝⽂本函数 Private Declare PtrSafe Function FindWindow Lib"user32" Alias "FindWindowA" (ByVal lpClassName As String,ByVal lpWindowName As String) As Long Private Declare PtrSafe Function SendMessage Lib"user32" Alias "SendMessageA" (ByVal hwnd As Long, ByValwMsg As Long, ByVal wParam As Long, lParam As Any) As Long Public Const WM_LBUTTONDOWN = &H201 Public Const WM_LBUTTONUP = &H202 Public Const MK_LBUTTON = &H1 执⾏语句部分: Do Until FindWindow("#32770", "来⾃⽹页的消息") >0 DoEvents Loop hwd = FindWindow("#32770", "来⾃⽹页的消息") '⽹页对话框的句柄 Do Until FindWindowEx(hwd, 0, "Button", "确定") > 0 DoEvents Loop hwd_child = FindWindowEx(hwd, 0, "Button", "确定") '保存按钮的句柄 SendMessage hwd_child, BM_CLICK, 0, 0 '发送⿏标单击 ‘这⼀句似乎不能起作⽤,下⾯两句可以完成点击功能 SendMessage hwd_child, WM_LBUTTONDOWN, 0, ByVal0 '点击“确定”按钮(按下左键) SendMessage hwd_child, WM_LBUTTONUP, 0, ByVal0 '点击“确定”按钮(松开左键) SendMessage hwd_child, WM_LBUTTONUP, 0, ByVal0 '点击“确定”按钮(松开左键) 注意:由于⽹页和程序是异步的,所以要防⽌弹出窗⼝还没准备好,⽽执⾏语句已经到达,故上⾯层层检查弹出窗⼝是否已经准备好,最好在发 送WM信息前再延时1秒,已防意外。 动态加载页⾯的处理 本条内容待证实。 ⽹页脚本中,加⼊的js类的代码,该代码的作⽤是动态加载⽹页内容,这⾥的动态是指,当⿏标或者滚动条滚动到此处时,才会⾃动加载⽹页内 容,否则⽹页始终不加载,所以程序就陷⼊了⽆限循环,这个解决⽅法就是模拟滚动条滚动到需要加载内容的区域。 这涉及到两个内容: 第⼀个⽹页元素在浏览器页⾯中的定位⽅法; 元素对象相对于⽬前浏览器顶部位置的像素距离:ndingClientRect().top 元素对象相对于⽬前浏览器左侧位置的像素距离:ndingClientRect().left 第⼆个滚动条控制⽅法; By X,Y(⼀般x为0,Y为top值) 所以,完整答案为: ⽤框架⾥⾯或者链接加载完毕后⾥⾯的代码,这个代码要能够跟主页⾯代码有所区别,就是说主页⾯⾥⾯没有的代码,然后通过在主页⾯代码⾥ ⾯查找框架或链接⾥⾯独特代码是否存在的形式,来完成页⾯是否加载的判断,具体代码为: Do WhileInStr(主页⾯代码, "框架某⼀独特代码") <=1 DoEvents Loop DOM DOM的对象模型 2.⽂档树 元素与节点,ID与name 在HTMLDOM中,⽂档的每⼀部分都是节点,整个⽂档被定义为⼀个⽂档节点,每个标签是⼀个元素节点,包含在元素中的⽂本是⽂本节点,每 ⼀个元素的属性是⼀个属性节点。 ⽹页⽂档,可以说是由元素组合⽽成的,也可以说是由节点连接⽽成的树构造的。节点是⽂档树结构中特有的名词,元素是节点,但是节点不⼀ 定是元素,节点还有⽂档节点、⽂本节点、属性节点等;元素是元素节点的扩展,元素可以拥有属性还有⽂本。 可⼤致理解为,同⼀个html dom对象,提供的两个不同接⼝。 元素集合 引⽤:集合(0) 长度: 集合.length 元素的引⽤⽅式 1.直接调⽤ 对象 描述 Document 代表整个 HTML ⽂档,可被⽤来访问页⾯中的所有元素 Anchors Body 代表 元素 Forms 代表 元素集合 Frames 代表 元素或元素集合 Images 代表 Links 代表 元素集合 Options 代表 元素集合(select元素⾥⾯可以直接使⽤) Cells 代表 元素集合
Rows
代表 All 对象集合,提供对⽂档中所有 HTML 元素的访问。 2.函数调⽤ getElementById(“元素的id属性”)或all(“元素的id属性”):返回拥有指定id的元素; getElementsByName(“元素的name属性”)或all(“元素的name属性”):返回拥有指定名称的元素的集合; getElementsByTagName_r(“标签名称”)或(“标签名称”):返回该类标签的元素集合; all(索引号)循环与InStr字符串查找结合; getElementsByClassName(“class”)(n) 此函数可能没有实现,请参见getElementsByClassName。 3.树型结点查找 l⽗结点:parentNode l⼦结点:childNodes (children, 在IE9、IE10模式下,可能要⽤此属性,可参见下⼀条内容:getElementsByClassName); lnodeName(节点名称):元素节点的名称为其标签名,属性节点的名称为其属性名称; lnodeValue(节点值):⽂本节点的值为其包含的⽂本,属性节点的值为其包含的属性值; lnodeType(节点类型):元素节点为1、属性节点为2、⽂本节点为3、注释节点为8、⽂档节点为9 4.树型元素查找 l⽗元素:parentElement l⼦元素集合:children,然后通过判断标签名称(tagname),值(value),内含⽂本(innertext)等⽅式来进⾏查找 l兄弟元素:nextSibling、previousSibling getElementsByClassName(“classname”) 以下内容未知。 ⽬前这⼀⽅法IE9 IE10⽀持,返回的是⼀个对象集合,但是如果你的浏览器本⾝是IE9或者IE10,如果你⽤excel调⼊插件webbrowser插件,你可 能仍然⽆法使⽤这⼀⽅法,但是可以解决。 1、如果你的浏览器本⾝IE9以下,那么如果还想⽤这种⽅法,就⾃⼰编辑⼀个函数,有点问题,这个问题就是如果你是IE9或者IE10,你是可以使 ⽤这个⽅法的,但是需要修改注册表。 因为IE浏览器不⽀持getElementsByClassName,所以你要⾃⼰写⼀个⽅法得到class 但是⽕狐浏览器知道getElementsByClassName,可以直接的⽤ = function () { var tagName = getClass("div","a1"); //因为返回的是包含多个元素的数组,所以要遍历⼀下 for (var i = 0; i< ; i++) { tagName[i].innerHTML= "你好"; } var tagName = getClass("div","a2"); for (var i = 0; i< ; i++) { tagName[i].innerHTML= "ALL好"; } } function getClass(tagname, className){ //tagname指元素,className指class的值 //判断浏览器是否⽀持getElementsByClassName,如果⽀持就直接的⽤ if (mentsByClassName){ return getElementsByClassName(className); } else { //当浏览器不⽀持getElementsByClassName的时候⽤下⾯的⽅法 var tagname =mentsByTagName_r(tagname); //获取指定元素 var tagnameAll = []; //这个数组⽤于存储所有符合条件的元素 for (var i = 0; i< ; i++) { //遍历获得的元素 if(tagname[i].className == className) { //如果获得的元素中的class的值等于指定的类名,就赋值给tagnameAll tagnameAll[]= tagname[i]; } } return tagnameAll; } } 2、如果你的浏览器是IE9或者IE10,根据微软介绍,通常使⽤的webbrowser插件的版本是IE7,所以你需要修改注册表,让他默认的webbrowser ⽤IE9或者IE10. There are two different sets of keys for 32 bit and 64bit applications. 32 bit: HKEY_LOCAL_MACHINESOFTWAREMicrosoftInternetExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION Value Key: 64 bit: HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftInternetExplorerMAINFeatureControlFEATURE_BROWSER_EMULATION Value Key: The value to set this key to is (taken from MSDN here) as decimal values: 注意:如果更换了webbrowser⽤的基础IE版本,如果换了电脑,由于对⽅的IE版本可能不同,会引起⼀些列问题,需要注意。 ⽬前发现: ·excel2013,在插⼊webbrowser控件存在问题,⽆法插⼊,可能需要修改注册表等,具体解决⽅案暂没有看到。 ·childnodes在IE9 IE10下,存在问题,需要⽤children来代替; ·getBoundingClientRect()⽅法在IE7下可以⽤getBoundingClientRect().bottom(right/top),但是IE9 10就需要加⼊元素名称 getBoundingClientRect("id").bottom,才不会弹出错误。 innerHTML,outerHTML,innerText,outerText的区别 innerHTML 设置或获取位于对象起始和结束标签内的 HTML outerHTML 设置或获取对象及其内容的 HTML 形式 innerText 设置或获取位于对象起始和结束标签内的⽂本 innerText 设置或获取位于对象起始和结束标签内的⽂本 outerText 设置(包括标签)或获取(不包括标签)对象的⽂本 innerText和outerText在获取时是相同效果,但在设置时,innerText仅设置标签内的⽂本,⽽outerText设置包括标签在内的⽂本。 简单的说innerHTML和outerHTML、innerText与outerText的不同之处在于: 1)、innerHTML与outerHTML在设置对象的内容时包含的HTML会被解析,⽽innerText与outerText则不会。 2)、在设置时,innerHTML与innerText仅设置标签内的⽂本,⽽outerHTML与outerText设置包括标签在内的⽂本。 对于⼀个id为"testdiv"的div来说,outerHTML、innerHTML以及innerTEXT三者的区别可以通过下图展⽰出来: 表单form的处理 表单form对象,有⼀个⽅法⽐较重要,就是submit,这个⽅法提供了表单的提交的动作。如果我们捕捉页⾯的提交按钮⾮常困难时,有时候只要 对表单,执⾏submit⽅法,表单也是可以提交的,不需去点击提交按钮。 表单控件,⽂本输⼊类控件,最常⽤就是value的属性了,通过这个属性,可以往⽂本框⾥⾯添加⽂本。 单选框、复选框,常⽤的就是checked属性了,如果为true就是被选中了,或者直接使⽤click⽅法也⾏。 下拉列表呢,可以通过select对象的selectedIndex属性去设置选中项,也可以通过其内含对象集合options(),设置某个options(x)的selected属性 为true,来设置选中项。 表格table的处理 Table对象.rows(0).cells(0) 每个单元格的innertext属性即可获取单元格的⽂本 框架frame和iframe Frame和iframe元素,均体现在frames对象集合⾥⾯,其最重要的属性就是contentDocument,也就是获取框架内的页⾯⽂档。 页⾯内容加载完毕,不代表框架页⾯内容加载完毕,故判断此点是⼀个⿇烦事。 document的属性frames仅⽀持到IE8,其后的IE只能通过getElementsByTagName_r(“frames”)来获得。 fireevent fireevent主要⽤于,有的表单的校验机制⾮常强,需要光标聚焦了,⽂本change了等等,才能提交表单,这些事件的模拟只能靠fireevent了,其 他⽅法就很难替代了。 ent"onclick" '触发body的点击事件 ation完整列表 HTML简介 整体框架 ⽹页⽂档主体 布局 段落 跳转的URL” target=”_blank/_self”>显⽰的超链接⽂本 图像 图像 ⽂本”> 表格 列表 1.有序列表 2.元序列表 3.⾃定义列表 表单和控件 表单form这个元素,有“method”和“action”两个属性,action属性指定的就是,提交表单后,向这个属性指定URL发送http请求(呵呵,涉及到第⼀ 节课的知识啦),method这个属性设定的就是,要按照get或者post等⽅式发送http请求。 1. 其类型由type属性定义,常见的有:text(⽂本框)、Radio(单选按钮)、Checkboxes(复选框)、submit(提交按钮)、hidden(隐藏)、 reset(重置)和password(密码框)等。 2. 如果存在multiple="multiple"的属性设定,则允许菜单多选,否则单选。Size是设置可见的菜单条⽬数。其下级元素,option代表的是其每个菜单 项⽬,语法为: 框架、 框架已死。 验证码图⽚处理 元素集合(table元素⾥⾯可以直接使⽤) 第⼀⾏第⼀个单元格 第⼀⾏第⼆个单元格 第⼆⾏第⼀个单元格 第⼆⾏第⼆个单元格
发布评论