版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、基于internet explorer內(nèi)核的網(wǎng)頁信息抓取程序2009年3月25日程序開發(fā)背景本程序來源于我們項(xiàng)目組最近正在開發(fā)的一個(gè)開源項(xiàng)目網(wǎng)頁分塊工具。其目的是作為一個(gè)底層的信息抽取模塊,為后期分析提供盡可能詳盡的分塊線索,包括盡可能完整的html源代碼和網(wǎng)頁元素的位置、顏色、字體、背景色等信息。程序還要具有較好的適應(yīng)性,能夠支持多種網(wǎng)頁,而事實(shí)上很多網(wǎng)頁都是不標(biāo)準(zhǔn)的。從通用性考慮,程序應(yīng)該能夠支持多種應(yīng)用,而不僅限于網(wǎng)頁分塊。預(yù)期目標(biāo)分析程序應(yīng)達(dá)到以下幾點(diǎn)設(shè)計(jì)要求:l 能夠指定要處理的網(wǎng)頁的url。l 能夠?yàn)閔tml源代碼添加附件信息,如元素位置。l 對(duì)于javascript等動(dòng)態(tài)腳本具有
2、良好的解析能力。l 通過命令行調(diào)用,提供良好的通用性。l 通過socket套接字返回html源代碼。l 支持延時(shí)讀取,保證抓取的成功率。l 支持超時(shí)退出,保證程序不會(huì)因?yàn)榧虞d不成功而卡死。使用ie內(nèi)核的原因本程序的核心部分使用的是ie內(nèi)核。至于為什么要基于ie內(nèi)核,而不使用其他瀏覽器的內(nèi)核,有以下幾方面的原因:首先,firefox、google chrome等瀏覽器雖然是開放源代碼的,但是其源代碼的閱讀難度相當(dāng)大,想在短時(shí)間內(nèi)弄明白是很困難的。其次,ie的相關(guān)開發(fā)文檔比較完整,開發(fā)環(huán)境比較容易構(gòu)建,開發(fā)起來更容易上手。最后,從網(wǎng)頁的兼容性考慮,得益于ie的廣泛的市場占有率,其兼容性明顯要比其他
3、瀏覽器要好很多,盡管對(duì)很多標(biāo)準(zhǔn)都支持得不是很好。綜上,就可以確定本程序使用ie內(nèi)核進(jìn)行開發(fā),實(shí)驗(yàn)證明,這個(gè)做法是正確的。internet explorer的程序結(jié)構(gòu)對(duì)于本程序來說,其中最重要的的就是網(wǎng)頁內(nèi)容處理層,所用到的接口也都位于mshtml.dll文件中。開發(fā)環(huán)境系統(tǒng):windows xpide:visual studio 2005中文版ie版本:internet explorer 6構(gòu)建基于對(duì)話框的mfc程序運(yùn)行visual studio 2005(c+),新建一個(gè)項(xiàng)目,選擇mfc標(biāo)簽下的 “mfc應(yīng)用程序”作為模板,填入項(xiàng)目名稱,確定。此時(shí)會(huì)彈出一個(gè)向?qū)?,按照以下步驟操作:點(diǎn)擊左側(cè)的
4、”應(yīng)用程序類型”,選擇”基于對(duì)話框”,”在靜態(tài)庫中使用mfc”(方便以后發(fā)布),其他保持默認(rèn)即可。然后單擊完成,程序會(huì)自動(dòng)生成相應(yīng)的類。切換到資源視圖,依次展開,在dialog中找到以項(xiàng)目名稱命名的對(duì)話框,雙擊打開。刪除“確定”和“取消”按鈕。在對(duì)話框窗口上單擊右鍵,選擇“插入activex控件”。在新彈出的窗口中選擇”microsoft web 瀏覽器”,確定。調(diào)整好ie控件的位置后,在其上單擊右鍵,選擇“添加變量”,輸入名稱m_webbrowser。切換到解決方案視圖,打開對(duì)話框的源文件,名稱通常為*dlg.cpp(*為項(xiàng)目名)。將下面的代碼添加到對(duì)話框初始化函數(shù)oninitdialog(
5、)中。lpctstr url = _t(“http:/*”);m_webbrowser.navigate(url,&vtempty,&vtempty,&vtempty,&vtempty);如何確定webbrowser控件中的網(wǎng)頁加載完成當(dāng)網(wǎng)頁下載完成后,webbrowser控件觸發(fā)documentcomplete 事件。通過在程序中添加響應(yīng)documentcomplete事件的程序,我們就可以在網(wǎng)頁下載完成后對(duì)其進(jìn)行分析和處理。添加事件處理程序的操作步驟如下:切換到資源視圖,打開包含webbrowser控件的對(duì)話框,在webbrowser控件上單擊右鍵,選擇“添加事件處理程序”,然后在彈出的對(duì)
6、話框中選擇documentcomplete消息,點(diǎn)擊“添加編輯”以確認(rèn)。webbrowser控件觸發(fā)documentcomplete事件的readystate屬性更改為 readystate_complete時(shí),這表示 webbrowser 控件已完成下載網(wǎng)頁。雖然通過響應(yīng)documentcomplete事件可以知道網(wǎng)頁是否加載完成,但是有的網(wǎng)頁觸發(fā)了不止一次documentcomplete事件,例如網(wǎng)易首頁會(huì)從加載開始到完全加載完畢會(huì)激發(fā)二十多次documentcomplete事件。出現(xiàn)這種情況的主要原因是:網(wǎng)頁中包含javascript等動(dòng)態(tài)腳本,而且有可能會(huì)改變網(wǎng)頁元素的結(jié)構(gòu),當(dāng)這些腳本
7、完成解析后會(huì)觸發(fā)documentcomplete事件;如果網(wǎng)頁是由多個(gè)frame框架組成的,每個(gè)框架中的網(wǎng)頁加載完成也會(huì)觸發(fā)documentcomplete事件。針對(duì)第二種情況,微軟給出了具體的解決方案, 通過將documentcomplete事件處理函數(shù)的參數(shù)中的url與當(dāng)前的網(wǎng)頁文檔的url相比較,若相同,則說明整個(gè)網(wǎng)頁都已經(jīng)完成加載,此時(shí)再對(duì)網(wǎng)頁進(jìn)行分析和處理,然后退出。按照理論,只需對(duì)網(wǎng)頁做一次處理就可以了。然而在測試新浪博客時(shí),我又發(fā)現(xiàn)了問題 在博客評(píng)論加載完成之前觸發(fā)很多次documentcomplete事件,其中的一次事件對(duì)應(yīng)的url與網(wǎng)頁文檔的url一樣。如果只對(duì)網(wǎng)頁處理一次,
8、程序是無法處理獲取加載評(píng)論之后的網(wǎng)頁。這就是為什么程序需要加上延時(shí)讀取功能的原因,具體思路請(qǐng)參照下一節(jié)。當(dāng)然,在webbrowser控件的事件中,還有其他的事件,比如navigatecomplete2事件。我曾經(jīng)嘗試在其他事件觸發(fā)時(shí)對(duì)網(wǎng)頁進(jìn)行分析,但是都會(huì)出錯(cuò),要么只能獲取到一部分元素,要么直接就彈出錯(cuò)誤信息。這是因?yàn)榇藭r(shí)網(wǎng)頁尚未完全加載,很多元素的屬性都沒確定,當(dāng)然無法確定元素的具體信息,如元素位置信息。延時(shí)讀取和超時(shí)退出為了降低網(wǎng)絡(luò)、機(jī)器配置、系統(tǒng)軟件等外界因素對(duì)程序的影響,提高讀取的成功率。本程序加入了延時(shí)讀取和超時(shí)退出的功能。具體實(shí)現(xiàn)方法是:首先在程序的初始化函數(shù)中,如對(duì)話框的onin
9、itdialog函數(shù),添加一個(gè)固定id的定時(shí)器,使程序定時(shí)發(fā)出一個(gè)wm_time消息。具體函數(shù)如下:settimer(8888,1000,null);/8888為該定時(shí)器的id,1000為定時(shí)發(fā)出wm_time消息的時(shí)間,單位為毫秒。然后添加一個(gè)處理wm_time消息的函數(shù),其代碼如下:void cmybrowserdlg:ontimer(uint_ptr nidevent)ctime ct;ctimespan cts(0,0,0,5000);/程序延時(shí)執(zhí)行時(shí)間ctimespan timeout(0,0,0,m_timeout);/程序超時(shí)退出時(shí)間/判斷定時(shí)器id,若非指定的定時(shí)器id則退出i
10、f(nidevent =! 8888)cdialog:ontimer(nidevent);return;/獲取當(dāng)前時(shí)間ct = ctime:getcurrenttime();/超時(shí)退出,并輸出錯(cuò)誤信息if(ct (m_time+timeout):postquitmessage(3);/強(qiáng)制退出程序,并返回一個(gè)int型的值/獲取ihtmldocument2指針,以便進(jìn)行下面的操作ccomqiptr spdoc2 = (ihtmldocument2 *)m_webbrowser.get_document();/判斷網(wǎng)頁加載狀態(tài),若加載完成則繼續(xù)處理;否則返回if(1 != m_flag)/m_fl
11、ag為documentcomplete事件觸發(fā)標(biāo)志,1表示已觸發(fā),0表示尚未觸發(fā)return;else if(m_webbrowser.readystate_complete != m_webbrowser.get_readystate()return;else if(ct get_body(&pbody);/獲取body對(duì)象的指針,返回操作結(jié)果if( succeeded( hr ) )/若操作成功,則繼續(xù)執(zhí)行/ something to doihtmldocument3接口前面說過了ihtmldocument3只是ihtmldocument2接口的擴(kuò)展,而且在本程序中用到該接口的地方也就一兩
12、處。使用ihtmldocument3接口的原因是其提供了一個(gè)get_documentelement函數(shù),下面是其介紹和簡單的示例:函數(shù)原型 功能說明 hresultget_documentelement(ihtmlelement*p); 獲取html文檔中根節(jié)點(diǎn)的接口指針 示例:ihtmlelement * pdocelem;/ ihtmlelement接口指針,指向body對(duì)象 hresult hr;/用于存放函數(shù)調(diào)用結(jié)果 hr = pdoc2-get_documentelement (& pdocelem);/獲取body對(duì)象的指針,返回操作結(jié)果if( succeeded( hr ) )/
13、若操作成功,則繼續(xù)執(zhí)行 / something to do 獲取根節(jié)點(diǎn)的目的是通過它獲取整個(gè)html文檔的源代碼,具體如何獲得請(qǐng)看下面關(guān)于ihtmlelement接口的介紹。ihtmlelement接口函數(shù)原型 功能說明 hresultget_innerhtml(bstr*p); 獲取當(dāng)前對(duì)象開始和結(jié)束標(biāo)簽之間的html源代碼(動(dòng)態(tài)內(nèi)容) hresultget_innertext(bstr*p);獲取當(dāng)前對(duì)象開始和結(jié)束標(biāo)簽之間的文本內(nèi)容(動(dòng)態(tài)內(nèi)容)hresult get_outerhtml(bstr*p); 獲取對(duì)象的html的內(nèi)容(靜態(tài)內(nèi)容) hresult get_outertext(bs
14、tr*p); 獲取對(duì)象的文本內(nèi)容(靜態(tài)內(nèi)容) 下面只給出get_innerhtml函數(shù)的使用方法示例,另外三個(gè)函數(shù)類似:ihtmlelement * pelem;/ ihtmlelement接口指針,指向body對(duì)象 bstr html;/存放html源代碼 _bstr_t html_t;/用于將bstr轉(zhuǎn)換為cout可以處理的字符串 hr = pelem-get_innerhtml(&html);if( succeeded( hr ) )html_t = html; cout”the html within this element is:”getabsx();/獲取父節(jié)點(diǎn)的絕對(duì)坐標(biāo)if(s
15、ucceeded(spelement-get_offsetleft(&absx) absx += parentabsx;值得注意的是這兩個(gè)函數(shù)獲取到的都是相對(duì)于父節(jié)點(diǎn)的坐標(biāo),計(jì)算元素絕對(duì)坐標(biāo)時(shí)還需要加上父節(jié)點(diǎn)的絕對(duì)坐標(biāo)。因此在設(shè)計(jì)程序時(shí)使用了一個(gè)自定義的node類,其中包含著當(dāng)前節(jié)點(diǎn)位置信息,然后傳遞給子節(jié)點(diǎn),子節(jié)點(diǎn)計(jì)算出相對(duì)坐標(biāo)后再加上該絕對(duì)坐標(biāo)就可以得到子節(jié)點(diǎn)的絕對(duì)坐標(biāo)。在ie的內(nèi)存模型中,網(wǎng)頁文檔是以dom(document object model文檔對(duì)象模型)存放在內(nèi)存中的,對(duì)網(wǎng)頁的處理和分析都是基于dom來操作的,其操作方法與普通的dom并無太大區(qū)別。下面簡單介紹ie處理網(wǎng)頁的兩個(gè)
16、dom相關(guān)接口:ihtmldomnode接口函數(shù)原型 功能說明 hresultget_childnodes(idispatch*p); 獲取指定節(jié)點(diǎn)的所有直接后裔節(jié)點(diǎn)的集合 hresultget_nodetype(long*p); 返回指定節(jié)點(diǎn)的類型 在網(wǎng)頁文檔的dom結(jié)構(gòu)中,標(biāo)簽的屬性、文本和注釋都是以節(jié)點(diǎn)的形式存在的。然而這些節(jié)點(diǎn)卻無法使用其他接口來處理,如ihtmlelement接口,如果要對(duì)這些類型的節(jié)點(diǎn)強(qiáng)行操作,程序就會(huì)報(bào)錯(cuò)退出。因此在dom遞歸時(shí)要進(jìn)行查詢ihtmlelement接口時(shí),就要通過ihtmldomnode的nodetype來進(jìn)行判斷。只有當(dāng)nodetype為eleme
17、nt時(shí)才有子節(jié)點(diǎn),向下遞歸才不會(huì)出錯(cuò)。nodetype所對(duì)應(yīng)的節(jié)點(diǎn)類型:(attribute屬性) 1(element元素) 3(text文本) 8(comment注釋)。 ihtmldomchildrencollection接口函數(shù)原型 功能說明 hresultget_length(long*p); 獲取集合中子節(jié)點(diǎn)的個(gè)數(shù) hresultitem(longindex, idispatch*ppitem ); 獲取指定索引位置的子節(jié)點(diǎn) 遍歷dom中的所有節(jié)點(diǎn)結(jié)合ihtmldomnode接口和ihtmldomchildrencollection接口就可以遍歷dom中的所有節(jié)點(diǎn)。下面是示例代碼:v
18、oid getallchild(ihtmldomnode * pnode)ccomptr spchildrendisp;/用于子節(jié)點(diǎn)的集合 ccomptr spchilddisp;/正在處理的子節(jié)點(diǎn) ihtmldomchildrencollection *spchildrennode;longnodetype;/節(jié)點(diǎn)類型 pnode-get_nodetype(&nodetype);pnode-get_childnodes(&spchildrendisp);if( 3 = nodetype )/判斷節(jié)點(diǎn)類型是否為element /一些額外的操作spchildrennode = (ihtmldomchildrencollection *)spchildrendisp;spchildrennode-get_length(&childrennum);/獲取子節(jié)點(diǎn)的集合長度 for(long i = 0 ; iitem(i,&spchi
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度智能家居公司成立合作協(xié)議書正式版4篇
- 2025年度新型農(nóng)業(yè)貸款合同標(biāo)的特征分析3篇
- 2024版鋁單板采購合同
- 2025年度養(yǎng)老設(shè)施承建與適老化裝修服務(wù)合同4篇
- 2025年現(xiàn)代農(nóng)業(yè)設(shè)施設(shè)備租賃合同3篇
- 攪拌樁施工方案
- 部編版八年級(jí)語文上冊(cè)《與朱元思書》中考復(fù)習(xí)教學(xué)設(shè)計(jì)
- 香料植物課程設(shè)計(jì)
- 2025年度車禍?zhǔn)芎φ呒彝ダщy援助協(xié)議3篇
- 二零二五版門窗行業(yè)信息化管理系統(tǒng)開發(fā)合同4篇
- 稱量與天平培訓(xùn)試題及答案
- 超全的超濾與納濾概述、基本理論和應(yīng)用
- 2020年醫(yī)師定期考核試題與答案(公衛(wèi)專業(yè))
- 2022年中國育齡女性生殖健康研究報(bào)告
- 各種靜脈置管固定方法
- 消防報(bào)審驗(yàn)收程序及表格
- 教育金規(guī)劃ppt課件
- 呼吸機(jī)波形分析及臨床應(yīng)用
- 常用緊固件選用指南
- 私人借款協(xié)議書新編整理版示范文本
- 自薦書(彩色封面)
評(píng)論
0/150
提交評(píng)論