Delphi GetFormFieldNames不总是工作
我试图找出哪种形式和元素也属于。我现在从本网站了解的代码: 包含此代码的Delphi GetFormFieldNames不总是工作,delphi,browser,ihtmldocument2,Delphi,Browser,Ihtmldocument2,我试图找出哪种形式和元素也属于。我现在从本网站了解的代码: 包含此代码的 function GetFormFieldNames(fromForm: IHTMLFormElement): TStringList; var index: integer; field: IHTMLElement; input: IHTMLInputElement; select: IHTMLSelectElement; text: IHTMLTextAreaElement; begin re
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;
似乎在大多数网站上都能正常工作。但是,也有一些网站,比如:
通过查看该代码并将其与活动id进行比较,我可以找到它所在的表单。但是,它不适用于该网站。出于某种原因,我认为这与htmldocument3和htmldocument2有关。但我不确定
所以我的问题是如何从这个网站中提取一个包含所有元素名称的tstringlist?希望你能帮忙
编辑:添加了一些代码
begin
theForm := GetFormByNumber(webbrowser1.document as IHTMLDocument2,
0);
fields := GetFormFieldNames(theForm);
num := fields.IndexOf(theid);
end;
until (num <> -1);
开始
格式:=GetFormByNumber(webbrowser1.document作为IHTMLDocument2,
0);
字段:=GetFormFieldName(格式);
num:=fields.IndexOf(theid);
结束;
直到(num-1);
Hm,您确定此链接包含任何表单元素吗?至少我没有看到任何可见的。也许它们是隐藏的——然而,我自己并没有检查这一点
Michael在网页中定位表单元素的一个复杂问题是,网页可能包含框架,并且任何框架中都可能有表单。基本上,您必须遍历所有帧和每个帧中的表单。一旦获得作为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的示例并不适用于所有网站,请参阅。以下函数成功地在我尝试过的所有站点上提取了一个帧作为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;
//来自TForm1声明
{公开声明}
wdoc:IHTMLDocument2;
程序TForm1.btnAnalyzeClick(发送方:TObject);
开始
wdoc:=作为IHTMLDocument2的WebBrowser.文档;
GetDoc(wdoc);
结束;
程序TForm1.GetDoc(文件1:IHTMLDocument2);
变量
i、 n:整数;
文件2:IHTMLDocument2;
帧调度:IDispatch;
框架:IHTMLWindow2;
oleu指数:油变异体;
sl:TStringList;
开始
如果doc1=零,则
开始
ShowMessage(“Web文档为空”);
出口
结束;
Form2.1.Lines.Clear;
sl:=TStringList.Create;
n:=doc1.frames.length;
sl.Add('Frames:'+IntToStr(n));
//检查每个帧的数据
如果n=0,则
GetForms(文档1,sl)
其他的
对于i:=0到n-1 do
开始
sl.Add('--Frame:'+IntToStr(i));
ole_指数:=i;
frame\u dispatch:=doc1.Frames.Item(ole\u索引);
如果帧分配为零,则
开始
frame_win:=作为IHTMLWindow2发送的frame_;
doc2:=框架文件;
//sl.Add(doc2.body.outerHTML);
GetForms(doc2,sl);
GetDoc(doc2);
结束;
结束;
//Form2只包含一个TMemo
Form2.Memo1.Lines.AddString(sl);
表2.表演;
sl.免费;
结束;
你例子中的逻辑是错误的,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;
var
i:整数;
nforms:整数;
文件:IHTML文件2;
形式:IHTMLFormElement;
字段:TStringList;
公式m1:整数;
num:整数;
theid:字符串;
开始
字段:=TStringList.Create;
theid:='xx';
//原始代码如下
i:=-1;
//nforms:=numberoforms(webbrowser1.document作为IHTMLDocument2);
//文档:=webbrowser1。作为IHTMLDocument2的文档;
//如果nforms=1,则
//开始
//格式:=GetFormByNumber(webbrowser1.document作为IHTMLDocument2,0);
//公式m1:=0;
//结束
//否则
开始
//重复
开始
公司(一);
格式:=GetFormByNumber(webbrowser1.document作为IHTMLDocument2,
i) );
字段:=GetFormFieldName(格式);
num:=fields.IndexOf(theid);
公式m1:=i;
结束;
//直到(num-1);
结束;
//原始代码结束
Memo1.Lines.Text:=字段.Text;
字段。免费;
结束;
是的,输入字段不也是元素吗?谢谢,但我似乎还没有完全理解。我不是按姓名搜索表单,而是按数字搜索表单。我给这个问题添加了一些代码,看看它是否对您更有意义。请看一看。Thx很抱歉,但是如何调用过程GetForms?GetForms(webbrowser1.documentasihtmldocument2,Tstringlist)?参见我添加的示例。您未能在示例中包含“i”的初始值。表单集合是基于零的,因此如果“i”被初始化为零,您将错过第一个表单。但它仍然找不到字段。您的示例中的逻辑是错误的。请参阅答案的最后一个补充。