Delphi通过MSHTML实现一个HTML解析类

简介:

最近经常会模拟网页提交返回网页源码,然后获得网页中相应的元素,于是需要常常解析Html中相应的各种元素,网络是个好东西,搜索一番,就找到了好几个Delphi版本的HtmlParser的类库,试着使用了几个,发现解析起来都不完整,或多或少的回出现一些问题!于是想到了如果界面上有一个浏览器,我们可以通过WebBrowser的Document接口对网页元素进行操作,很是方便!但是模拟网页提交,界面上是不一定要出现WebBrowser的,肯定有办法,不通过WebBrowser就直接解析HTML的,那便是我不要WebBrowser这个外壳,只要他里面的Document文档接口对象就能实现对Html的解析了,查找了一番MSDN,然后Google一下,果然可行,构建方法如下:

//创建IHTMLDocument2接口
  CoCreateInstance(CLASS_HTMLDocument, nil, CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, FHtmlDoc);

接口创建好了之后就能够对文档元素进行解析了,很是爽快!

结合了我自己的特有操作,我对Combobox,Table,Frame等一些网页元素做了相应的封装,实现了一个HTMLParser,大致代码如下:

这里只给出声明,代码请在最后下载 

复制代码
代码
(* **************************************************** *)
(*                 得闲工作室                           *)
(*               网页元素操作类库                       *)
(*                                                      *)
(*               DxHtmlElement Unit                     *)
(*     Copyright(c) 2008-2010  不得闲                   *)
(*     email:appleak46@yahoo.com.cn     QQ:75492895     *)
(* **************************************************** *)
unit  DxHtmlElement;

interface
uses  Windows,sysUtils,Clipbrd,MSHTML,ActiveX,OleCtrls,Graphics,TypInfo;

{ Get EleMent Type }
function  IsSelectElement(eleElement: IHTMLElement): Boolean;
function  IsPwdElement(eleElement: IHTMLElement): Boolean;
function  IsTextElement(element: IHTMLElement): boolean;
function  IsTableElement(element: IHTMLElement): Boolean;
function  IsElementCollection(element: IHTMLElement): Boolean;
function  IsChkElement(element: IHTMLElement): boolean;
function  IsRadioBtnElement(element: IHTMLElement): boolean;
function  IsMemoElement(element: IHTMLElement): boolean;
function  IsFormElement(element: IHTMLElement): boolean;
function  IsIMGElement(element: IHTMLElement): boolean;
function  IsInIMGElement(element: IHTMLElement): boolean;
function  IsLabelElement(element: IHTMLElement): boolean;
function  IsLinkElement(element: IHTMLElement): boolean;
function  IsListElement(element: IHTMLElement): boolean;
function  IsControlElement(element: IHTMLElement): boolean;
function  IsObjectElement(element: IHTMLElement): boolean;
function  IsFrameElement(element: IHTMLElement): boolean;
function  IsInPutBtnElement(element: IHTMLElement): boolean;
function  IsInHiddenElement(element: IHTMLElement): boolean;
function  IsSubmitElement(element: IHTMLElement): boolean;
{ Get ImgElement Data }
function  GetPicIndex(doc: IHTMLDocument2; Src:  string ; Alt:  string ): Integer;
function  GetPicElement(doc: IHTMLDocument2;imgName:  string ;src:  string ;Alt:  string ): IHTMLImgElement;
function  GetRegCodePic(doc: IHTMLDocument2;ImgName:  string ; Src:  string ; Alt:  string ): TPicture;  overload ;
function  GetRegCodePic(doc: IHTMLDocument2;Index: integer): TPicture;  overload ;
function  GetRegCodePic(doc: IHTMLDocument2;element: IHTMLIMGElement): TPicture; overload ;

type
  TObjectFromLResult 
=   function (LRESULT: lResult; const  IID: TIID; WPARAM: wParam; out  pObject): HRESULT;  stdcall ;
  TEleMentType 
=  (ELE_UNKNOW,ELE_TEXT,ELE_PWD,ELE_SELECT,ELE_CHECKBOX,ELE_RADIOBTN,ELE_MEMO,ELE_FORM,ELE_IMAGE,
  ELE_LABEL,ELE_LINK,ELE_LIST,ELE_CONTROL,ELE_OBJECT,ELE_FRAME,ELE_INPUTBTN,ELE_INIMAGE,ELE_INHIDDEN);


