本人是大学刚刚毕业从事C++开发半年的小菜鸟,但是对编程非常热爱,今天是第一次鼓起勇气在看雪发非求助帖子,献丑了。
首先说明一下:1.绝大多数Web表单中带有Submit类型按钮并带有Password类型文本框的,我们就可以认为这个表单是一个用来输入账号和密码的表单,我不敢保证100%正确,但是95%以上绝对没有问题。
2.如果一个Web表单包含text类型文本框、textarea类型文本框、Submit类型按钮,我们完全有理由认为这个表单是用来发帖子的。
好了有了以上2点,就有了努力的方向了:
1.我们可以建立一个时钟,每隔一段时间去遍历开启的浏览器,并监听浏览器事件
遍历浏览器我们可以用IShellWindows接口指针,这个接口有个方法叫get_count(),我们可以获取到当前开启了多少个浏览器,既然获取到了浏览器个数那么我们就可以用for循环进行遍历,微软还提供了一个接口IWebBrowser2,MSND上解释说IWebBrowser2是浏览器控件或IE的实现,那么我们可以在for循环内把IShellWindows::Item()付给IWebBrowser2的指针
现在的问题是我们如何监听浏览器事件,微软提供了一个函数AtlAdvise(),MSDN上的解释是可以在对象连接点和客户端的sink(我不知道翻译成什么好
)之间建立一个连接,这样说在我们的C++程序中必须建一个sink,这个sink类很简单,只要从IDispatch接口派生一下就OK,当然了要实现IDispatch和IUnknown的虚函数,在调用AtlAdvise()之后,我们就可以在sink类的Invoke函数里面响应浏览器事件了。
也许看到这大家会想,每隔一段时间遍历一次开启的浏览器(在遍历浏览器里面我们当然还要做遍历网页,要不遍历浏览器有什么用
),如果开启的浏览器和网页少行,如果多了电脑肯定运行的很慢
,我当时对这个问题也很头疼,于是我是一个劲的查MSDN
,都要查到绝望了,终于发现微软真好,IWebBrowser2接口有2个函数IWebBrowser2::GetProperty和IWebBrowser2::PutProperty,IWebBrowser2::PutProperty允许我们自己设定一个属性,嘿嘿,机会来了,这样的话我们可以用IWebBrowser2::PutProperty设定一个属性标示这个浏览器已经用AtlAdvise()与sink建立连接了,并遍历了,然后在遍历开始的时候用IWebBrowser2::GetProperty获取标示,如果遍历了就直接返回了
,现在问题又来了,如果把浏览器标示遍历过了,那么人家开启新网页不就不去遍历了吗?对,是这样的,但我们有办法解决,可以在sink类的Invoke函数里响应一下浏览器的DISPID_NAVIGATECOMPLETE2事件,如果浏览器跳转到新的网页,再把浏览器设为未遍历状态,OK,哈哈
2.我们在遍历浏览器里面加上遍历网页中的表单、表单元素(比如:文本框,提交按钮)
接上面,截然我们有了IWebBrowser2,那么我们首先调用IWebBrowser2::get_Document()获取文档指针,这样我们就获取到了IHTMLDocument2接口的指针,有了IHTMLDocument2接口指针,我们就可以用来遍历网页中的表单了,先调用IHTMLDocument2::get_forms(),这个函数有个Out参数,类型是IHTMLElementCollection的二级指针,这样就获取到了表单集合,然后调用IHTMLDocument2::get_length获取表单数目,老办法用for循环遍历表单,在遍历过程中我们会将每个IHTMLElementCollection::Item(),赋给IHTMLFormElement的指针。
现在又有个问题,我们在获取通过浏览器在Web表单中输入的账户、密码或者是发帖的标题和内容,有很关键的一点就是获取到表单提交这一时刻,当表单刚提交时,我们立即将我们需要的东西拿出来,要不然就没法获取了
,是不是想起什么东西来了,对了AtlAdvise(),但是我们这次不用这个函数了,嘿嘿
各位,不好意思,下班了,周一接着写
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课