一、 目标
获取Web页面上的元素坐标,如获取http://www.baidu.com/上的文本输入框的坐标和“百度一下”按钮坐标。
二、 环境及开发工具
环境:Java
工具:eclipse
开发包:如图
三、 原理
浏览器可以通过得到html源码,经过浏览器内核HTML解析引擎对html源码进行解析,最后得到构建文档模型DOM,浏览器渲染引擎随即建立与DOM对应的Render树,JS引擎解析并执行Javascript,排版引擎(如IE的MSHTML)对在浏览器平台中绘制图层模板(layout),最后由渲染引擎对图层模板进行渲染得到漂亮的网页页面呈现给用户。
由此可见,排版引擎是可以知道html元素在客户端浏览器上的具体坐标位置,才对网页元素在浏览器平台上进行布局的。
因此,要获取网页元素的坐标,则只需使用浏览器解析网页后所得到的排版引擎的相关数据,则可以得到某个网页元素的坐标。
MSHTML 是微软的窗口操作系统(Windows)搭载的网页浏览器—Internet Explorer的排版引擎的名称,(又称为Trident)。MSHTML是微软公司的一个COM组件,该组件封装了HTML语言中的所有元素及其属性,通过其提供的标准接口,可以访问指定网页的所有元素。
MSHTML提供了众多的API给用户编写程序,其提供的标准接口如下图:
在这些MSHTML提供的众多接口中有很多接口是可以访问网页元素的,如:
其中的有几个方法是可以获取网页元素的与坐标相关的。
其中,offsetLeft是获取基于父元素的左移的偏置像素,offsetTop是获取基于父元素的下移的偏置像素,offsetParent则获取该偏置元素的父元素。
因此,可以通过利用该接口提供的方法,抽取某个元素的坐标信息。其参考算法如下:
(1)获取网页表单中需要获取坐标的那个控件元素的接口指针;(2)根据获得的接口指针,调用函数get_offsetLeft()来取得控件元素相对offsetparent的偏移量;(3)累加get_offsetTop,和get_offsetLeft,直到offestParent为BODY,来取得元素相对于页面左上角的坐标;(4)获取控件元素右下角的坐标,方法与上面(2)、(3)类似,其中获取元素的横坐标时要先加上元素自身的宽度,通过函数get_offsetWidth()获取,同时,获取纵坐标时要先加上元素自身的高度,通过函数get_offsetHeight()获取。
四、 具体实现
1. 构建浏览器,并导航到www.baidu.com。
类定义为:
其中,IDolongWebBrowser是笔者基于jexplorer-1.9构建的浏览器接口。
2. 使用org.w3c.dom.Document.getElementById(String elementId)获取网页元素HTMLElement
即得到id为kw的百度首页输入文本框和id为su的“百度一下”按钮,其两个元素的html源码为:
<input name=wd id=kw maxlength=100 style="width:444px;">
<input type=submit value="百度一下" id=su class=btn onmousedown="this.className='btn btn_h'" onmouseout="this.className='btn'">
因此,可以知道他们的id属性。
3. 建立HTMLElement与MSHTML的IHTMLElement接口的消息绑定
该函数是为了获得HTMLElement对应的MSHTML中IHTMLElement接口,在计算坐标函数中被调用。
4. 计算元素的X坐标和Y坐标函数
五、 调试及结果
获得两个元素的HTMLElement对象,并获取浏览器对应的WebBrowser接口,调用计算坐标函数:
执行结果:
值得声明的是,该坐标是基于浏览器左上角的,即左上角为(0,0)。