function  GetElementType(element: IHTMLELEMENT): TEleMentType;
function  GetElementTypeName(element: IHTMLELEMENT):  string ;
function  GetHtmlTableCell(aTable: IHTMLTable;aRow,aCol: Integer): IHTMLElement;
function  GetHtmlTable(aDoc: IHTMLDocument2; aIndex: Integer): IHTMLTable;
function  GetWebBrowserHtmlTableCellText(Doc: IHTMLDocument2;
         
const  TableIndex, RowIndex, ColIndex: Integer; var  ResValue:  string ):   Boolean;
function  GetHtmlTableRowHtml(aTable: IHTMLTable; aRow: Integer): IHTMLElement;

function  GetWebBrowserHtmlTableCellHtml(Doc: IHTMLDocument2;
         
const  TableIndex,RowIndex,ColIndex: Integer; var  ResValue:  string ):   Boolean;
function  GeHtmlTableHtml(aTable: IHTMLTable; aRow: Integer): IHTMLElement;
function  GetWebBrowserHtmlTableHtml(Doc: IHTMLDocument2;
         
const  TableIndex,RowIndex: Integer; var  ResValue:  string ):   Boolean;

type
  TDxWebFrameCollection 
=   class ;
  TDxWebElementCollection 
=   class ;

 
  TLoadState 
=  (Doc_Loading,Doc_Completed,Doc_Invalidate);

  TDxWebFrame 
=   class
  
private
    FFrame: IHTMLWINDOW2;
    FElementCollections: TDxWebElementCollection;
    FWebFrameCollections: TDxWebFrameCollection;
    
function  GetSrc:  string ;
    
function  GetElementCount: integer;
    
function  GetWebFrameCollections: TDxWebFrameCollection;
    
function  GetElementCollections: TDxWebElementCollection;
    
function  GetDocument: IHTMLDOCUMENT2;
    
function  GetReadState: TLoadState;
    
function  GetIsLoaded: boolean;
    
procedure  SetFrame( const  Value: IHTMLWINDOW2);
    
function  GetName:  string ;
  
public
    Constructor Create(IFrame: IHTMLWINDOW2);
    Destructor Destroy;
override ;
    
property  Frame: IHTMLWINDOW2  read  FFrame  write  SetFrame;
    
property  Src:  string   read  GetSrc;
    
property  Document: IHTMLDOCUMENT2  read  GetDocument;
    
property  Name:  string   read  GetName;
    
property  Frames: TDxWebFrameCollection  read  GetWebFrameCollections;
    
property  ElementCount: integer  read  GetElementCount;
    
property  ElementCollections: TDxWebElementCollection  read  GetElementCollections;
    
property  ReadyState: TLoadState  read  GetReadState;
    
property  IsLoaded: boolean  read  GetIsLoaded;  
  
end ;


  TDxWebFrameCollection 
=  Class
  
private
    FFrameCollection: IHTMLFramesCollection2;
    Frame: TDxWebFrame;
    
function  GetCount: integer;
    
function  GetFrameInterfaceByIndex(index: integer): IHTMLWINDOW2;
    
function  GetFrameInterfaceByName(Name:  string ): IHTMLWINDOW2;
    
function  GetFrameByIndex(index: integer): TDxWebFrame;
    
function  GetFrameByName(Name:  string ): TDxWebFrame;
    
procedure  SetFrameCollection( const  Value: IHTMLFramesCollection2);
  
public
    Constructor Create(ACollection: IHTMLFramesCollection2);
    Destructor Destroy;
override ;
    
property  FrameCollection: IHTMLFramesCollection2  read  FFrameCollection  write  SetFrameCollection;
    
property  Count: integer  read  GetCount;
    
property  FrameInterfaceByIndex[index: integer]: IHTMLWINDOW2  read  GetFrameInterfaceByIndex;
    
property  FrameInterfaceByName[Name:  string ]: IHTMLWINDOW2  read  GetFrameInterfaceByName;

    
property  FrameByIndex[index: integer]: TDxWebFrame  read  GetFrameByIndex;
    
property  FrameByName[Name:  string ]: TDxWebFrame  read  GetFrameByName;
  
