我正在寻找一种方法来获取给定特定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'
我相信为输入字段做类似的事情并不困难,我发现最具挑战性的是选择和选项字段的RegEx。
答案 0 :(得分:7)
使用正则表达式解析HTML可能不是最好的方法。
您可以查看DOMDocument::loadHTML,这将允许您使用DOM方法处理HTML文档(例如,如果您知道这些,则使用XPath查询)。
您可能还想查看Zend_Dom
和Zend_Dom_Query
,顺便说一下,如果您可以在应用程序中使用Zend Framework的某些部分,这些都非常好。
例如,在使用Zend_Test
进行功能测试时,它们用于从HTML页面获取数据 - 并且工作得很好; - )
首先看起来似乎更难......但是,考虑到一些HTML页面的混乱,它可能是一个更明智的想法......
评论和编辑OP后编辑
以下是一些关于“简单”的输入标记的想法:
好吧,其中一些点无效 - HTML;但仍然在大多数公共网络浏览器中工作,因此必须考虑它们......
只有那些点,我不想成为写正则表达式的人^^
但我想可能还有其他一些我没想过的困难。
另一方面,你有DOM和xpath ...要获得输入名称=“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)
(我查了一下:页面上有两个输入名称=“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时不是一个好主意......也许吧?的; - )强>
仍然:玩得开心!