【问题标题】:How do I use and debug WWW::Mechanize?如何使用和调试 WWW::Mechanize?
【发布时间】:2010-11-01 09:48:10
【问题描述】:

我对 Perl 很陌生,我在尝试自动化一些工作项目时正在学习。到目前为止,它一直很有趣。

我正在为客户生成报告。我可以从我可以访问的网页获取此报告。 首先,我需要用我的用户名、密码填写表格,然后从下拉列表中选择一个服务器,然后登录。 其次,我需要单击报告部分的链接。 第三,需要填写表格来创建报告。

这是我到目前为止写的:

my $mech = WWW::Mechanize->new();
my $url = 'http://X.X.X.X/Console/login/login.aspx';

$mech->get( $url );

$mech->submit_form(
     form_number => 1,
     fields      =>{
        'ctl00$ctl00$cphVeriCentre$cphLogin$txtUser'  => 'someone',
        'ctl00$ctl00$cphVeriCentre$cphLogin$txtPW'    => '12345',
        'ctl00$ctl00$cphVeriCentre$cphLogin$ddlServers'  => 'Live',
     button => 'Sign-In'
   },   
);
die unless ($mech->success);

$mech->dump_forms();

我不明白为什么,但是,在此之后,我查看了转储输出的内容,并看到了第一个登录页面的代码,而我相信我应该在成功登录后到达下一页。

是否有一些带有 cookie 的东西可以影响我和登录尝试?

还有什么我做错了吗?

感谢您的帮助, 亚尼夫