end ;
  
  TDxWebElementCollection 
=   class
  
private
    FCollection: IHTMLElementCollection;
    FChildCollection:  TDxWebElementCollection;
    
function  GetCollection(index: String): TDxWebElementCollection;
    
function  GetCount: integer;
    
function  GetElement(itemName:  string ; index: integer): IHTMLElement;
    
function  GetElementByName(itemName:  string ): IHTMLELEMENT;
    
function  GetElementByIndex(index: integer): IHTMLELEMENT;
    
procedure  SetCollection( const  Value: IHTMLElementCollection);
  
public
    Constructor Create(ACollection: IHTMLElementCollection);
    Destructor Destroy;
override ;
    
property  Collection: IHTMLElementCollection  read  FCollection  write  SetCollection;
    
property  ChildElementCollection[index: String]: TDxWebElementCollection  read  GetCollection;
    
property  ElementCount: integer  read  GetCount;
    
property  Element[itemName:  string ;index: integer]: IHTMLElement  read  GetElement;
    
property  ElementByName[itemName:  string ]: IHTMLELEMENT  read  GetElementByName;
    
property  ElementByIndex[index: integer]: IHTMLELEMENT  read  GetElementByIndex;
  
end ;

  TLinkCollection 
=   class (TDxWebElementCollection)
  
  
end ;
  TDxWebTable 
=   class ;

  TDxTableCollection 
=   class
  
private
    FTableCollection: IHTMLElementCollection;
    FDocument: IHTMLDOCUMENT2;
    FWebTable: TDxWebTable;
    
function  GetTableInterfaceByName(AName:  string ): IHTMLTABLE;
    
procedure  SetDocument(Value: IHTMLDOCUMENT2);
    
function  GetTableInterfaceByIndex(index: integer): IHTMLTABLE;
    
function  GetCount: integer;
    
function  GetTableByIndex(index: integer): TDxWebTable;
    
function  GetTableByName(AName:  string ): TDxWebTable;
  
public
    Constructor Create(Doc: IHTMLDOCUMENT2);
    
destructor  Destroy; override ;
    
property  TableInterfaceByName[AName:  string ]: IHTMLTABLE  read  GetTableInterfaceByName;
    
property  TableInterfaceByIndex[index: integer]: IHTMLTABLE  read  GetTableInterfaceByIndex;

    
property  TableByName[AName:  string ]: TDxWebTable  read  GetTableByName;
    
property  TableByIndex[index: integer]: TDxWebTable  read  GetTableByIndex;
    
    
property  Document: IHTMLDOCUMENT2  read  FDocument  write  SetDocument;
    
property  Count: integer  read  GetCount;
  
end ;

  TDxWebTable 
=   class
  
private
    FTableInterface: IHTMLTABLE;
    
function  GetRowCount: integer;
    
procedure  SetTableInterface( const  Value: IHTMLTABLE);
    
function  GetCell(ACol, ARow: integer):  string ;
    
function  GetRowColCount(RowIndex: integer): integer;
    
function  GetInnerHtml:  string ;
    
function  GetInnerText:  string ;
    
function  GetCellElement(ACol, ARow: Integer): IHTMLTableCell;
  
public
    Constructor Create(ATable: IHTMLTABLE);
    
property  TableInterface: IHTMLTABLE  read  FTableInterface  write  SetTableInterface;
    
property  RowCount: integer  read  GetRowCount;
    
property  Cell[ACol: integer;ARow: integer]:  string   read  GetCell;
    
property  CellElement[ACol: Integer;ARow: Integer]: IHTMLTableCell  read  GetCellElement;
    
property  RowColCount[RowIndex: integer]: integer  read  GetRowColCount;
    
property  InnerHtml:  string   read  GetInnerHtml;
    
property  InnerText:  string   read  GetInnerText;
  
end ;

  TDxWebCombobox 
=   class
  
private
    FHtmlSelect: IHTMLSelectElement;
    
function  GetCount: Integer;
    
procedure  SetItemIndex( const  Value: Integer);
    
function  GetItemIndex: Integer;
    
function  GetName:  string ;
    
procedure  SetName( const  Value:  string );
    
function  GetValue:  string ;
    
