一、 目標
擷取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)。