怎样获取firefox正在访问的URL?

coding8848 2009-11-15 05:22:50
不要用DDE的方法。
...全文
1897 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
gtzjfa 2010-07-02
  • 打赏
  • 举报
回复
看不懂,帮顶
yangdaming1983 2010-01-19
  • 打赏
  • 举报
回复
mark
huhuc 2009-12-25
  • 打赏
  • 举报
回复
use oleacc;//http://files.codes-sources.com/fichier.aspx?id=28611&f=oleacc.pas
function ffdoc: THandle;
const
A_szClassName:array[0..6] of PChar=('MozillaUIWindowClass','MozillaWindowClass',
'MozillaWindowClass','MozillaWindowClass','MozillaContentWindowClass',
'MozillaWindowClass','MozillaWindowClass'
);
var
i:Integer;
begin
Result:=0;
for i:=0 to 6 do Result:=FindWindowEx(Result,THandle(nil),A_szClassName[i],nil);
end;
function ffurl:string;
var
acc:IAccessible;
pw:PWChar;
begin
if AccessibleObjectFromWindow(ffdoc,OBJID_CLIENT,IID_IAccessible,Pointer(acc))=0 then
Acc.get_accValue(CHILDID_SELF,pw);
Result:=pw;
end;

initialization
OleInitialize(nil);
finalization
OleUninitialize;
擒兽 2009-12-12
  • 打赏
  • 举报
回复
强烈关注
tiancanyue 2009-11-16
  • 打赏
  • 举报
回复
关注
coding8848 2009-11-16
  • 打赏
  • 举报
回复
up up
iseekcode 2009-11-16
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 coding8848 的回复:]
DDE不能显示最后一个窗口的URL,当开了多个IE的时候。。。
[/Quote]

不用DDE的话,IE内核的可以遍历...
coding8848 2009-11-15
  • 打赏
  • 举报
回复
DDE不能显示最后一个窗口的URL,当开了多个IE的时候。。。
贝隆 2009-11-15
  • 打赏
  • 举报
回复
帮顶
iseekcode 2009-11-15
  • 打赏
  • 举报
回复
对这个问题很感兴趣.
我都是用的DDE.
好像有不少人是做个FF插件,我不喜欢插件.
期待高人.
coding8848 2009-11-15
  • 打赏
  • 举报
回复
 程序基于以下思路:首先通过Spy++软件获得所有基于IE内核浏览器的顶级窗口类型(比如IE7.0的窗口类型为“ IEFrame ”,Maxthon2为” Maxthon2_Frame ”)和网页容器窗口类型(IE7.0为” Internet Explorer_Server ”,然后枚举所有的窗口并获得其窗口类型,如果符合上述类型之一则对其子窗口进行枚举并取得其网页容器窗口类型,下面是最关键的一步,通过上面所说的AccessibleObjectFromWindow获得容器窗口的Iaccessible指针,接着就可以进一步获得前面所说的IhtmlDocument2指针。
下面以支持标签式浏览的IE7.0为例,具体程序如下:
  // 窗体过程函数
  BOOLCALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam) {
  char buf[100];
  GetClassName(hwnd,(LPTSTR)&buf,100); // 获得窗体类型
  if ( strcmp(buf,("IEFrame"))==0 ) { // 如果窗体为IEFrame则枚举子窗口
  EnumChildWindows(hwnd,EnumChildProc,NULL); }
  return true;
  }
  // 子窗体过程函数
  BOOL CALLBACK EnumChildProc(HWND hWnd,LPARAM lParam) {
  char buf[100];
  GetClassName(hWnd,(LPTSTR)&buf,100);
  BSTR urlbuf;
  if (strcmp(buf,_T("Internet Explorer_Server"))==0) {
  IHTMLDocument2* spDoc=GetIEDocInterface(hWnd);
  if (spDoc){// 成功获得IHTMLDocument2指针
  spDoc->get_URL(&urlbuf);// 获得url地址
  char* sp=_com_util::ConvertBSTRToString(urlbuf);}
  return true;} }
  // 核心函数,用于取得IHTMLDOCUMENT2接口
  IHTMLDocument2* GetIEDocInterface(HWND hWnd) {
  IAccessible* spAccessible=NULL;
  // 从指定句柄获得Iaccessible指针
  If (S_OK==AccessibleObjectFromWindow( hWnd,
   OBJID_WINDOW,
   IID_Iaccessible,
   (void**)&spAccessible)) {
  IServiceProvider*spServiceProv=NULL;
  IHTMLWindow2* spWin=NULL;
  IHTMLDocument2* spDoc=NULL;
  HRESULT hResult;
  // 查询接口
  hResult=spAccessible->QueryInterface(IID_IServiceProvider,(void**)&spServiceProv);
  if (SUCCEEDED(hResult)) { hResult=spServiceProv->QueryService(IID_IHTMLWindow2,
   IID_IHTMLWindow2,
   (void**)&spWin);
   if (SUCCEEDED(hResult)) {
   hResult=spWin->get_document(&spDoc);
   if (SUCCEEDED(hResult)) {
   return spDoc;} } } }
  return NULL; }
  // 以下是主程序代码
  CoInitialize(NULL); // 初始化
  EnumWindows(EnumWindowsProc,0); //枚举窗口
  CoUninitialize();
  这里用到的关键头文件oleacc.和链接库oleacc.dll。
  至此我们就取得了所有标签的IHTMLDOCUMENT2接口,并且获取了相应的URL地址,接下来可以按照需要对网页内容进行相应的处理和分析。
  3.3 Gecko内核浏览器网页内容获取与分析(基于MSAA技术)
  Gecko是目前除IE外另一个比较强大的浏览器内核,基于它的Firefox目前也是十分的流行,其对MSAA也提供了支持,通过查阅Mozilla开发手册,我们得知其提供了ISimpleDOMNode、 ISimpleDOMText、、 ISimpleDOMDocument三个接口,其中的ISimpleDOMDocument类似于IE的IHTMLDOCUMENT2。
  为了调用以上三个接口,我们先从Mozilla Developer Center下载三个文件ISimpleDOMNode.idl、ISimpleDOMText.idl 、ISimpleDOMDocument.idl。这里解释一下IDL的概念: IDL(Interface Definition Language)即接口定义语言,它提供一套通用的数据类型,并以这些数据类型来定义更为复杂的数据类型。可变化 IDL 基本类型 整数类型 OMG IDL 摒弃int 类型在不同平台上取值范围不同带来的多义性的问题。常数定义常数可以是整数、字符、浮点数、字符串、Boolean、octet 或枚举型,不能是 any 类型或用户定义的类型。OMG IDL数组类型IDL array 和 sequence,可以轻易地被映射到实现语言中。序列可以包含所有类型的元素,不管是基本类型还是用户定义的类型。
  我们使用微软的IDL编译器即MIDL来生成windows平台下的头文件,命令格式如下:
  MIDLISimpleDOMNode.idl
  MIDLISimpleDOMText.idl
  MIDLISimpleDOMDocument.idl
  然后我们就得到了三个头文件ISimpleDOMNode.h、ISimpleDOMText.h、ISimpleDOMDocument.h可供我们使用,接着我们使用Spy++结构对Firefox的窗体结构进行分析,得知Firefox的顶级窗口类型为" MozillaUIWindowClass ",网页容器窗口类型为” MozillaContentWindowClass ”,实现网页获取的关键就是获取ISimpleDOMNode和ISimpleDOMDocument指针。
  下面以最新发布的Firefox3.0为例实现网页获取,大致流程与3.2相同,只需修改连个窗体函数
  // 首先定义两个接口的IID值
  const IID IID_ISimpleDOMNode = {0x1814ceeb,0x49e2,0x407f,{0xaf,0x99,0xfa,0x75,0x5a,0x7d,0x26,0x07}};
  const IID IID_ISimpleDOMDocument = {0x0D68D6D0,0xD93D,0x4d08,{0xA3,0x0D,0xF0,0x0D,0xD1,0xF4,0x5B,0x24}};
  // 窗体过程函数
  BOOLCALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam) {
  char buf[100];
  GetClassName(hwnd,(LPTSTR)&buf,100); // 获得窗体类型
 if ( strcmp(buf,(" MozillaUIWindowClass "))==0 ) { // 如果为Firefox的窗体类型则枚举子窗口
  EnumChildWindows(hwnd,EnumChildProc,NULL); }
  return true;
  }
  // 子窗体过程函数
  BOOL CALLBACK EnumChildProc(HWND hWnd,LPARAM lParam) {
  char buf[100];
  GetClassName(hWnd,(LPTSTR)&buf,100);
  BSTR urlbuf;
  if (strcmp(buf,_T("MozillaContentWindowClass"))==0) {
  ISimpleDOMDocument* spDoc=GetGeckoDocInterface(hWnd);
  if (spDoc){// 成功获得ISimpleDOMDocument指针
  spDoc->get_URL(&urlbuf); //获得url地址
  char* sp=_com_util::ConvertBSTRToString(urlbuf);}
  return true;} }
  // 核心函数,用于取得IHTMLDOCUMENT2接口
  ISimpleDOMDocument* GetGeckoDocInterface(HWND hWnd) {
  IAccessible* spAccessible=NULL;
  ISimpleDOMNode* spDOMNode=NULL;
  ISimpleDOMDocument* spDoc=NULL;
  HRESULT hResult;
  if (S_OK==AccessibleObjectFromWindow(hWnd,
   OBJID_CLIENT, // 注意,由于Firefox窗口结构的特殊性
   // 这里只能使用OBJID_CLIENT
   IID_IAccessible,
   (void**)&spAccessible))
  { hResult=spAccessible->QueryInterface(IID_ISimpleDOMNode,(void**)&spDOMNode);
  if (SUCCEEDED(hResult)) {
   hResult=spDOMNode->QueryInterface(IID_ISimpleDOMDocument,(void**)&spDoc);
   if (SUCCEEDED(hResult)) {
   return spDoc;} } }
   return NULL; }
  这里的头文件除了3.3中的外还有刚才生成的ISimpleDOMDocument.h和ISimpleDOMNode.h
  ISimpleDOMNode接口中提供了诸如get_parentNode()、get_firstChild()、get_nextSibling()等方法,可以用来对文档结构进行树状解析。
  
  4 关键技术对比
  
  1)基于COM技术:这是与windows内核紧密结合的技术,对基于IE内核的浏览器可以说一种完美的解决方案,只要其内核不发生本质性的变化,将永远奏效。不过它却有两个缺点:①由于COM技术本身的封闭性,导致只能对基于IE内核的浏览器起作用,而其他非IE浏览器则无法用这种方式访问(Gecko内核可以考虑使用XPCOM技术,这是一种开源的组件技术);②由于windows系统和许多软件都调用了IE内核,比如资源管理器、CHM帮助文档、某些Active插件等,使用这种方式将会导致可能会捕获到原本对用户来说不在计划之内的页面,对页面过滤能力提出了挑战。
  2)基于MSAA技术:这种技术其实也涉及了COM技术的成份,但是由于它的本意是实现平台无关性(类似SOA的观念),只要第三方的软件遵循相应的标准,用户就可以同样的方式访问不同的接口。但是上文获取网页内容的方式有一个缺陷:对窗口句柄的获得依赖与窗口类型,如果某些浏览器版本升级或改版后导致窗口类型变化,则需要修改原先的代码,对新的浏览器进行支持,随着各种浏览器的不断升级改进,可能会造成代码的不断扩充,导致程序臃肿不堪。
  
  5 总结
  
  讨论了windows平台下针对IE和Gecko内核的浏览器网页内容获取并对各种技术进行了比较和点评,仅起到一个抛砖引玉的作用,因为针对一项技术而言,其本身是固化的,而其带来的结果则是千变万化的。基于上文讨论的网页获取技术,我们可以想象有可能会诞生基于此的新兴技术或商业行为,也有可能带来新的隐患(如网页密码窃取)等。但技术本身是中性的,使用的方向不同则会产生截然不同的结果。
  
  参考文献:
  [1] (美)Rogerson D.Inside COM[M].Microsoft Press,1997.
  [2] (美)Mayfield C.COM/DCOM Primer Plus[M].Sams Publishing,1999.
  [3]潘爱民.COM原理与应用[M].北京:清华大学出版社,2001.
  [4] (美)理查特.Windows核心编程[M].北京:机械工业出版社,2006.
  [5]孙鑫,余安萍.VC++深入详解[M].北京:电子工业出版社,2006.
  [6] (美)Kruglinski D J. Visual C++技术内幕[M].4版.潘爱民,王国印,译.清华大学出版社,1999.
  [7]Microsoft.MSDN Library Visual Studio 6.0[EB/DK].Microsoft Developer Network,2000.
  [8]Mozilla.Accessibility:AT-APIs:ImplementationFeatures:MSAA[EB/OL]. http://developer.mozilla.org/en/docs/Accessibility:AT-APIs:ImplementationFeatures:MSAA#Additional_DOM_Support.
  [9]Klementiev D.Software Driving Software: Active Accessibility-Compliant Apps Give Programmers New Tools to Manipulate Software [EB/OL].http://msdn.microsoft.com/en-us/library/cc301312.aspx.
