2011-03-11 30 views
0

我想找出哪些表單和元素也屬於。我現在從這個網站了解代碼:包含此代碼GetFormFieldNames不總是工作

function GetFormFieldNames(fromForm: IHTMLFormElement): TStringList; 
var 
    index: integer; 
    field: IHTMLElement; 
    input: IHTMLInputElement; 
    select: IHTMLSelectElement; 
    text: IHTMLTextAreaElement; 
begin 
    result := TStringList.Create; 
    for index := 0 to fromForm.length do 
    begin 
    field := fromForm.Item(index,'') as IHTMLElement; 
    if Assigned(field) then 
    begin 
     if field.tagName = 'INPUT' then 
     begin 
     // Input field. 
     input := field as IHTMLInputElement; 
     result.Add(input.name); 
     end 
     else if field.tagName = 'SELECT' then 
     begin 
     // Select field. 
     select := field as IHTMLSelectElement; 
     result.Add(select.name); 
     end 
     else if field.tagName = 'TEXTAREA' then 
     begin 
     // TextArea field. 
     text := field as IHTMLTextAreaElement; 
     result.Add(text.name); 
     end; 
    end; 
    end; 

end; 

http://www.cryer.co.uk/brian/delphi/twebbrowser/read_write_form_elements.htm

似乎是工作的罰款大多數網站。但是也有一些網站,如這一個:

http://service.mail.com/registration.html#.1258-bluestripe-product1-undef

通過查看代碼,並將其與活動的ID進行比較,我可以找到它是形式。然而它並沒有針對該網站的工作。 。出於某種原因,我認爲它與htmldocument3和這個代碼是用於htmldocument2。但我不確定。

所以我的問題是如何從這個網站提取一個tstringlist與他們所有的元素名稱?希望你能幫助!

編輯:添加一些代碼

   begin 

       theForm := GetFormByNumber(webbrowser1.document as IHTMLDocument2, 
        0); 
       fields := GetFormFieldNames(theForm); 
       num := fields.IndexOf(theid); 
       end; 
       until (num <> -1); 

回答

0

嗯,你確定這個鏈接包含任何形式的元素嗎?至少我沒有看到任何可見的。也許他們是隱藏的 - 但是,我自己沒有檢查過。

邁克爾

+0

是啊,是不是輸入字段的表單元素呢? – dave123 2011-03-11 11:50:16

1

一個與在網頁中定位表單元素複雜的是,網頁可能包含幀和可能存在的形式中的任何幀。基本上,你必須遍歷每一幀中的所有幀和表單。將表單作爲IHTMLFormElement獲取後,使用Cryer的函數獲取表單元素名稱。

您給出的示例鏈接沒有任何框架,您應該沒有問題獲取表單元素列表,除非您嘗試通過名稱獲取表單,因爲它沒有分配名稱。我沒有問題,使用以下步驟

procedure GetForms(doc1: IHTMLDocument2; var sl: TStringList); 
var 
    i, j, n: integer; 
    docForm: IHTMLFormElement; 
    slt: TStringList; 
    s: string; 
begin 
    if doc1 = nil then 
    begin 
    ShowMessage('doc1 is empty [GetForms]'); 
    Exit; 
    end; 
    slt := TStringList.Create; 

    n := NumberOfForms(doc1); 
    sl.Add('Forms: ' + IntToStr(n)); 
    for i := 0 to n - 1 do 
    begin 
    docForm := GetFormByNumber(doc1, i); 
    sl.Add('Form Name: ' + docForm.Name); 
    slt.Clear; 
    slt := GetFormFieldNames(docForm); 
    for j := 0 to slt.Count - 1 do 
    begin 
     s := GetFieldValue(docForm, slt[j]); 
     sl.Add('Field Name: ' + slt[j] + ' value: "' + s + '"'); 
    end; 
    end; 
    sl.Add(''); 
    slt.Free; 
end; 

克萊爾的例子爲navigating a frameset不會爲所有網站的工作得到表單元素的名稱和值,請參閱http://support.microsoft.com/support/kb/articles/Q196/3/40.ASP。下面的函數successfuly提取作爲的IHTMLDocument2上的所有網站我已盡力

function GetFrameByNumber(Doc:IHTMLDocument2; n:integer):IHTMLDocument2; 
var 
    Container: IOleContainer; 
    Enumerator: ActiveX.IEnumUnknown; 
    Unknown: IUnknown; 
    Browser: IWebBrowser2; 
    Fetched: Longint; 
    NewDoc: IHTMLDocument2; 
    i : integer; 
begin 
    // We cannot use the document's frames collection here, because 
    // it does not work in every case (i.e. Documents from a foreign domain). 
    // From: http://support.microsoft.com/support/kb/articles/Q196/3/40.ASP 
    i := 0; 
    if (Supports(Doc, IOleContainer, Container)) and 
    (Container.EnumObjects(OLECONTF_EMBEDDINGS, Enumerator) = S_OK) then 
    begin 
    while Enumerator.Next(1, Unknown, @Fetched) = S_OK do 
    begin 
     if (Supports(Unknown, IWebBrowser2, Browser)) and 
     (Supports(Browser.Document, IHTMLDocument2, NewDoc)) then 
     begin 
     // Here, NewDoc is an IHTMLDocument2 that you can query for 
     // all the links, text edits, etc. 
     if i=n then 
     begin 
      Result := NewDoc; 
      Exit; 
     end; 
     i := i+1; 
     end; 
    end; 
    end; 
end; 

下面是我用GetForms的例子,GetFrameByNumber

// from the TForm1 declaration 
    { Public declarations } 
    wdoc: IHTMLDocument2; 


procedure TForm1.btnAnalyzeClick(Sender: TObject); 
begin 
    wdoc := WebBrowser.Document as IHTMLDocument2; 
    GetDoc(wdoc); 
end; 

procedure TForm1.GetDoc(doc1: IHTMLDocument2); 
var 
    i, n: integer; 
    doc2: IHTMLDocument2; 
    frame_dispatch: IDispatch; 
    frame_win: IHTMLWindow2; 
    ole_index: olevariant; 
    sl: TStringList; 
begin 
    if doc1 = nil then 
    begin 
    ShowMessage('Web doc is empty'); 
    Exit; 
    end; 
    Form2.Memo1.Lines.Clear; 
    sl := TStringList.Create; 

    n := doc1.frames.length; 
    sl.Add('Frames: ' + IntToStr(n)); 
    // check each frame for the data 
    if n = 0 then 
    GetForms(doc1, sl) 
    else 
    for i := 0 to n - 1 do 
    begin 
     sl.Add('--Frame: ' + IntToStr(i)); 
     ole_index := i; 
     frame_dispatch := doc1.Frames.Item(ole_index); 
     if frame_dispatch <> nil then 
     begin 
     frame_win := frame_dispatch as IHTMLWindow2; 
     doc2 := frame_win.document; 
//  sl.Add(doc2.body.outerHTML); 
     GetForms(doc2,sl); 
     GetDoc(doc2); 
     end; 
    end; 

// Form2 just contains a TMemo 
    Form2.Memo1.Lines.AddStrings(sl); 
    Form2.Show; 
    sl.Free; 
end; 

在你的榜樣的邏輯是錯誤的框架, 1.當網頁上只有一個表單時,表單元素的列表永遠不會被提取,2.重複循環會導致訪問衝突,除非找到「theid」中的標籤

這是您的示例削減成功提取fo元素。

var 
    i : integer; 
    nforms : integer; 
    document : IHTMLDocument2; 
    theForm : IHTMLFormElement; 
    fields : TStringList; 
    theform1 : integer; 
    num : integer; 
    theid : string; 
begin 
    fields := TStringList.Create; 
    theid := 'xx'; 

// original code follows 
i := -1; 
// nforms := NumberOfForms(webbrowser1.document as IHTMLDocument2); 
// document := webbrowser1.document as IHTMLDocument2; 
// if nforms = 1 then 
// begin 
//  theForm := GetFormByNumber(webbrowser1.document as IHTMLDocument2, 0); 
//  theform1 := 0; 
// end 
// else 
    begin 
//    repeat 
       begin 
       inc(i); 
       theForm := GetFormByNumber(webbrowser1.document as IHTMLDocument2, 
        i); 
       fields := GetFormFieldNames(theForm); 
       num := fields.IndexOf(theid); 
       theform1 := i; 
       end; 
//    until (num <> -1); 
    end; 
// end of original code 

    Memo1.Lines.Text := fields.Text; 
    fields.Free; 
end; 
+0

thx的帖子,但我似乎還沒有完全理解。我不按姓名搜索表格,而是按數字搜索。我爲這個問題添加了一些代碼,看看它是否對你更有意義。請看一看。thx – dave123 2011-03-12 09:50:23

+0

而且很抱歉,但我如何調用過程GetForms? GetForms(webbrowser1.document作爲IHTMLDocument2,Tstringlist)? – dave123 2011-03-12 10:00:19

+0

查看我添加的示例。你沒有在你的例子中包含「我」的初始值。表單集合是基於零的,所以如果「i」被初始化爲零,那麼你會錯過第一個表單。 – crefird 2011-03-12 14:22:05