【问题讨论】:

    标签: perl www-mechanize


    【解决方案1】:

    这是事发几个月后的事,但我根据我提出的类似问题解决了同样的问题。请参阅Is it possible to automate postback from the client side? 了解更多信息。

    我使用 Python 的 Mechanize 或 Perl,但原理相同。

    总结一下我之前的回复:

    ASP.NET页面在表单中需要一个名为__EVENTTARGET的隐藏参数,正常使用mechanize时不会存在。

    当普通用户访问时,这些页面上有一个 __doPostBack('foo') 函数,它通过每个链接上的 javascript onclick 事件为 __EVENTTARGET 提供相关值,但由于 mechanize 不使用 javascript 你'需要自己设置这些值。

    下面是python的解决方案,不过适应perl应该不会太难。

    def add_event_target(form, target):
        #Creates a new __EVENTTARGET control and adds the value specified
        #.NET doesn't generate this in mechanize for some reason -- suspect maybe is 
        #normally generated by javascript or some useragent thing?
        form.new_control('hidden','__EVENTTARGET',attrs = dict(name='__EVENTTARGET'))
        form.set_all_readonly(False)
        form["__EVENTTARGET"] = target
    

    【讨论】:

    • 我试过了,但对于我的问题,它仍然不起作用。 Firebug 显示还传递了另一个参数 (__EVENTARGUMENT)。我添加了它和 __EVENTTARGET 一个,但它们似乎被忽略了——我总是得到相同的结果(我需要这些用于分页——访问后续页面)。
    • @HD:您是否通过表单提交到达您的页面? (例如,“搜索小部件”功能为您提供了一个分页的结果列表)如果您使用表单进入该页面,则可能会更加棘手,因为您也需要处理这么长的 __VIEWSTATE。如果你能发个链接我可以看看
    • @HD:我还在一些网站上发现您还需要清除一些无关的表单值。您可以使用 select_form 查看所有字段值,并通过您首选语言用于删除数组元素的任何方式清除它们。 (例如 python 中的 .pop())不幸的是,反复试验是我找到找到这些元素的唯一方法。
    【解决方案2】:

    你只能机械化你知道的东西。在您编写更多代码之前,我建议您使用 Firebug 之类的工具,并在手动执行此操作时检查浏览器中发生的情况。

    当然可能会使用 cookie。或者您可能忘记了隐藏的表单参数?只有你自己知道。

    编辑:

    • WWW::Mechanize 应该在没有任何进一步干预的情况下处理 cookie。
    • 您应该经常检查您调用的方法是否成功。第一个 get() 有效吗?
    • 查看服务器日志以了解实际请求的内容以及作为响应发送的 HTTP 状态代码可能很有用。

    【讨论】:

    • 感谢曼尼。我有 Firebug,但我不确定要寻找什么。我在哪里检查 cookie?我查看了所有参数,没有隐藏的。
    • 查看标有“网络”的标签。它将显示服务器发送的所有 HTTP 标头,包括任何 cookie。
    • 这是我从我的代码中得到的:GET X.X.X.X/Console/login/login.aspx Accept-Encoding: gzip, x-gzip, deflate User-Agent: libwww-perl/5.822 (no content) HTTP/1.1 200 OK缓存控制:私人连接:关闭日期:2009 年 6 月 8 日星期一 15:08:32 GMT 服务器:Microsoft-IIS/6.0 内容长度:14720 内容类型:文本/html; charset=utf-8 Client-Date: Mon, 08 Jun 2009 15:08:32 GMT Client-Peer: X.X.X.X:80 Client-Response-Num: 1
    • 链接:<..>; rel="样式表"; type="text/css" 刷新:6010; URL=../login/login.aspx?logoff=true Set-Cookie: ASP.NET_SessionId=ivz5k045r4en4eehrn3yed55;路径=/; HttpOn +ly 标题:控制台 - 登录 X-AspNet-版本:2.0.50727 X-Meta-CODE-LAN​​GUAGE:C# X-Meta-GENERATOR:Microsoft Visual Studio .NET 7.1 X-Meta-Vs-DefaultClientScript:JavaScript X-Meta -Vs-TargetSchema: schemas.microsoft.com/intellisense/ie5 X-Powered-By: ASP.NET
    • 这不是很容易阅读,但它确实说明了包含会话 ID 的 cookie。
    【解决方案3】:

    如果您使用的是 Windows,请使用 Fiddler 查看手动执行此过程时发送的数据,然后使用 Fiddler 将其与脚本执行时捕获的数据进行比较。

    根据我的经验,在检查表单帖子时,像 Fiddler 这样的网络调试代理比 Firebug 更有用。

    【讨论】:

      【解决方案4】:

      我发现在使用 WWW::Mechanize 编写 Web 自动化时使用 Wireshark 实用程序非常有帮助。它将在以下几个方面为您提供帮助:

      1. 让您了解您的 HTTP 请求是否成功。
      2. 查看 HTTP 级别的失败原因。
      3. 跟踪您传递给服务器的确切数据并查看您收到的返回内容。

      只需为网络流量设置一个 HTTP 过滤器并启动您的 Perl 脚本。

      【讨论】:

        【解决方案5】:

        aspx 页面非常简短的要点是,它们将所有本地会话信息保存在几个以通用 aspxform 为前缀的变量中。通常这是一个顶级表单,所有表单元素都是其中的一部分,但我想这可能因实现而异。

        对于我正在处理的特定实现,我需要担心其中的 2 个状态变量,具体来说:

        __VIEWSTATE
        __EVENTVALIDATION.
        

        您的目标是确保将这些变量提交到您提交的表单中,因为它们可能是我上面提到的主表单 aspxform 的一部分,而您提交的表单可能与此不同。

        当浏览器加载一个 aspx 页面时,一段 javascript 会在 asp 服务器/客户端交互中传递此会话信息,但当然我们没有 perl 机械化那么奢侈,因此您需要手动发布这些使用 mechanize 将元素添加到当前表单中。

        在我刚刚解决的情况下,我基本上是这样做的:

        my $browser = WWW::Mechanize->new( );
        
        # fetch the login page to get the initial session variables
        my $login_page = 'http://www.example.com/login.aspx';
        $response = $browser->get( $login_page);
        
        # very short way to find the fields so you can add them to your post
        $viewstate = ($browser->find_all_inputs( type => 'hidden', name => '__VIEWSTATE' ))[0]->value;
        $validation = ($browser->find_all_inputs( type => 'hidden', name => '__EVENTVALIDATION' ))[0]->value;
        
        # post back the formdata you need along with the session variables
        $browser->post( $login_page, [ username => 'user', password => 'password, __VIEWSTATE => $viewstate, __EVENTVALIDATION => $validation ]);
        
        # finally get back the content and make sure it looks right
        print $response->content();
        

        【讨论】:

          猜你喜欢
          • 2011-04-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-10
          • 2012-08-10
          • 2013-04-08
          相关资源
          最近更新 更多