网页自动提交

MSHTML 是微软公司的一个COM组件,该组件封装了HTML语言中的所有元素及其属性,通过其提供的标准接口,可以访问指定网页的所有元素.MSHTML对象模型是由一些对象和集合组成的.处于根部的是HTML,描述了打开页面的1个窗口,包括一系列集合和对象。如Frames集合,History, Location,Navigator,Document,Vi—sum,Event对象等.其中描述呈现在客户窗口实际网页的是Document对象。由一系列的属性、方法、对象和集合组成.其中All集合中包含网页中所有标记(Tag)元素,其主要的方法和属性有:
(1)Length(长度):即标记出现的个数,可以把标记的集合理解为从0开始的一维数组,其次序按照标记在网页位置排列;
(2)Tags(标记):用于过滤出给定标记的集合,如Doc.Al1.Tags(P)得到所有分段标记P;
(3)Item(项目):用于选择集合中的某1个元素,如object.item(0)得到集合的第1个元素,而object.item(i)得到第i+1个元素.
此外,IHTMLElement也是个常用的集合对象,代表网页中指定标记的集合,通过这个集合对象,可以得到网页上特定标记的内容.IHTMLElement有4个主要属性:
(1)InnerText:开始标记和结束标记之间的文本;
(2)InnerHTML:开始标记和结束标记之间的文本和HTML;
(3)OuterText:对象的文本;
(4)OuterHTML:对象的文本和HTML.


procedure TForm1.Button1Click(Sender: TObject);
var
Doc:IHTMLDocument2;
input:OleVariant;
userinputelement,pwdinputelement:ihtmlinputelement;
begin
doc:=webbrowser1.document as ihtmldocument2;
userinputelement:=(doc.all.item(‘user’(也就是网页中用户名控件的名字),0) as ihtmlinputelement);
userinputelement.value:=edit1.text;(也就是你要向网页输入的东西)
pwdinputelement:=(doc.all.item(‘password’,0) as ihtmlinputelement);
pwdinputelement.value:=edit2.text;
input:=doc.all.item(‘submit’,0);
input.click;
end;  


当提交数据按钮没有NAME属性时,采用如下方法:



procedure TForm1.Button1Click(Sender: TObject);
var
Doc:IHTMLDocument2;
form:ithmlformelement;
userinputelement,pwdinputelement:ihtmlinputelement;


begin
doc:=webbrowser1.document as ihtmldocument2;
userinputelement:=(doc.all.item(‘user’(也就是网页中用户名控件的名字),0) as ihtmlinputelement);
userinputelement.value:=edit1.text;(也就是你要向网页输入的东西)
pwdinputelement:=(doc.all.item(‘password’,0) as ihtmlinputelement);
pwdinputelement:=edit2.text;
form:=(doc.all.item(‘login_form’,0) as ihtmlformelement):
form.submit;
end;  

2 Comments

TWebBrowser的使用


偶然的机会需要使用TWebBrowser,在开发过程中涉及到一些比较不肤浅的东西,于是免不了搜资料,翻CSDN的帖子,终于把要做的东西作了出来,同时对于TWebBrowser也有了初步的了解。同时看到很多CSDN上的不少朋友也在TWebBrowser上存在很多疑问,于是把自己这段时间所得的拿出来与大家分享。还是那句话,本人水平很洼,说的不对的话敬请指出,不要客气,否则不但我自己学错了东西,也让看这篇文章的人误入歧途。废话少说正文开始。


首先我们要认识到TWebBrowser其实是Delphi对Internet Explorer Browser的封装,也就是说它是一个ActiveX控件,看过TWebBrowser代码的朋友会发现这个空间的所有方法的实现部分都调用了DefaultInterface的方法,而TWebBrowser的这个属性是一个IWebBrowser2接口类型的对象,这个接口就是IE的接口。我们在使用TWebBrowser代替IE浏览器的目的大部分是为了能够让程序处理页面,实现自动对WebApplication的请求,所以我们首先想得到的就是TWebBrowser所浏览的内容。TWebBrowser的Documnet属性正是这一内容,Document其实是一个IHTMLDocument2,但是它被声明为IDispatch接口类型,我们需要把它转化为IHTMLDocument2类型然后是用我们需要的各种方法。在这里需要注意IHTMLDocument2是在MSHTML单元定义的,需要我们手动将这一单元加入到uses部分。具体代码如下:


var D : IHTMLDocument2;
begin 
  D := WebBrowser1.Document as IHTMLDocument2;
end;


