使用RegEx提取表单字段

Ali*_*xel 1 html php 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');
Run Code Online (Sandbox Code Playgroud)

有人能为我提供必要的正则表达式吗?

编辑:我理解查询DOM将更加可靠,但我正在寻找的是一个网站无关的解决方案,允许我获取给定表单的所有字段.在不知道文档节点的情况下,我不相信这是可能的,我错了吗?

我不需要防弹解决方案,只需要在标准网页上运行的东西,对于FORM标签,我提出了以下RegEx;

'~<form.*?name=[\'"]?' . $name . '[\'"]?.*?>(.+?)</form>~is'
Run Code Online (Sandbox Code Playgroud)

我相信为输入字段做类似的操作并不困难,我发现最具挑战性的是select和option字段的RegEx.

Pas*_*TIN 7

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

您可以查看DOMDocument :: loadHTML,它允许您使用DOM方法处理HTML文档(例如,如果您知道那些,则使用XPath查询).

你可能也想看看Zend_DomZend_Dom_Query,顺便说一句,这是相当不错的,如果你可以在你的应用程序中使用Zend框架的某些部分.
例如,它们用于在进行功能测试时从HTML页面获取数据Zend_Test- 并且工作得很好;-)

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


在评论和编辑OP之后编辑

这里有一些想法,从"简单"开始,一个输入标签:

  • 它可以跨越几条线传播
  • 它可以有很多属性
  • 只考虑名称和价值是你感兴趣的,你必须处理这两个可能是任何可能的顺序的事实
  • 属性可以有双引号,单引号,甚至没有任何值
  • 标签/属性可以是小写的也可以是大写的
  • 标签并不总是必须关闭

好吧,其中一些点无效 - HTML; 但仍然在大多数公共网络浏览器中工作,所以必须考虑到它们......

只有这些点,我不想成为写正则表达式的人^^
但我想可能还有其他一些我没想到的困难.


另一方面,你有DOM和xpath ...要获得输入名称="q"的值(例如这个页面),这是一个类似这样的事情:

$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...
}
Run Code Online (Sandbox Code Playgroud)

重要的是什么?XPath查询,只有...并且它有什么静态/常量吗?
好吧,我说我希望所有<input>具有name等于" q" 的属性.
它只是起作用:我得到了这个结果:

string 'test' (length=4)
string 'test' (length=4)
Run Code Online (Sandbox Code Playgroud)

(我查了一下:页面上有两个输入名称="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...
}
Run Code Online (Sandbox Code Playgroud)

我得到一个输出:

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)
Run Code Online (Sandbox Code Playgroud)

这是我的预期.


一些解释?

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

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

哦,作为旁注:我仍然不知道HTML文档的结构是什么样的:我甚至没有看过它的源代码^^


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

还是:玩得开心!