我正在寻找一种方法,从给定特定 URL 和表单名称的页面获取所有表单输入和相应值。
function GetForm($url, $name)
{
return array
(
'field_name_1' => 'value_1',
'field_name_2' => 'value_2',
'select_field_name' => array('option_1', 'option_2', 'option_3'),
);
}
GetForm('http://www.google.com/', 'f');
任何人都可以为我提供必要的正则表达式来完成这个吗?
编辑:我知道查询 DOM 会更可靠,但我正在寻找的是一个与网站无关的解决方案,它允许我获取给定表单的所有字段。我不相信在不首先了解文档节点的情况下使用 DOM 是不可能的,我错了吗?
我不需要防弹解决方案,只需要在标准网页上工作的东西,对于 FORM 标签,我已经用以下 RegEx 提出了;
'~<form.*?name=[\'"]?' . $name . '[\'"]?.*?>(.+?)</form>~is'
我相信为输入字段做类似的事情并不困难,我发现最具挑战性的是选择和选项字段的正则表达式。
最佳答案
使用正则表达式解析 HTML 可能不是最好的方法。
你可以看看DOMDocument::loadHTML ,这将允许您使用 DOM 方法(以及 XPath 查询,例如,如果您知道的话)来处理 HTML 文档。
您可能还想看看 Zend_Dom
和 Zend_Dom_Query
, 顺便说一句,如果您可以在您的应用程序中使用 Zend Framework 的某些部分,那将是非常好的。
它们用于在使用 Zend_Test
进行功能测试时从 HTML 页面获取数据。 , 例如——并且工作得很好;-)
一开始可能看起来更难......但是,考虑到一些 HTML 页面的困惑,这可能是一个更明智的想法......
在评论和编辑 OP 之后编辑
这里有一些想法,从一些“简单”的东西开始,一个输入标签:
- 它可以分布在多条线路上
- 它可以有很多属性
- 假设您只对 name 和 value 感兴趣,您必须处理这两个可以以任何可能的顺序排列的事实
- 属性的值可以有双引号、单引号,甚至什么也没有
- 标签/属性可以是小写或大写
- 标签不一定要关闭
好吧,其中一些点是无效的 HTML;但仍然可以在最常见的网络浏览器中工作,因此必须考虑到它们......
只有这些点,我不想成为编写正则表达式的人 ^^
但我想可能还有其他我没有想到的困难。
另一方面,你有 DOM 和 xpath ......要获得输入 name="q"的值(例如 this page ),这是一个类似这样的问题:
$url = 'http://www.google.fr/search?q=test&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a';
$html = file_get_contents($url);
$dom = new DOMDocument();
if (@$dom->loadHTML($html)) {
// yep, not necessarily valid-html...
$xpath = new DOMXpath($dom);
$nodeList = $xpath->query('//input[@name="q"]');
if ($nodeList->length > 0) {
for ($i=0 ; $i<$nodeList->length ; $i++) {
$node = $nodeList->item($i);
var_dump($node->getAttribute('value'));
}
}
} else {
// too bad...
}
这里重要的是什么? XPath 查询,仅此而已……其中是否有任何静态/常量?
好吧,我说我要全部<input>
有一个 name
等于“q
”的属性。
它确实有效:我得到了这个结果:
string 'test' (length=4)
string 'test' (length=4)
(我查了一下:页面上有两个input name="q"^^)
我知道页面的结构吗?绝对不是 ;-)
我只知道我/你/我们想要名为 q 的输入标签 ;-)
这就是我们得到的 ;-)
编辑 2:选择和选项有点有趣:
好吧,只是为了好玩,这里是我想出的选择和选项:
$url = 'http://www.google.fr/language_tools?hl=fr';
$html = file_get_contents($url);
$dom = new DOMDocument();
if (@$dom->loadHTML($html)) {
// yep, not necessarily valid-html...
$xpath = new DOMXpath($dom);
$nodeListSelects = $xpath->query('//select');
if ($nodeListSelects->length > 0) {
for ($i=0 ; $i<$nodeListSelects->length ; $i++) {
$nodeSelect = $nodeListSelects->item($i);
$name = $nodeSelect->getAttribute('name');
$nodeListOptions = $xpath->query('option[@selected="selected"]', $nodeSelect); // We want options that are inside the current select
if ($nodeListOptions->length > 0) {
for ($j=0 ; $j<$nodeListOptions->length ; $j++) {
$nodeOption = $nodeListOptions->item($j);
$value = $nodeOption->getAttribute('value');
var_dump("name='$name' => value='$value'");
}
}
}
}
} else {
// too bad...
}
我得到的输出是:
string 'name='sl' => value='fr'' (length=23)
string 'name='tl' => value='en'' (length=23)
string 'name='sl' => value='en'' (length=23)
string 'name='tl' => value='fr'' (length=23)
string 'name='sl' => value='en'' (length=23)
string 'name='tl' => value='fr'' (length=23)
这是我所期望的。
一些解释?
好吧,首先,我得到页面的所有选择标签,并将它们的名字保存在内存中。
然后,对于其中的每一个,我都会得到选定的选项标签,它们是它的后代(顺便说一句,总是只有一个)。
在这里,我有值(value)。
比前面的例子复杂一点...但仍然比正则表达式容易得多,我相信...花了我大概 10 分钟,而不是更多...而且我仍然没有勇气(疯狂? ) 开始思考某种能够做到这一点的突变正则表达式:-D
哦,还有,作为旁注:我仍然不知道 HTML 文档的结构是什么样的:我什至没有看一眼它的来源 ^^
我希望这会有所帮助......
谁知道,也许我会说服你正则表达式在解析 HTML 时不是一个好主意……也许吧? ;-)
仍然:玩得开心!
关于php - 使用 RegEx 提取表单字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1274020/