php - 使用 RegEx 提取表单字段

标签 php html regex forms

我正在寻找一种方法,从给定特定 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/

相关文章:

java - 使用正则表达式从字符串中提取多个值

php - 警告:mysqli::query():空查询

php - MySQL 从一个单独的表中选择一个键

html - 标题元素中的换行符

javascript - 如何使用jquery向基本 Accordion 添加加减号?

c# - 如何匹配正则表达式中以空格分隔的所有单词?

regex - 当 XACML 谈到 "regexp-match"时,它指的是哪个正则表达式规则?

php - jeditable 正在更新 mysql 但在我的 php 中返回 header

php - 如何在 Windows 上使用命令行访问 PHP?

javascript - 位置 :fixed difference in IE Vs Firefox