【问题标题】:Extract form fields using RegEx使用 RegEx 提取表单字段
【发布时间】:2009-08-13 19:16:11
【问题描述】:

我正在寻找一种方法来从给定特定 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 解析库将适当的 DOM 节点模式化为关联数组。那些人是对的。不要使用正则表达式来解析 HTML。

标签: php html regex forms


【解决方案1】:

使用正则表达式解析 HTML 可能不是最好的方法。

您可以查看DOMDocument::loadHTML,它允许您使用 DOM 方法(以及 XPath 查询,如果您知道的话)来处理 HTML 文档。

您可能还想看看Zend_DomZend_Dom_Query,顺便说一句,如果您可以在您的应用程序中使用Zend Framework 的某些部分,它们会非常好。
例如,在使用 Zend_Test 进行功能测试时,它们用于从 HTML 页面获取数据——并且工作得很好;-)

一开始可能看起来更难...但是,考虑到一些 HTML 页面的混乱,这可能是一个更明智的想法...


在评论和 OP 编辑​​之后编辑

这里有几个想法,从“简单”的东西开始,一个输入标签:

  • 它可以跨多行传播
  • 它可以有很多属性
  • 您只对名称和值感兴趣,您必须处理这两个可以按任何可能的顺序排列的事实
  • 属性的值可以有双引号、单引号,甚至没有任何内容
  • 标签/属性既可以是小写也可以是大写
  • 标签不必总是关闭

好吧,其中一些点是无效的-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 查询,仅此而已……其中是否有任何静态/常量?
好吧,我说我想要所有&lt;input&gt;name 属性等于“q”。
而且它确实有效:我得到了这个结果:

string 'test' (length=4)
string 'test' (length=4)

(我查过:页面上有两个输入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)

这是我所期望的。


一些解释?

嗯,首先,我获取页面的所有选择标签,并将它们的名称保存在内存中。
然后,对于其中的每一个,我都会获得作为其后代的选定选项标签(总是只有一个,顺便说一句)。
在这里,我有价值。

比前面的例子复杂一点...但我相信仍然比正则表达式容易得多...花了我大概 10 分钟,而不是更多...而且我仍然没有勇气(疯狂? )开始考虑某种能够做到这一点的突变正则表达式:-D

哦,顺便说一句:我仍然不知道 HTML 文档的结构是什么样的:我什至没有看过它的源代码 ^^


我希望这可以帮助更多...
谁知道呢,也许我会说服你在解析 HTML 时,正则表达式不是一个好主意......也许吧? ;-)

仍然:玩得开心!

【讨论】:

  • 我已经多次编辑我的答案,举几个例子,使用 XPath 来输入和选择+选项标签。希望这会有所帮助:-) - 抱歉,但我绝对不会尝试编写任何正则表达式来做到这一点;不想在假期前几天发疯^^
猜你喜欢
  • 2015-10-04
  • 1970-01-01
  • 1970-01-01
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-25
  • 1970-01-01
相关资源
最近更新 更多