接下来我们来看看一个网页中包含什么,也就是我们希望通过TWebBrowser来处理的内容有哪些。网页中的元素主要有普通文本内容,超级连接以及动态的元素(Form中的元素),当然还有其它元素,但是我们在一般的处理过程中一般会用到这些,因此我在这里以这些元素为例首先我要介绍的是Form和包含在Form中的元素的使用。


在IHTMLDocument接口中有一个Forms的属性,这个属性是IHTMLElementCollection接口类型,其实这个Forms属性是TWebBrowser显示的页面中的所有Form元素。也就是说一个页面中的所有Form都包含在Forms这个集合中。我们可以以使用IHTMLDocument.Forms.item(name: OleVariant; index: OleVariant)得到我们需要操作的Form,当然我们在这里得到的只是一个IDispatch接口,我们需要再把这个接口转换成IHTMLFormElement来使用Form的方法和属性。示例如下(该例子为yahoo的免费信箱登陆界面http://mail.yahoo.com.cn):


var Form :  IHTMLFormElement  ;
    D:IHTMLDocument2  ;


begin
  with WebBrowser1 do begin
     D := Document as IHTMLDocument2;
     Form := D.Forms.item(‘login_form’,0) as IHTMLFormElement;
     (form.item(‘login’,0) as IHTMLElement).setAttribute(‘value’,edit1.Text,0);
     (form.item(‘passwd’,0) as IHTMLElement).setAttribute(‘value’,edit2.Text,0);
     //form.submit; // this line work too
     (form.item(‘.save’,0) as IHTMLElement).click;
  end;
end;


从上面的例子我们可以看到我们可以通过两种方法提交一个Form,这两种方法在一般情况下没有什么区别,但是当页面中编写了一些js用来实现页面提交的控制时,前者会忽略掉这些js,所以后面的方法是我所推荐的。


在这个时候我遇到了一个问题,就是在我要处理的页面中有两个Form,而且这样两个Form都没有名字,也就是说Form := D.Forms.item(‘login_form’,0) as IHTMLFormElement;这一句中item的第一个参数的我们无法从网页中得到,同时在设置这个参数时我发现了一个问题,就是说如果在页面中有两个Form元素的话,第一个Form元素可以通过item(varEmpty,0)得到,第二个Form元素可以通过item(verNull,0)得到,而item的第二个参数完全不起作用,这个问题可能是由于我对该函数的错误使用造成的,希望有人可以给出这一问题的解决方案(我在自己翻看帖子是找到了答案,的确是我对该函数的参数的错误使用造成的,第一个参数应该是我们要使用的对象的索引值。)。我的想法是DHTML在没有明确得到一个元素的名称时会自动生成一个唯一的元素名称分配给该元素,但是如何得到这个唯一的元素名称呢?这个只是我的一个设想,我们会看到,当我们处理链接的时候我们还要遇到这个问题。示例如下(


这是我自己做的一个jsp程序):
var   form : IHTMLFormElement  ;
     d:IHTMLDocument2  ;
begin
  with WebBrowser1 do begin
     d := document as IHTMLDocument2;
     form := d.forms.item(varNull,01) as IHTMLFormElement;
     (form.item(‘firstName’,0) as IHTMLElement).setAttribute(‘value’,edit1.Text,0);
     (form.item(‘lastName’,0) as IHTMLElement).setAttribute(‘value’,edit1.Text,0);
     form.submit;
  end;
end;


以上是网页中Form的基本处理,接下来我介绍一下网页中对于链接的控制,我们一般是希望能够实现程序自动点击网页中的连接。在这里正如前面提到的,我只能得到前两个没有名称的连接。示例如下:


var  Links : IHTMLElementCollection;
     D:IHTMLDocument2  ;
     Element : IHTMLElement;
begin
  with WebBrowser1 do begin
    D := Document as IHTMLDocument2;
    Links := D.links;
    Element := (Links.Item(varempty,0) as IHTMLElement);
    ShowMessage(Element.getAttribute(‘href’,0));
    Element := (Links.Item(varNull,0) as IHTMLElement);
    ShowMessage(Element.getAttribute(‘href’,0));
  end;
end;


我们可以通过调用以上代码中的Element.Click事件来模拟点击。不行了,写不下去了,还有一个常见的问题就是怎么使自己写的Browser在打开一个新窗口时在制定窗口打开。这个要在TWebBrowser的NewWindows2中改变 ppDisp来实现。


就是这么多,希望大家能够从中学到点什么,更希望有人能够解答我上面的疑问。


版权所有:idilent 网站转载请注明作者 其他转载方式请与作者联系(idilent@yahoo.

2 Comments

编程实现网页表单数据的自动提交

MSHTML 是微软公司的一个COM组件,该组件封装了HTML语言中的所有元素及其属性,通过其提供的标准接口,可以访问指定网页的所有元素.MSHTML对象模型是由一些对象和集合组成的.处于根部的是HTML,描述了打开页面的1个窗口,包括一系列集合和对象。如Frames集合,History, Location,Navigator,Document,Vi—sum,Event对象等.其中描述呈现在客户窗口实际网页的是Document对象。由一系列的属性、方法、对象和集合组成.其中All集合中包含网页中所有标记(Tag)元素,其主要的方法和属性有:
(1)Length(长度):即标记出现的个数,可以把标记的集合理解为从0开始的一维数组,其次序按照标记在网页位置排列;
(2)Tags(标记):用于过滤出给定标记的集合,如Doc.Al1.Tags(P)得到所有分段标记P;
(3)Item(项目):用于选择集合中的某1个元素,如object.item(0)得到集合的第1个元素,而object.item(i)得到第i+1个元素.
此外,IHTMLElement也是个常用的集合对象,代表网页中指定标记的集合,通过这个集合对象,可以得到网页上特定标记的内容.IHTMLElement有4个主要属性:
(1)InnerText:开始标记和结束标记之间的文本;
(2)InnerHTML:开始标记和结束标记之间的文本和HTML;
(3)OuterText:对象的文本;
(4)OuterHTML:对象的文本和HTML.


procedure TForm1.Button1Click(Sender: TObject);
var
Doc:IHTMLDocument2;
input:OleVariant;
userinputelement,pwdinputelement:ihtmlinputelement;
begin
doc:=webbrowser1.document as ihtmldocument2;
userinputelement:=(doc.all.item(‘user’(也就是网页中用户名控件的名字),0) as ihtmlinputelement);
userinputelement.value:=edit1.text;(也就是你要向网页输入的东西)
pwdinputelement:=(doc.all.item(‘password’,0) as ihtmlinputelement);
pwdinputelement.value:=edit2.text;
input:=doc.all.item(‘submit’,0);
input.click;
end;  


当提交数据按钮没有NAME属性时,采用如下方法:



procedure TForm1.Button1Click(Sender: TObject);
var
Doc:IHTMLDocument2;
form:ithmlformelement;
userinputelement,pwdinputelement:ihtmlinputelement;


begin
doc:=webbrowser1.document as ihtmldocument2;
userinputelement:=(doc.all.item(‘user’(也就是网页中用户名控件的名字),0) as ihtmlinputelement);
userinputelement.value:=edit1.text;(也就是你要向网页输入的东西)
pwdinputelement:=(doc.all.item(‘password’,0) as ihtmlinputelement);
pwdinputelement:=edit2.text;
form:=(doc.all.item(‘login_form’,0) as ihtmlformelement):
form.submit;
end;  


登录”按钮一般都是网页中默认的回车按钮,所以可以用上面代码来代替前面的点击按钮.

Leave a comment

treeview

dm.qchushi.SQL.Clear;//qchushi是adoquery
dm.qchushi.SQL.Add(‘select * from table’);
dm.qchushi.open;

  inherited;
  treeview1.Items.Clear ;
  root:=ttreenode.Create(treeview1.items);
  node:=ttreenode.Create(treeview1.items);
  root:=treeview1.Items.AddChild(nil,’51111   |   ××’);
  dm.qchushi.First;
  for i:=0 to dm.qchushi.RecordCount-1 do
    begin
    str:=trimright(dm.qchushi['bianma'])+’   |   ‘+trimright(dm.qchushi['mingchen']);
    node:=treeview1.Items.Addchild(root,str);
    dm.qchushi.Next ;
    end;
    root.Expand(true);
    dm.qchushi.Close;

  treeview2.Items.Clear ;
  root1:=ttreenode.Create(treeview2.items);
  node1:=ttreenode.Create(treeview2.items);
  root1:=treeview2.Items.AddChild(nil,’gjsk’);
  dm.qchushi.SQL.Clear;
  dm.qchushi.SQL.Add(‘select * from table2′);
  dm.qchushi.Open;
  dm.qchushi.first ;
  for t:=0 to dm.qchushi.RecordCount-1 do
    begin
    str1:=trimright(dm.qchushi['bm'])+’   |   ‘+trimright(dm.qchushi['mc']);
    node1:=treeview2.Items.Addchild(root1,str1);
    dm.qchushi.Next ;
    end;
    root1.Expand(true);
    dm.qchushi.Close;  


来自:9278707, 时间:2005-12-14 14:33:43, ID:3296422

加我qq发给你,,66516186  


来自:seasky212, 时间:2005-12-14 14:43:57, ID:3296441

兄弟的Email是:season_k2005@163.com
最好有解释  


来自:周海涛, 时间:2005-12-14 15:05:57, ID:3296474

加我的QQ我发给你273482488  


来自:kikyo, 时间:2005-12-14 15:31:35, ID:3296520

with adoquery_shengfen do
     begin
     thisnode:=Treeview1.Items.Add(nil,’所有地区’);
     while not adoquery_shengfen.Eof do
       begin
         department:=fieldbyname(‘shengfen’).AsString;
         thisnode:=treeview1.Items.Add(thisnode,department);
             adoquery_diqu.SQL.Text:=’select name from diqu where sf=”’+fieldbyname(‘sfid’).asstring+””;
           with adoquery_diqu do
             begin
             open;
               first;
                while not adoquery_diqu.Eof do
                  begin
                  treeview1.Items.AddChild(thisnode,fieldbyname(‘name’).AsString);
                    next;
                   end;
               close;
              end;
         next;
      end;
     end;  

Leave a comment

调用存储过程

用ADOSTOREDPROC调用存储过程
procedure TCPKCFORM.Button1Click(Sender: TObject);
VAR
  RQ1,RQ2:TDATETIME;
begin
  RQ1:=DATETIMEPICKER1.DATE;
  RQ2:=NOW();
  with adoS1 do
  begin
     Close;
     procedurename:=’MYCPKKC’;
     parameters.refresh;
     Parameters[1].Value:=RQ1;
     Parameters.ParamByName(‘@ZZRQ’).Value:=RQ2;
     ExecProc;
  end;
  EDIT1.Text:=ADOS1.Parameters[0].VALUE; //判断是否调用成功。
end;
设置好DataSource的连接,和DbgridEh的连接,程序执行后没有显示。
Text值返回0,这是为什么呢?

  


来自:Txh2005, 时间:2005-12-25 15:00:23, ID:3308108

open [:D][:D]  

Leave a comment

数据流的压缩

数据流的压缩.
procedure CompressStream(var MyStream: TMemoryStream); //压缩数据流
var
  SourceStream: TCompressionStream;
  DestStream: TMemoryStream;
  Count: Integer;
Begin
  //获得数据流的原始尺寸
  Count := MyStream.Size;
  DestStream := TMemoryStream.Create;
  SourceStream := TCompressionStream.Create(clMax, DestStream);
  Try
    //SourceStream中保存着原始的数据流
    MyStream.SaveToStream(SourceStream);
    //将原始数据流进行压缩, DestStream中保存着压缩后的数据流
    SourceStream.Free;
    MyStream.Clear;
    //写入原始数据流的尺寸
    MyStream.WriteBuffer(Count, SizeOf(Count));
    //写入经过压缩的数据流
    MyStream.CopyFrom(DestStream, 0);
    //复位流指针
    MyStream.Position := 0;
  finally
    DestStream.Free;
    //SourceStream.Free;
  end;
end;


procedure UnCompressStream(const MyStream: TMemoryStream);
var
  SourceStream: TDecompressionStream;
  DestStream: TMemoryStream;
  Buffer: PChar;
  Count: integer;
Begin
//还原被压缩数据流
  //从被压缩的数据流中读出原始数据流的尺寸
  MyStream.Seek(0, soFromBeginning);
  MyStream.ReadBuffer(Count, SizeOf(Count));
  //根据数据流尺寸大小为将要读入的原始数据流分配内存块
  GetMem(Buffer, Count);
  DestStream := TMemoryStream.Create;
  SourceStream := TDecompressionStream.Create(MyStream);
  Try
    //将被压缩的数据流解压缩,然后存入 Buffer内存块中
    SourceStream.ReadBuffer(Buffer^, Count);
    //将原始数据流保存至 DestStream流中
    DestStream.WriteBuffer(Buffer^, Count);
    //复位流指针
    DestStream.Position := 0;
    MyStream.LoadFromStream(DestStream);
  finally
    FreeMem(Buffer);
    DestStream.Free;
    //SourceStream.Free;
  end;
end;

Leave a comment

近期想解决的问题

壹、把用户权限体系用数据库来实现(包括对应部门)


贰、数据库的异常如何能用DELPHI截获并解释


叁、c/s系统网络加密的问题

Leave a comment

现在这里这么冷清啊

不过,天天能记点东西还是不错滴

Leave a comment

这个日记本能备份吗?为什么不能上传附件呢?

如果这个日记本能备份到本地多好啊,要是能够存点文件就更好了,呵呵

Leave a comment

BS微软一下

VFP的DBF文件访问竟然tmd要专门有驱动vfpoledb,靠,真麻烦

Leave a comment