在 PHP Mink 中选择没有 id 的表单元素?
Selecting form element without id in PHP Mink?
我正在试验 PHP Mink(安装在 nodejs cannot find module 'zombie' with PHP mink 上)。我正在尝试解析一个网页(我无法控制),它在表单中有一个这样的元素:
<input tabindex="5" value="Do Submit!" class="my_btn my_btn_2" type="submit"></input>
值得注意的是,这个 <input>
既没有 id
也没有 name
,所以我找不到 select 这个元素的方法。
我宁愿避免使用 XPath,因为我不想专门指定一个层次结构路径,它在未来很可能会发生变化。我最想在表单中查找 child,它有一个 value
属性,值为 Do Submit!
,但我不知道如何在 Mink 中指定它?
我创建了一个最小的例子来证明这一点;这是 HTML 文件:
selbtnnoid.htm
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
.my_form {
width: 50%;
border: 2px solid red;
}
.my_label {
font-size: large;
}
.my_input_2 {
font-size: medium;
}
.my_btn {
background-color: yellow;
}
.my_btn_2 {
font-size: large;
}
</style>
</head>
<body>
<h1>Hello World!</h1>
<p>Here is the form:</p>
<form method="post" action="wherever.php" id="my-form" class="my_form">
<h1>Some form here:</h1>
<p>
<label for="my-input-txt">
<span class="my_label">Some data:</span>
<input name="my-input-txt" id="my-input-txt" placeholder=" Enter data. " class="my_input_2" tabindex="1" type="text"></input>
</label>
</p>
<p>
<input tabindex="5" value="Do Submit!" class="my_btn my_btn_2" type="submit"></input>
</p>
</form>
</body>
</html>
... 这是 PHP 文件:
test_php_mink_selbtnnoid.php
<?php
$nodeModPath = "/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules";
putenv("NODE_PATH=".$nodeModPath); # doesn't really help; use setNodeModulesPath
# composer autoload for mink:
require_once __DIR__ . '/vendor/autoload.php';
$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->visit('selbtnnoid.htm'); // nope; status code: 0 if just called locally
//~ $session->visit('file:///path/to/selbtnnoid.htm'); // nope; Error: listen EADDRINUSE 127.0.0.1:8124
$session->visit('http://localhost:8090/selbtnnoid.htm'); // run php -S localhost:8090 in the folder with these two files
echo " current URL: " . $session->getCurrentUrl() ."\n";
echo " status code: " . $session->getStatusCode() ."\n";
$page = $session->getPage();
$myForm = $page->findById("my-form");
$myInput = $myForm->findField("my-input-txt");
# check if we have the element: // yes, displays 'my input tag is: input'
echo "my input tag is: ". $myInput->getTagName() ."\n";
# try to get the button:
$myBtn = $myForm->findField("Do Submit!");
echo "button selected by value is: " . var_export($myBtn, true) ."\n"; // NULL
$myBtn = $myForm->find('css', 'my_btn');
echo "button selected by css is: " . var_export($myBtn, true) ."\n"; // NULL
?>
脚本输出:
$ php test_php_mink_selbtnnoid.php
current URL: http://localhost:8090/selbtnnoid.htm
status code: 200
my input tag is: input
button selected by value is: NULL
button selected by css is: NULL
那么,我怎样才能 select / 获得对这个 HTML 文件中这个按钮元素的引用?
好吧,看来 XPath 确实有效 - 我想我设法找到了一个查询,它不一定涉及从文档的根部写下到元素的整个路径;但我在 XPath 方面真的很糟糕,所以我仍然希望得到一个更合格的答案。无论如何,我所做的是将其添加到 OP 脚本中:
$myBtn = $myForm->find('xpath', '//*[@value="Do Submit!"]');
echo "button selected by xpath is: " . $myInput->getTagName() . "; with 'value': " . $myBtn->getAttribute('value') ."\n";
... 输出:
button selected by xpath is: input; with 'value': Do Submit!
...这正是我需要的...
首先,您应该确定一个独特的部分(如果有),然后确定您的元素。
以下是一些可能的选择器:
css: #my-form input[type=submit]
css: #my-form input.my_btn
css: #my-form input.my_btn_2
xpath: //*[@id='my-form']//input[@type='submit']
xpath: //*[@id='my-form']//input[contains(@class, 'my_btn')]
如果您在页面中只有一个独特的输入,您可以删除 "my-form" 部分。
在任何情况下(xss、xpath)您都不必指定层次结构路径,这对于自动化来说可能是一种不好的做法。如果您知道它可能 change/translate.
,请尽量避免在选择器中使用文本
我正在试验 PHP Mink(安装在 nodejs cannot find module 'zombie' with PHP mink 上)。我正在尝试解析一个网页(我无法控制),它在表单中有一个这样的元素:
<input tabindex="5" value="Do Submit!" class="my_btn my_btn_2" type="submit"></input>
值得注意的是,这个 <input>
既没有 id
也没有 name
,所以我找不到 select 这个元素的方法。
我宁愿避免使用 XPath,因为我不想专门指定一个层次结构路径,它在未来很可能会发生变化。我最想在表单中查找 child,它有一个 value
属性,值为 Do Submit!
,但我不知道如何在 Mink 中指定它?
我创建了一个最小的例子来证明这一点;这是 HTML 文件:
selbtnnoid.htm
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
.my_form {
width: 50%;
border: 2px solid red;
}
.my_label {
font-size: large;
}
.my_input_2 {
font-size: medium;
}
.my_btn {
background-color: yellow;
}
.my_btn_2 {
font-size: large;
}
</style>
</head>
<body>
<h1>Hello World!</h1>
<p>Here is the form:</p>
<form method="post" action="wherever.php" id="my-form" class="my_form">
<h1>Some form here:</h1>
<p>
<label for="my-input-txt">
<span class="my_label">Some data:</span>
<input name="my-input-txt" id="my-input-txt" placeholder=" Enter data. " class="my_input_2" tabindex="1" type="text"></input>
</label>
</p>
<p>
<input tabindex="5" value="Do Submit!" class="my_btn my_btn_2" type="submit"></input>
</p>
</form>
</body>
</html>
... 这是 PHP 文件:
test_php_mink_selbtnnoid.php
<?php
$nodeModPath = "/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules";
putenv("NODE_PATH=".$nodeModPath); # doesn't really help; use setNodeModulesPath
# composer autoload for mink:
require_once __DIR__ . '/vendor/autoload.php';
$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->visit('selbtnnoid.htm'); // nope; status code: 0 if just called locally
//~ $session->visit('file:///path/to/selbtnnoid.htm'); // nope; Error: listen EADDRINUSE 127.0.0.1:8124
$session->visit('http://localhost:8090/selbtnnoid.htm'); // run php -S localhost:8090 in the folder with these two files
echo " current URL: " . $session->getCurrentUrl() ."\n";
echo " status code: " . $session->getStatusCode() ."\n";
$page = $session->getPage();
$myForm = $page->findById("my-form");
$myInput = $myForm->findField("my-input-txt");
# check if we have the element: // yes, displays 'my input tag is: input'
echo "my input tag is: ". $myInput->getTagName() ."\n";
# try to get the button:
$myBtn = $myForm->findField("Do Submit!");
echo "button selected by value is: " . var_export($myBtn, true) ."\n"; // NULL
$myBtn = $myForm->find('css', 'my_btn');
echo "button selected by css is: " . var_export($myBtn, true) ."\n"; // NULL
?>
脚本输出:
$ php test_php_mink_selbtnnoid.php
current URL: http://localhost:8090/selbtnnoid.htm
status code: 200
my input tag is: input
button selected by value is: NULL
button selected by css is: NULL
那么,我怎样才能 select / 获得对这个 HTML 文件中这个按钮元素的引用?
好吧,看来 XPath 确实有效 - 我想我设法找到了一个查询,它不一定涉及从文档的根部写下到元素的整个路径;但我在 XPath 方面真的很糟糕,所以我仍然希望得到一个更合格的答案。无论如何,我所做的是将其添加到 OP 脚本中:
$myBtn = $myForm->find('xpath', '//*[@value="Do Submit!"]');
echo "button selected by xpath is: " . $myInput->getTagName() . "; with 'value': " . $myBtn->getAttribute('value') ."\n";
... 输出:
button selected by xpath is: input; with 'value': Do Submit!
...这正是我需要的...
首先,您应该确定一个独特的部分(如果有),然后确定您的元素。 以下是一些可能的选择器:
css: #my-form input[type=submit]
css: #my-form input.my_btn
css: #my-form input.my_btn_2
xpath: //*[@id='my-form']//input[@type='submit']
xpath: //*[@id='my-form']//input[contains(@class, 'my_btn')]
如果您在页面中只有一个独特的输入,您可以删除 "my-form" 部分。 在任何情况下(xss、xpath)您都不必指定层次结构路径,这对于自动化来说可能是一种不好的做法。如果您知道它可能 change/translate.
,请尽量避免在选择器中使用文本