coding8848 2009-11-15
  • 打赏
  • 举报
回复
这篇VC的代码可能有启发意义,但是我水平菜,还是不能用delphi写出来。供各位大虾参考!!


基于IE和Gecko内核的网页内容获取与分析研究
• 分类:IT
• 作者:周 昼
• 字数:12852
来源:电脑知识与技术•学术交流 第23期

  摘要:对基于IE内核(如IE,Maxthon)与基于Gecko内核(如Firefox)的浏览器的网页内容获取与分析的技术进行了研究,采用Visual C++ 6.0为平台,基于COM技术和微软的MSAA技术,采用了多种方式实现了基于以上两类不同内核的浏览器的网页内容获取,并对这几种获取方式进行了优劣比较。
  关键词:COM; DOM; MSAA; IE; Gecko; windows编程
  中图分类号:TP393文献标识码:A文章编号:1009-3044(2008)23-936-04
  The Research of the Technique of Capturing and Analyzing the Web Page Contents Based on the Kernel of IE and Gecko
  ZHOU Zhou
  (College of Software Engineering, Beijing Jiao Tong University, Beijing 100044, China)
  Abstract: With the instant development of World Wide Web, it becomes important to capture and analyze the web page contents in order to give the customers information better arranged. This article did a research in several ways and techniques which can capture and analyze the web pages by using the Visual C++ 6.0, on the basis of COM and MSAA. At last the article compared all the techniques and listed distinctly their advantages and disadvantages.
  Key words: COM; DOM; MSAA; IE; Gecko; windows programming
  
  1 引言
  
  随着互联网的迅猛发展,如今我们面对的是一个包罗万象的网络世界,面对浩如烟海的信息,如何有效地提取网页信息成了一个十分重要的课题。如果掌握了相关的网页内容获取技术,将可以进行多方面的拓展活动,比如实时网页内容审查过滤、用户浏览行为分析、用户浏览网站的实时统计、网页自动化测试、为残疾人士浏览网页提供辅助功能。以上许多活动中都可能隐藏着很多潜在的商机。
  
  2 关键概念
  
  2.1 组件技术(COM)
  简单地说,COM是一种跨应用和语言共享二进制代码的方法。与C++不同,它提倡源代码重用。COM通过定义二进制标准解决了这些问题,即COM明确指出二进制模块(DLLs和EXEs)必须被编译成与指定的结构匹配。这个标准也确切规定了在内存中如何组织COM对象。COM定义的二进制标准还必须独立于任何编程语言(如C++中的命名修饰)。一旦满足了这些条件,就可以轻松地从任何编程语言中存取这些模块。由编译器负责所产生的二进制代码与标准兼容。这样使后来的人就能更容易地使用这些二进制代码。
  2.2 MSAA (Microsoft? Active Accessibility)
  Microsoft? Active Accessibility 是一种相对较新的技术。目的是方便身患残疾的人士使用电脑——可用于放大器、屏幕阅读器,以及触觉型鼠标。同样还可以用来开发驱动其它软件的应用程序,其模拟用户输入的能力尤其适合测试软件的开发。
  Active Accessibility 的主要思想是提供一种以程序方式访问UI元素信息或操作这些UI元素的功能。支持这种功能的 UI(User Interface) 元素是可访问的。在大多数情况下,这意味着一个UI元素支持 IAccessible 接口。你也可以说在 Active Accessibility 的世界里,一个可访问的UI元素可表示为 IAccessible 接口。每当你需要得到有关一个元素的信息,在其上执行一个动作,或者使用 Active Accessibility 做其它的什么,你通常需要通过使用代表这个元素的 IAccessible 接口的一种方法或者属性来引用这个元素。
  2.3 GUID (Globally Unique Identifier)
  GUID(全球唯一标示符——Globally Unique Identifier)是个128位的数字。它是一种独立于COM编程语言的标示方法。每一个接口和coclass有一个GUID。因为每一个GUID都是全球唯一的,所以避免了名字冲突(只要你用COM API创建它们)。有时你还会碰到另一个术语UUID(意思也是全球唯一标示符——universally unique identifier)。UUIDs和GUIDs在实际使用时的用途是一样的。
  
  3 程序实现
  
  3.1 IE内核浏览器网页内容获取与分析(基于COM技术)
  上述基于窗口遍历的技术有十分大的缺陷,无法对网页内容进行访问,而且更为严重的是,当前几乎所有的浏览器都支持标签式的浏览,如果采用上述的方法只能访问当前激活的标签。鉴于以上原因,我们采用COM技术来进行实现,这里的关键就是取得每个网页的IHTMLDocument2接口,这个接口封装了众多的方法,我们完全可以用它来进行丰富的二次开发。
  这里引入一个windows编程中的对象Shell Windows Object。通俗来说,shell就是用户和操作系统交互的一个接口,也就是接收和返回信息的一个通道;比如说windows操作系统中的explorer.exe,也就是桌面任务栏就是一个shell,如果通过任务管理器结束explorer.exe进程,桌面任务栏也就随之没有了。每一个网页就是一个Shell Windows Object,我们通过枚举所有的Shell Windows Object并试图获得其IHTEMLDocument2接口指针,如果成功说明这个Shell Windows Object是一个HTML容器,我们就可以通过其封装的方法进行操作。
  这里使用COM技术来取得所有网页的URL,具体程序如下:
  CComPtr <IShellWindows> spShellWin;// 定义智能指针
  CoInitialize(NULL);// 初始化COM库
  HRESULT hr =spShellWin.CoCreateInstance(CLSID_ShellWindows);// 根据指定CLSID创建一个未初始化的对象
  if (FAILED(hr)) return;
  long nCount=0;
  char URL[2000];
  spShellWin->get_Count(&nCount); // 获得ShellWindows对象个数
 for(long i=0; i<nCount; i++){
  CComPtr <IDispatch> spDisp;
  hr=spShellWin->Item(CComVariant(i), &spDisp );// 返回InternetExplorer 对象
  if (FAILED(hr)) continue; // 如失败则直接跳出本次循环
  CComQIPtr <IWebBrowser2> spBrowser=spDisp;// 活儿得IWebBrowser2指针
  if (!spBrowser) continue;
  spDisp.Release();
  hr = spBrowser->get_Document(&spDisp);// 返回Active Document对象
  if (FAILED(hr)) continue;
  CComQIPtr <IHTMLDocument2> spDoc=spDisp; // 获得IHTMLDOCUMENT2指针
  if (!spDoc) continue;
  BSTR pstr; // 分配BSTR空间
  spDoc->get_URL(&pstr);// 取得URL
  char* sp=_com_util::ConvertBSTRToString(pstr); }}// 转换BSTR
  以上程序所需的几个特殊头文件 atlbase.hmshtml.h、comdef.h、 exdisp.h、objbase.h
  当我们取得IHTMLDOCUMENT2指针后,除了获取URL,还可利用其他方法,如get_forms,get_links等来获得网页中的任何元素,而获得的这些元素都是以IHTMLElementCollection接口的形式返回,可以它提供的get__newEnum方法来枚举其中的每一个元素并使用相应的算法来进行分析。
  3.2 IE内核浏览器网页内容获取与分析(基于MSAA技术)
  这里我们使用MSAA技术来实现网页获取。首先解释一下有关MASS的两个问题:
  1)Active Accessibility的工作原理:Active Accessibility 的核心功能由 OLEACC.DLL 提供的。每次当你调用一个函数来返回一个 IAccessible 接口指针,其与一个UI元素相对应,OLEACC.DLL就检查此元素是否内在支持 IAccessible。内在的支持意思是该元素的 IAccessible 是用程序实现的。当一个UI元素不能内在的支持 IAccessible 时,OLEACC.DLL 检查该元素的Windows 类名。如果该类是一个 USER 或者 COMCTL32 支持的类,OLEACC.DLL 就创建一个代理为 UI 元素实现 IAccessible 接口。
  2)如何得到 IAccessible 接口指针 :每当你需要有关一个元素的信息,在其上执行一个动作,或者使用ActiveAccessibility 做其它的什么,你只需要通过使用代表这个元素的 IAccessible 接口的一种方法或者属性来引用这个元素。
  有几种方法取得代表一个可访问 UI 元素的 IAccessible 接口的指针。最普通的方法是使用 Active Accessibility 提供的一种函数,例如 AccessibleObjectFromPoint,AccessibleObjectFromWindow 等等,或者使用 IAccessible 支持的方法,例如 get_accChild,get_accParent。
  IAccessible 接口支持允许你得到各 UI 元素信息的属性,而其中对于例子程序最重要的属性是名字、角色和状态。
  下面介绍如何得到 IAccessible 接口指针。前面已经提到过 AccessibleObjectFromWindow 这个 Active Accessibility 提供的函数,从字面上大家可以看出是通过窗口来得到对应的 IAccessible 接口指针。
  因为 IAccessible 接口的数量比窗口要多(因为大多数,但不是全部,COMCTL32 控件都有被 OLEACC.DLL 支持的 IAccessible 接口。),使用 Win32 函数来搜索一个窗口将会比使用 Active Accessibility 树搜索与该窗口相应的 IAccessible 接口要占用少得多的时间。这就意味着为了提高性能,你应该使用 FindWindow 和 EnumWindows 这样的 Win32 函数来找到与希望的UI元素最接近的窗口。当然,在权衡 Win32 函数和 Active Accessibility 函数时,上面的规则只是使用它们的一般标准而不能盲目的遵照执行,重要的是理解它们的本来意义。
  下面对上面涉及到的几个重要的函数进行解释:
  // 此函数用于从窗口句柄获得指定的接口或对象
  STDAPIAccessibleObjectFromWindow(
  HWND hwnd,
  DWORD dwId,
  REFIID riid,
  void **ppvObject
  );
  //此函数枚举所有的窗口并对每一个窗口应用lpEnumFunc所指想的回调函数
  //在此处我们使用它寻找所有基于IE内核的浏览器窗口
  BOOLEnumWindows(
  WNDENUMPROC lpEnumFunc,// pointer to callback function
  LPARAM lParam// application-defined value
  );
  //此函数枚举某个父窗口的所有子窗口并对每一个子窗口应用lpEnumFunc所指想的回调函数
  //在此处我们使用它寻找所有基于IE内核的浏览器窗口中的每一个标签窗口
  BOOL EnumChildWindows(
  HWND hWndParent,// handle to parent window
  WNDENUMPROC lpEnumFunc,// pointer to callback function
  LPARAM lParam// application-defined value
  );
 

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