procedure  SetValue( const  Value:  string );
    
procedure  SetCombInterface( const  Value: IHTMLSelectElement);
    
function  GetItemByName(EleName:  string ):  string ;
    
function  GetItemByIndex(index: integer):  string ;
    
function  GetItemAttribute(index: Integer; AttribName:  string ): OleVariant;
  
public
    
constructor  Create(AWebCombo: IHTMLSelectElement);
    
procedure  Add(Ele: IHTMLElement);
    
procedure  Insert(Ele: IHTMLElement;Index: Integer);
    
procedure  Remove(index: Integer);

    
property  CombInterface: IHTMLSelectElement  read  FHtmlSelect  write  SetCombInterface;
    
property  Count: Integer  read  GetCount;
    
property  ItemIndex: Integer  read  GetItemIndex  write  SetItemIndex;
    
property  ItemByIndex[index: integer]:  string   read  GetItemByIndex;
    
property  ItemByName[EleName:  string ]:  string   read  GetItemByName;
    
property  ItemAttribute[index: Integer;AttribName:  string ]: OleVariant  read  GetItemAttribute;
    
property  Name:  string   read  GetName  write  SetName;
    
property  value:  string   read  GetValue  write  SetValue;
  
end ;

implementation
end .
复制代码


 HTMLParser解析类的代码实现单元

复制代码
代码
(* **************************************************** *)
(*                 得闲工作室                           *)
(*               HTML解析单元库                         *)
(*                                                      *)
(*               DxHtmlParser Unit                      *)
(*     Copyright(c) 2008-2010  不得闲                   *)
(*     email:appleak46@yahoo.com.cn     QQ:75492895     *)
(* **************************************************** *)
unit  DxHtmlParser;

interface
uses  Windows,MSHTML,ActiveX,DxHtmlElement,Forms;

type
  TDxHtmlParser 
=   class
  
private
    FHtmlDoc: IHTMLDocument2;
    FHTML: 
string ;
    FWebTables: TDxTableCollection;
    FWebElements: TDxWebElementCollection;
    FWebComb: TDxWebCombobox;
    
procedure  SetHTML( const  Value:  string );
    
function  GetWebCombobox(AName:  string ): TDxWebCombobox;
  
public
    
constructor  Create;
    
destructor  Destroy; override ;
    
property  HTML:  string   read  FHTML  write  SetHTML;
    
property  WebTables: TDxTableCollection  read  FWebTables;
    
property  WebElements: TDxWebElementCollection  read  FWebElements;
    
property  WebCombobox[Name:  string ]: TDxWebCombobox  read  GetWebCombobox;
  
end ;
implementation

{  TDxHtmlParser  }

constructor  TDxHtmlParser.Create;
begin
  CoInitialize(
nil );
  
// 创建IHTMLDocument2接口
  CoCreateInstance(CLASS_HTMLDocument, 
nil , CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, FHtmlDoc);
  Assert(FHtmlDoc
<> nil , ' 构建HTMLDocument接口失败 ' );
  FHtmlDoc.Set_designMode(
' On ' );  // 设置为设计模式,不执行脚本
  
