天天看點

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,大緻代碼如下:

這裡隻給出聲明,代碼請在最後下載下傳 

<a></a>

代碼

(******************************************************)

(*                得閑工作室                          *)

(*              網頁元素操作類庫                      *)

(*                                                    *)

(*              DxHtmlElement Unit                    *)

(*    Copyright(c) 2008-2010  不得閑                  *)

(*    email:[email protected]     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;

  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

    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);

    Constructor Create(ACollection: IHTMLFramesCollection2);

    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;

  TDxWebElementCollection = class

    FCollection: IHTMLElementCollection;

    FChildCollection:  TDxWebElementCollection;

    function GetCollection(index: String): TDxWebElementCollection;

    function GetElement(itemName: string; index: integer): IHTMLElement;

    function GetElementByName(itemName: string): IHTMLELEMENT;

    function GetElementByIndex(index: integer): IHTMLELEMENT;

    procedure SetCollection(const Value: IHTMLElementCollection);

    Constructor Create(ACollection: IHTMLElementCollection);

    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;

  TLinkCollection = class(TDxWebElementCollection)

  TDxWebTable = class;

  TDxTableCollection = class

    FTableCollection: IHTMLElementCollection;

    FDocument: IHTMLDOCUMENT2;

    FWebTable: TDxWebTable;

    function GetTableInterfaceByName(AName: string): IHTMLTABLE;

    procedure SetDocument(Value: IHTMLDOCUMENT2);

    function GetTableInterfaceByIndex(index: integer): IHTMLTABLE;

    function GetTableByIndex(index: integer): TDxWebTable;

    function GetTableByName(AName: string): TDxWebTable;

    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;

  TDxWebTable = class

    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;

    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;

  TDxWebCombobox = class

    FHtmlSelect: IHTMLSelectElement;

    function GetCount: Integer;

    procedure SetItemIndex(const Value: Integer);

    function GetItemIndex: Integer;

    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;

    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;

implementation

end.

 HTMLParser解析類的代碼實作單元

(*              HTML解析單元庫                        *)

(*              DxHtmlParser Unit                     *)

unit DxHtmlParser;

uses Windows,MSHTML,ActiveX,DxHtmlElement,Forms;

  TDxHtmlParser = class

    FHtmlDoc: IHTMLDocument2;

    FHTML: string;

    FWebTables: TDxTableCollection;

    FWebElements: TDxWebElementCollection;

    FWebComb: TDxWebCombobox;

    procedure SetHTML(const Value: string);

    function GetWebCombobox(AName: string): TDxWebCombobox;

    constructor Create;

    property HTML: string read FHTML write SetHTML;

    property WebTables: TDxTableCollection read FWebTables;

    property WebElements: TDxWebElementCollection read FWebElements;

    property WebCombobox[Name: string]: TDxWebCombobox read GetWebCombobox;

{ TDxHtmlParser }

constructor TDxHtmlParser.Create;

begin

  CoInitialize(nil);

  //建立IHTMLDocument2接口

  CoCreateInstance(CLASS_HTMLDocument, nil, CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, FHtmlDoc);

  Assert(FHtmlDoc&lt;&gt;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;

  FWebTables.Free;

  FWebElements.Free;

  FWebComb.Free;

  CoUninitialize;

  inherited;

function TDxHtmlParser.GetWebCombobox(AName: string): TDxWebCombobox;

   if FWebElements.Collection &lt;&gt; nil then

   begin

     FWebComb.CombInterface := FWebElements.ElementByName[AName] as IHTMLSelectElement;

     Result := FWebComb;

   end

   else Result := nil;

procedure TDxHtmlParser.SetHTML(const Value: string);

  if FHTML &lt;&gt; Value then

    FHTML := Value;

    FHtmlDoc.body.innerHTML := FHTML;

    FWebElements.Collection := FHtmlDoc.all;

繼續閱讀