【问题标题】:PHP Mink/Zombie - page visit returns status code 0?PHP Mink/Zombie - 页面访问返回状态码 0?
【发布时间】:2016-05-27 10:13:20
【问题描述】:

我应该使用 PHP 中的 Mink 和 Zombie 驱动程序在不受我控制的服务器(HTTPS)上测试登录。问题是,每当我访问登录页面时,我大多会得到状态代码 0,因此我无法使用任何元素。我曾尝试使用 Wireshark 来检查网络流量 - 但由于它是 HTTPS,它已被加密,我不知道 Wireshark 捕获中发生了什么;我只能看到已经和服务器交换了一些数据。

我无法分享我正在尝试访问的实际页面的 URL,但我发现我可以通过 Centreon 的公开演示演示它(更多信息请参见 https://www.centreon.com/en/centreon-demo/;提前向 Centreon 道歉)。所以这是一个复制这个问题的例子(我的安装是在nodejs cannot find module 'zombie' with PHP mink):

<?php
$nodeModPath = "/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules";

# composer autoload:
require_once __DIR__ . '/vendor/autoload.php';

$URL = "http://demo.centreon.com/centreon";
$USERNAME = "admin";
$PASSWORD = "centreon";
$LFID = "useralias";
$PFID = "password";
$BFID = "submitLogin";


$zsrv = new \Behat\Mink\Driver\NodeJS\Server\ZombieServer();
$zsrv->setNodeModulesPath($nodeModPath . "/"); # needs to end with a trailing '/'
$driver = new \Behat\Mink\Driver\ZombieDriver( $zsrv );
$session = new \Behat\Mink\Session($driver);

// start the session
$session->start();
$session->setRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2049.0 Safari/537.36');

//~ $session->visit($URL);

$statcode = 0;
while ($statcode != 200) {
  $isleep = rand(2, 7); echo "sleeping $isleep sec...\n";
  sleep($isleep);
  $session->visit($URL);
  $statcode = $session->getStatusCode();
  echo "  current URL: " . $session->getCurrentUrl() ."\n";
  echo "  status code: " . $statcode ."\n";
}


$page = $session->getPage();
$el_login = $page->findField($LFID);
$el_password = $page->findField($PFID);
$el_button = $page->find('xpath', '//*[@name="'.$BFID.'"]');//findById($BFID);//findField($BFID);
//~ var_dump($el_button);

$el_login->setValue($USERNAME);
$el_password->setValue($PASSWORD);

echo "  pressing/clicking login button\n";
$el_button->click();

echo "Page URL after click: ". $session->getCurrentUrl() . "\n";
$page = $session->getPage();
?>

现在,当我运行这个脚本时,我通常会得到:

$ php test_php_mink.php 
sleeping 4 sec...
  current URL: https://demo.centreon.com/centreon/
  status code: 0
sleeping 4 sec...
  current URL: https://demo.centreon.com/centreon/
  status code: 0
sleeping 5 sec...
  current URL: https://demo.centreon.com/centreon/
  status code: 0
...

值得注意的是,在此过程中,如果我在浏览器中刷新相同的 URL,它会正确返回页面(因此状态为 200)。

非常非常罕见,我实际上可以在脚本中以状态 200 和整页加载的结果得到这个结果;但是一旦我再次尝试,我再次获得状态 0 - 这是其中的一个 sn-p(带有一个额外的 JavaScript 错误,这似乎与站点相关):

$ php test_php_mink.php 
sleeping 7 sec...
  current URL: https://demo.centreon.com/centreon/
  status code: 0
sleeping 4 sec...
  current URL: https://demo.centreon.com/centreon/
  status code: 200
  pressing/clicking login button
PHP Fatal error:  Uncaught exception 'Behat\Mink\Exception\DriverException' with message 'Error while processing event 'click': "ReferenceError: Effect is not defined\n    at https://demo.centreon.com/centreon/include/common/javascript/modalbox.js:517:1\n    at Object.exports.runInContext (vm.js:44:17)\n ...

谁能解释导致这种行为的原因 - 有什么我可以以可靠的方式在脚本中正确检索页面的吗?

【问题讨论】:

    标签: php node.js mink


    【解决方案1】:

    嗯,我发现了一些东西,但我真的不确定事情应该如何工作 - 所以一个更博学的答案将不胜感激。

    无论如何,我做了一些试验,最终我发现$session-&gt;getStatusCode()(很可能)在./vendor/behat/mink-zombie-driver/src/ZombieDriver.php 中定义为:

    public function getStatusCode()
    {
        return (int) $this->server->evalJS('browser.statusCode', 'json');
    }
    

    所以,基本上,它读取 JavaScript 属性 browser.statusCode。事实证明,如果我们等待这个状态码改变的时间足够长,那么页面加载就会继续,最后我得到状态码 200(同样,这是针对普通浏览器总是正确读取页面的情况,从而确认网络是为了)。这是我所做的更改:

    $statcode = 0;
    while ($statcode != 200) {
      $isleep = rand(2, 7); echo "sleeping $isleep sec...\n";
      sleep($isleep);
      $session->visit($URL);
      // $session->wait(20000, '(0 === jQuery.active)'); # Uncaught exception 'RuntimeException' with message 'Could not establish connection: Connection refused (111)'
      $session->wait(20000, '(browser.statusCode > 0)'); ### THIS makes things work?!
      $statcode = $session->getStatusCode();
      echo "  current URL: " . $session->getCurrentUrl() ."\n";
      echo "  status code: " . $statcode ."\n";
    }
    

    注意:

    • 我在How to make Behat wait for an AJAX call? 上找到了等待条件(0 === jQuery.active);然而在这里它似乎导致'RuntimeException' with message 'Could not establish connection: Connection refused (111)'
    • 即使使用(browser.statusCode &gt; 0) 等待条件,如果我只使用随机睡眠延迟,即wait($isleep, '(browser.statusCode &gt; 0)');,它也会像在OP 中一样失败——这可能是因为$isleep 以秒为单位,而wait() 预计为毫秒;在我将等待时间显式设置为 20000(毫秒 = 20 秒;脚本完成得比这更快)后,脚本开始工作。

    现在,在过去 10-15 次我运行脚本时,我得到了这个:

    $ php test_php_mink_timeout.php 
    sleeping 6 sec...
      current URL: https://demo.centreon.com/centreon/
      status code: 200
      pressing/clicking login button
    PHP Fatal error:  Uncaught exception 'Behat\Mink\Exception\DriverException' with message 'Error while processing event 'click': "ReferenceError: Effect is not defined\n    at https://demo.centreon.com/centreon/include/common/javascript/modalbox.js:517:1\n    at Object.exports.runInContext (vm.js:44:17)\n    at window._evaluate (/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/zombie/lib/document.js:253:75)\n ...
    

    ... 这看起来好像连接/状态代码 0 问题已通过此 wait() 解决。但是,还有另一个问题 - 找不到页面使用的 JavaScript 类之一,程序崩溃了 - 更糟糕的是,后台挂着 mink 进程,直到我 kill 他们,我不能再次运行脚本。但我会为此发布另一个问题......并且这样做了,在这里:PHP Mink/Zombie - handling hanging processes after a fatal exception?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-29
      • 2014-07-01
      • 2015-05-12
      • 2019-07-15
      • 1970-01-01
      • 2011-05-07
      • 1970-01-01
      • 2021-06-09
      相关资源
      最近更新 更多