0

どのフォームと要素が属しているかを調べようとしています。私がこのウェブサイトから理解しているコード:

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

このコードを含む

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;

ほとんどのサイトで問題なく動作しているようです。ただし、次のような Web サイトがいくつかあります。

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

そのコードを見て、アクティブな ID と比較すると、フォームを見つけることができます。ただし、その Web サイトでは機能しません。何らかの理由で、このコードがhtmldocument2用であることはhtmldocument3と関係があると思います。しかし、よくわかりません。

だから私の質問は、このWebサイトからすべての要素名を含むtstringlistを抽出するにはどうすればよいですか? あなたが助けてくれることを願っています!

編集:いくつかのコードを追加

              begin

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

2 に答える 2

1

Web ページにフォーム要素を配置する際の複雑な点の 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;

フレームセットをナビゲートするCryer の例は、すべての Web サイトで機能するとは限りません。 http://support.microsoft.com/support/kb/articles/Q196/3/40.ASPを参照してください。次の関数は、私が試したすべてのサイトでフレームを 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.Webページにフォームが1つしかない場合、フォーム要素のリストは決して抽出されません.2.「theid」のタグが見つからない限り、繰り返しループはアクセス違反になります.

フォーム要素を正常に抽出するために切り取られた例を次に示します。

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;
于 2011-03-12T03:16:05.367 に答える
0

うーん、このリンクにはフォーム要素が含まれていますか? 少なくとも目に見えるものは見当たりませんでした。おそらくそれらは隠されています-しかし、これを自分でチェックしませんでした.

マイケル

于 2011-03-11T11:31:09.043 に答える