网页数据提取功能主要在一个 C++类及其辅助类中完成。假设提取类的名称为
CDownloader(下载器),则当 BHO 加载时,创建一个 CDownloader 对象,并将
Invoke 中收到事件转发给该对象进行处理。CDownloader 处理 IE 事件的主要方法有两
个:一个是 OnBeforeNavigate2(VARIANT_BOOL *pCancel, VARIANT *pVarURL,
IDispatch *pDispBrowser),用于处理 DISPID_BEFORENAVIGATE2 事件;另一个是
OnDocumentComplete(VARIANT *pVarURL, IDispatch *pDispBrowser),用于处
理 DISPID_DOCUMENTCOMPLETE 事件。
CDownloader 具体的实现思路如下:
1、在 OnBeforeNavigate2 中记录起始页。需要定义一个变量 IDispatch*
m_pStartBrowser 以记录起始页的浏览器对象,定义一个变量 HWND m_hwndStart 以
记录起始页的浏览器窗口句柄,定义一个变量 TCHAR m_szUrlStart[MAX_URL]以记录
起始页的 URL。当调用 OnBeforeNavigate2 时,检查 m_pStartBrowser 是否为空,如
果为空表明下载还没有开始,需要自动决定或由用户选择决定是否把当前即将跳转到的页
面作为起始页,如是则将 OnBeforeNavigate2 传入的 pDispBrowser 保存到
m_pStartBrowser 变量中,pVarURL 保存到 m_szUrlStart 变量中,同时找到
pDispBrowser 对应浏览器对象的窗口句柄保存到 m_hwndStart 变量中。
2、在 OnDocumentComplete 中,根据完成页面与起始页的关系,进行相应的处理。最
典型的两种情况中,一种是当起始页完成时,OnDocumentComplete 事件的浏览器对
象与原来保存的起始页 m_pStartBrowser 相同,并且 URL 也相同。此时需要新建一个线
程读取和解析文档内容,并根据设定的条件进行自动点击。另一种情况是数据页面完成时,
OnDocumentComplete 事件的浏览器对象与原来保存的起始页 m_pStartBrowser 不
同,并且各自的顶层窗口也不相同。此时同样需要新建一个读取和解析文档内容,并保存
数据到指定的文件中。上述两种情况创建线程后,浏览器 COM 对象需进行跨线程传递,
因此要调用 CoMarshalInterThreadInterfaceInStream 和
CoGetInterfaceAndReleaseStream 函数在两个线程端转换。
3、在检查起始页时,一方面需要点击打开新的数据页面,另一方面在所有数据页的链接
已经完成后,需要检查有无指向下一页的标记,如果有则自动点击并跳转。到下一页的跳
评论15