while   not  (FHtmlDoc.readyState  =   ' complete ' do
  
begin
    sleep(
1 );
    Application.ProcessMessages;
  
end ;                   
  FWebTables :
=  TDxTableCollection.Create(FHtmlDoc);
  FWebElements :
=  TDxWebElementCollection.Create( nil );
  FWebComb :
=  TDxWebCombobox.Create( nil );
end ;

destructor  TDxHtmlParser.Destroy;
begin
  FWebTables.Free;
  FWebElements.Free;
  FWebComb.Free;
  CoUninitialize;
  
inherited ;
end ;

function  TDxHtmlParser.GetWebCombobox(AName:  string ): TDxWebCombobox;
begin
   
if  FWebElements.Collection  <>   nil   then
   
begin
     FWebComb.CombInterface :
=  FWebElements.ElementByName[AName]  as  IHTMLSelectElement;
     Result :
=  FWebComb;
   
end
   
else  Result : =   nil ;
end ;

procedure  TDxHtmlParser.SetHTML( const  Value:  string );
begin
  
if  FHTML  <>  Value  then
  
begin
    FHTML :
=  Value;
    FHtmlDoc.body.innerHTML :
=  FHTML;
    FWebElements.Collection :
=  FHtmlDoc.all;
  
end ;
end ;

end .
复制代码
相关文章
|
5月前
|
XML 前端开发 C#
C#编程实践:解析HTML文档并执行元素匹配
通过上述步骤,可以在C#中有效地解析HTML文档并执行元素匹配。HtmlAgilityPack提供了一个强大而灵活的工具集,可以处理各种HTML解析任务。
315 19
|
11月前
|
Java 开发者
重学Java基础篇—Java类加载顺序深度解析
本文全面解析Java类的生命周期与加载顺序,涵盖从加载到卸载的七个阶段,并深入探讨初始化阶段的执行规则。通过单类、继承体系的实例分析,明确静态与实例初始化的顺序。同时,列举六种触发初始化的场景及特殊场景处理(如接口初始化)。提供类加载完整流程图与记忆口诀,助于理解复杂初始化逻辑。此外,针对空指针异常等问题提出排查方案,并给出最佳实践建议,帮助开发者优化程序设计、定位BUG及理解框架机制。最后扩展讲解类加载器层次与双亲委派机制,为深入研究奠定基础。
446 0
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
数据可视化 数据挖掘 BI
团队管理者必读:高效看板类协同软件的功能解析
在现代职场中,团队协作的效率直接影响项目成败。看板类协同软件通过可视化界面,帮助团队清晰规划任务、追踪进度,提高协作效率。本文介绍看板类软件的优势,并推荐五款优质工具:板栗看板、Trello、Monday.com、ClickUp 和 Asana,助力团队实现高效管理。
344 2
|
12月前
|
数据采集 存储 调度
BeautifulSoup VS Scrapy:如何选择适合的HTML解析工具?
在Python网页抓取领域,BeautifulSoup和Scrapy是两款备受推崇的工具。BeautifulSoup易于上手、灵活性高,适合初学者和简单任务;Scrapy则是一个高效的爬虫框架,内置请求调度、数据存储等功能,适合大规模数据抓取和复杂逻辑处理。两者结合使用可以发挥各自优势,例如用Scrapy进行请求调度,用BeautifulSoup解析HTML。示例代码展示了如何在Scrapy中设置代理IP、User-Agent和Cookies,并使用BeautifulSoup解析响应内容。选择工具应根据项目需求,简单任务选BeautifulSoup,复杂任务选Scrapy。
330 1
BeautifulSoup VS Scrapy:如何选择适合的HTML解析工具?
|
11月前
|
存储 监控 安全
重学Java基础篇—类的生命周期深度解析
本文全面解析了Java类的生命周期,涵盖加载、验证、准备、解析、初始化、使用及卸载七个关键阶段。通过分阶段执行机制详解(如加载阶段的触发条件与技术实现),结合方法调用机制、内存回收保护等使用阶段特性,以及卸载条件和特殊场景处理,帮助开发者深入理解JVM运作原理。同时,文章探讨了性能优化建议、典型异常处理及新一代JVM特性(如元空间与模块化系统)。总结中强调安全优先、延迟加载与动态扩展的设计思想,并提供开发建议与进阶方向,助力解决性能调优、内存泄漏排查及框架设计等问题。
500 5
|
11月前
|
安全 IDE Java
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
354 1
|
Java 数据库 开发者
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
1551 12
|
11月前
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
465 5
|
11月前
|
机器学习/深度学习 人工智能 监控
鸿蒙赋能智慧物流:AI类目标签技术深度解析与实践
在数字化浪潮下,物流行业面临变革,传统模式的局限性凸显。AI技术为物流转型升级注入动力。本文聚焦HarmonyOS NEXT API 12及以上版本,探讨如何利用AI类目标签技术提升智慧物流效率、准确性和成本控制。通过高效数据处理、实时监控和动态调整,AI技术显著优于传统方式。鸿蒙系统的分布式软总线技术和隐私保护机制为智慧物流提供了坚实基础。从仓储管理到运输监控再到配送优化,AI类目标签技术助力物流全流程智能化,提高客户满意度并降低成本。开发者可借助深度学习框架和鸿蒙系统特性,开发创新应用,推动物流行业智能化升级。
392 1

推荐镜像

更多
  • DNS