带frame的php网站,利用webbrower想实现自动登录并自动分析获取网页中的数据,该网页中的数据定时自动刷新。
见有利用IHTMLDocument2的方法,用Olevariant进行赋值;因为不知道网页上对应input、submit控件的名称,所以不知道可行否;我使用o:=wb.OleObject.document.all.tags('input',0);后,o.value:=xx的时侯抛异常,提示automation object不支持value方法。
急~

解决方案 »

  1.   

    >不知道网页上对应input、submit控件的名称
    view source
    o:=wb.OleObject.document.all.tags('input',0);后,o.value:=xx的时侯抛异常,提示automation object不支持value方法。
    document.all.tags returns a collection. you should locate the input by its type, location or style.
      

  2.   

    还是不明白
    如何获取带frame网页中的数据呢?是一个表单,可能有多页,php的网站
      

  3.   

    query IHTMLWindow2 or IWebBrowser2 from the frame element
      

  4.   

    谢谢大虾的解答,但我的问题还没有解决,目前我已经实现遍历frame得到指定frame的页面源码。该页面中有一个表单,我想读取这个表单的内容,除了用字符串方法外,有没有什么用类似取element属性的方法可以得到表格中的数据?该表格有多页,有没有办法一次取得所有数据?
    对于frame中相关页面的tagname我用以下方法进行遍历,发现取得的tagname值均为html,为什么?
     doc:=Wb.document as IHtmlDocument2; 
     frameCol:=doc.frames;
     for i:=0 to frameCol.Length-1 do
     begin
       vi:=i;
       frame:=frameCol.Item(vi);
       frame.QueryInterface(IID_IHTMLWindow2,framewin2);
       if LowerCase(framewin2.name)='frame1' then
       begin
         mmo.Lines.Add(framewin2.document.body.innerHTML);
         doc2:=framewin2.document as IHtmlDocument2;
         for j:=0 to doc2.all.length-1 do
         begin
           _element:= doc2.all.item(i,EmptyParam) as IHTMLElement;//估计是这句话的问题,但不知道如何改
           mmo.Lines.Add(_element.tagname);
         end;
       end;
      

  5.   

    不要用IHTMLELEMENT,直播用OLEDOCUMENT,
    我就是这样做的, 分析很畅快,而且不会出错
      

  6.   

    怎么做的,能不能给个例子?
    我需要获取指定frame的table中的数据,最好是一次获取多页的数据
    还有就是关于自动登录后,如何等待提交成功后页面的完成?
      

  7.   

    1 query IHTMLTable from IHTMLElement if the tagname is "table"
    2 handle the DocumentComplete event
      

  8.   

    [CLSCompliant(false), ComVisible(false)]
    public static void SaveTableByColumn(IHTMLTable table, StringDictionary container)
    {
    if (table == null)
    return;
    if (container == null)
    return;
    foreach (object o in table.rows)
    {
    IHTMLTableRow row = (IHTMLTableRow)o;
    for (int j = 0; j < row.cells.length / 2; j++)
    {
    string key = ((IHTMLElement)row.cells.item(j, 0)).innerText;
    string value = ((IHTMLElement)row.cells.item(j + 1, 0)).innerText;
    if (key != null && value != null)
    {
    key = key.Trim();
    value = value.Trim();
    if (key.Length > 0)
    container.Add(key, value);
    }
    }
    }
    }
    [CLSCompliant(false), ComVisible(false)]
    public static List<IHTMLTable> GetDescentsTables(IHTMLElement htmlElement)

    List<IHTMLTable> tableList=new List<IHTMLTable>();
    if (htmlElement==null)
    return tableList;
    IHTMLElementCollection formDescents = (IHTMLElementCollection)htmlElement.all;
    foreach (object o in formDescents)
    {
    IHTMLElement he = (IHTMLElement)o;
    if (he.tagName.ToLower().CompareTo("table")==0)
    {
    IHTMLTable t = (IHTMLTable)he;
    tableList.Add(t);
    }
    }
    return tableList;
    }
    [CLSCompliant(false), ComVisible(false)]
    public static List<IHTMLTable> GetChildTables(IHTMLElement htmlElement)
    {
    List<IHTMLTable> tableList = new List<IHTMLTable>();
    if (htmlElement == null)
    return tableList;
    IHTMLElementCollection formChildren= (IHTMLElementCollection)htmlElement.children;
    foreach (object o in formChildren)
    {
    IHTMLElement he = (IHTMLElement)o;
    if (he.tagName.ToLower().CompareTo("table") == 0)
    {
    IHTMLTable t = (IHTMLTable)he;
    tableList.Add(t);
    }
    }
    return tableList;
    }
      

  9.   

    我试过在document complete里判断,但不成功,第一个页面我可以用busy和ReadyState来判断(单个用好象也不很准)。我的程序第一个页面自动submit.click后,需要等待submit成功后转向的页面加载完成,这时用busy、Readystate等方法都不行,我也试过取title,但可能因为是frame的结构,也无法判断(有可能是我判断的方法不对)。由于我不太清楚如何用post方法让网页返回所需要的指定页面(我用取到的url直接访问指定的数据页面时,网站直接跳到了登录页面,估计网站不是通过cookie来判断,有可能用session或refer方法来判断,如果有方法可以直接get或post到数据页面的话,就可以不用自动登陆的方法了,毕竟这个方法很费时间,而且受限制太多)所以我才走了这个弯路:从登陆页面开始由程序实现自动提交。网站的用户名和密码好象有加密,但加载数据的页面用的是用户名进行查询的,所以如果可以实现直接post或get,那么我只用通过登陆页面后取加密后的uid和pwd再直接get或post了(有时间抓个包研究加密过程后就可以直接get或post了)对于你提供的代码我看不太懂,在参考一下资料后,我自己写了一个多框架中取table的方法,但在取table元素的地方写不下去了,不知道该怎么提取
     doc:=WebBrowser.document as IHtmlDocument2;
     frameCol:=doc.frames;
     for i:=0 to frameCol.Length-1 do
     begin
       vi:=i;
       frame:=frameCol.Item(vi);
       frame.QueryInterface(IID_IHTMLWindow2,framewin2);
       if LowerCase(framewin2.name)='frametable' then
       begin
         doc2:=framewin2.document as IHtmlDocument2;
         _element:=doc2.get_all;
         for j:=0 to doc2.all.length-1 do
         begin
           tbDisp:=_element.item(j,0);
           if SUCCEEDED(tbDisp.QueryInterface(IHTMLTable,HtmlTblEle)) then
           with HtmlTblEle do
           begin
             for m:=0 to HtmlTblEle.cols-1 do
             begin
               _element :=HtmlTblEle.rows;
               for n:=0 to _element.length-1 do
               begin
                 //如何将table内容输出?
    //             mmo.Lines.Add(_element.item(0,0));
               end;
             end;
           end;
      

  10.   

    取table的问题已经解决,多页的如何取呢?一定要一个个地取吗?有没有next之类的方法可用?再就是如何判断自动登陆后跳转到的页面加载完成
      

  11.   

    yes
    you have to detect the change of page numbers
      

  12.   

    table一个个地取没问题,只是不能做到实时了,如果对实时性要求较高就麻烦了对于等待自动登陆后跳转到的页面加载完成,我实在是没什么好办法了,因为涉及到多frame,用documentcomplete不好使,目前我使用的是在这个事件中对frame进行count,到了指定的数字后就可以认为加载完了,不过虽然理论上是一个good idea,但我还没测试成功 :(
    不知道还有没有什么别的好方法?
      

  13.   

    readystate我也试过,也不行,click之后直接就到了判断readystate,但此时,由于刚刚click,wb还没有跳转,此时的readystate还是第一个页面的,当然就认为ready了
      

  14.   

    我在click之后加了个1~1000的计数循环,然后再判断就ok了
      

  15.   

    check ready state in your documentcomplete handler to make sure ALL frames are ready
      

  16.   

    在其它代码没有改动的情况下,我就在click之后加了个计数循环用ready和busy就可以正常判断了;而我使用documentcomplete对frames进行count时,却不管用
      

  17.   

    我用JAVA做过同样的东西.当时是为了抓取QQ天气,并可以根据提交的城市获取不同的天气情况,Delphi有同样的3rd控件,我曾经看过Demo,效果相当不错.做成论坛轰炸机都没有问题,呵呵.
      

  18.   

    楼主使用DOM的方法来获得表格内容,我认为不是一个好办法。费时费事不说,而且效率底下。比较高效的做法是:直接读取整个页面的HTML,然后使用规则表达式,获取页面中符合条件的代码片断。这样做比DOM高效N倍。对于分页的问题,估计没有什么好办法。唯一可行的就是获得“下一页”的地址,然后循环读取页面。
      

  19.   

    tttk大虾所提到的dom方法的意思是什么
    为了能和页面进行交互,目前我只能想到加载页面并用shtml的方法对页面进行控制
    还请tttk大虾多多指点
      

  20.   

    我现在要做的并不只是分析网页内容,而且要在满足条件后与页面进行交互,这个交互过程是完全自动的。所以取得页面的element,然后在满足条件后对element进行控制,我想这应该是唯一可行的办法。IHTMLTable2好象有FirstPage、LastPage的属性,但没有见到有NextPage的属性,如果有此属性或许就只用一个nextpage方法就ok了,分页功能的实现是由数据访问层来控制的吧?目前还有个麻烦,就是控制的问题,现在我已经可以用嵌套循环取得某个特定frame中的element的属性,而对其控制的话我现在只找到了这样的方法:WB.oleobject.document.documentelement.document.frames.item(0).document.all.item('name',0),也就是说得先把该element所在的frame序数找出来,然后再套这个式子;然而,如果这个frame序数是根据条件变化的,就麻烦了。我想在用循环遍历找到特定的element之后,能够直接对该element进行交互。
      

  21.   

    用for each循环,判断frame的URL,input的ID,Table的表头之类的特征值
      

  22.   

    循环遍历后直接对取得的element控制的问题已经解决了,搞定后才发现好简单。非常感谢蒋晟大虾的热情解答。我现在在搞分页的问题,对于分页你有没有什么好的建议?