繁体   English   中英

使用 WWW::Mechanize 登录

[英]Logging in using WWW::Mechanize

我正在查看使用以下内容 登录 https://imputationserver.sph.umich.edu/index.html#!pages/login

#!/usr/bin/env perl

use strict;
use warnings FATAL => 'all';
use feature 'say';
use autodie ':all';
use WWW::Mechanize;
use DDP;

my $mech = WWW::Mechanize->new();
$mech->get( 'https://imputationserver.sph.umich.edu/index.html#!pages/login' );
my $username = '';
my $password = '';
#$mech->set_visible( $username, $password );
#$mech -> field('Username:', $username);
#$mech -> field('Password:', $password);

my %data;
@{ $data{links} } = $mech -> find_all_links();
@{ $data{inputs}    } = $mech -> find_all_inputs();
@{ $data{submits} } = $mech ->find_all_submits();
@{ $data{forms} } = $mech -> forms();
p %data;

#$mech->set_fields('Username' => $username, 'Password' => $password);

但似乎没有任何有用的信息,通过打印显示:

{
    forms     [],
    inputs    [],
    links     [
        [0] WWW::Mechanize::Link  {
            public methods (9) : attrs, base, name, new, tag, text, URI, url, url_abs
            private methods (0)
            internals: [
                [0] "favicon.ico",
                [1] undef,
                [2] undef,
                [3] "link",
                [4] URI::https,
                [5] {
                    href   "favicon.ico",
                    rel    "icon"
                }
            ]
        },
        [1] WWW::Mechanize::Link  {
            public methods (9) : attrs, base, name, new, tag, text, URI, url, url_abs
            private methods (0)
            internals: [
                [0] "assets/css/loader.css",
                [1] undef,
                [2] undef,
                [3] "link",
                [4] var{links}[0][4],
                [5] {
                    href   "assets/css/loader.css",
                    rel    "stylesheet"
                }
            ]
        }
    ],
    submits   []
}

我查看了 Firefox 的工具 -> 页面信息,但那里没有任何有价值的信息,我看不到此页面上的用户名和密码来自何处。

我试过了

$mech -> submit_form(
    form_number => 0,
    fields      => { username => $username, password => $password },
);

但后来我得到No form defined

在链接、输入、字段方面,我看不到任何内容,也不知道如何继续。

我在https://metacpan.org/pod/WWW::Mechanize::Examples上没有看到任何可以帮助我解决这种情况的内容。

如何使用 Perl 的 WWW::Mechanize 登录到这个页面?

正如 Dave 所说,许多现代网站将通过 Javascript 驱动的(私有)API 处理登录。 您需要在浏览器中打开“网络”选项卡,像往常一样手动登录,并观察 GET、PUT、POST 等发生的顺序,以了解完成登录所需的交互,然后使用MechLWP自己执行该序列。

页面上的 Javascript 可能会创建 JSON 甚至 JWT 来进行交互; 你必须在你的代码中复制它才能工作。

特别是检查 cookies 的标头,以及正在设置的身份验证和 CSRF 令牌; 您需要捕获这些并通过请求重新发送它们(POST 请求将需要 CSRF 令牌)。 这可能需要与站点进行更多交互以捕获操作序列并复制它们。 HTTP::Cookies should handle the cookies for you automatically, but more sophisticated header usage will require you to use HTTP::Headers to extract the data and possibly resubmit it that way.

从本质上讲,这些过程都非常简单。 这只是准确复制它们的问题,以便您可以自动化它们。

您应该检查该站点是否已经有程序员的 API,如果有,请使用它; 这样的 API 几乎总是会为您提供更简单、直接的站点功能接口和更易于使用的返回数据格式。 如果该站点是高度动态的,例如一个重型 React 站点,则站点中的其他页面可能会加载一个骨架 HTML 页面,然后也使用 Javascript 来填充它; 随着页面的发展,您的代码也必须如此。 如果您使用的是已定义程序员的 API,那么只要 API 版本不变,您就可以依赖交互和返回的数据保持不变。

最后一点:您应该通过使用自动化来验证您没有违反用户协议。 一些网站明确禁止使用自动登录方法。

该页面来源的有趣部分是:

<body class="bg-light">

  <div id="main">
    <div class="spinner">
        <div class="bounce1"></div>
      <div class="bounce2"></div>
      <div class="bounce3"></div>
    </div>
  </div>

  <script src="./dist/bundles/cloudgene/index.js"></script>


</body>

因此,构成该页面的 HTML 中没有登录表单。 这就解释了为什么 WWW::Mechanize 什么都看不到——那里什么也看不到。

似乎该页面都是由该 Javascript 文件 - index.js构建的。

现在,您可以花几个小时阅读该 JS 并准确了解页面的工作方式。 但这将是一项艰苦的工作,而且有一个更简单的方法。

无论客户端(浏览器或您的代码)如何工作,实际登录都必须由 HTTP 请求和响应来处理。 客户端发送请求,服务器响应,客户端根据该响应进行操作。 你只需要弄清楚请求和响应的样子,然后在你的代码中重现它。

您可以使用浏览器中几乎肯定内置的工具检查 HTTP 请求和响应(在 Chrome 中,它是点菜单 -> 更多工具 -> 开发人员工具)。 这将使您能够准确地看到 HTTP 请求的样子。

完成此操作后,您“只”需要使用 Perl 代码制作类似的响应。 您可能会发现使用LWP::UserAgent及其相关模块比使用 WWW::Mechanize 更容易。

WWW::Mechanize 是一个 web 客户端,具有一些 HTML 解析功能。 但正如 Dave Cross 指出的,您想要的表格不在您要求的 HTML 文档中。 它是由一些 JavaScript 代码生成的。 要完成浏览器所做的事情,需要一个 JavaScript 引擎,而 WWW::Mechanize 没有。

实现这一目标的最简单方法是远程控制 web 浏览器(例如使用Selenium::Chrome )。

另一种是在不获取和填写表单的情况下手动制作登录请求。

查看您的代码,我看到以下 URL:

https://imputationserver.sph.umich.edu/index.html#!pages/login

尤其是这部分引起了我的注意: #!pages/login

这可能意味着登录表单在加载时不存在于页面上,而是在页面加载后使用 JavaScript 添加到页面中。

但是,您的脚本不知道这一点,并在页面加载后立即查找登录表单及其元素。

解决此问题的最简单方法是在页面加载和尝试登录之间设置一个硬编码超时,例如 5 秒。

更“正确”的处理方式是通过检查其控件等待登录表单出现,然后继续登录过程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM