2009-08-13 33 views
1

我正在尋找一種方法,可以從給定特定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會更可靠,但是我正在尋找的是一個網站無關的解決方案,讓我得到一個給定形式的所有領域。如果不先知道文檔節點,我不相信這是可能的,我錯了嗎?

我不需要防彈解決方案,只需要在標準網頁上工作,FORM標籤我已經提出了以下RegEx;

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

我認爲,這樣做對於輸入字段類似的東西不會很難,我覺得最有挑戰性的是正則表達式的選擇和選項字段。

+5

人們會告訴你使用一個html解析庫來將適當的DOM節點模式化爲一個關聯數組。那些人是對的。不要使用正則表達式來解析HTML。 – 2009-08-13 19:19:27

回答

7

使用正則表達式來解析HTML可能不是最好的方法。

你可以看看DOMDocument::loadHTML,它可以讓你使用DOM方法處理HTML文檔(例如,如果你知道的話,也可以使用XPath查詢)。

您可能還想看看Zend_DomZend_Dom_Query,順便說一句,如果您可以在您的應用程序中使用Zend Framework的某些部分,這是非常好的。
它們被用來獲取做functionnal測試時Zend_Test,例如從HTML頁面獲取數據 - 而且工作得非常好;-)

這似乎在首位更難...但是,考慮到一塌糊塗一些HTML頁面,這可能是一個更明智的想法...評論後


編輯和OP的編輯

這裏有幾個關於思想的,被什麼東西開始「簡單」,輸入標籤:

  • 它可以傳播翻過幾行
  • 它可以有很多屬性
  • condirering只有名稱和價值是你的興趣,你不得不面對的事實,這兩個可以在任何可能的順序
  • 屬性可以有雙引號,單引號,甚至沒有任何角落找尋他們的價值觀
  • 標籤/屬性既可以是小寫或大寫
  • 標籤不總是被關閉

那麼,其中的一些點是無效的 - 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查詢,並且只有那個...並且裏面有靜態/常量嗎?
好吧,我說我希望有一個name屬性等於「q」所有<input>
,它就可以工作:我得到這個結果:

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

(我查了一下:有兩個輸入名稱=「Q」的頁面上^^)

我認識的頁面的結構?是絕對不;-)
我只知道我/你/我們要爲q ;-)

這就是我們得到的;-)


EDIT 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) 

這是我的預期。


一些解釋嗎?

好吧,首先,我得到的頁面的所有選擇標籤,並保持他們的名字在內存中。
然後,對於每個人,我得到的是它的後代(有永遠只有一個,BTW)所選擇的選項標籤。
在這裏,我有價值。

複雜一點,前面的例子...但仍然比正則表達式容易,我相信...也許10分鐘,而不是更多...我仍然不會有勇氣(瘋狂?)開始思考某種能夠做到這一點的突變正則表達式:-D

噢,作爲旁註:我仍然不知道HTML文檔的結構是什麼樣的:我有即使不採取單​​看它的源^^


我希望這有助於更多一點......
誰知道呢,也許我會說服你的正則表達式是不是一個很好的ID當涉及到解析HTML ...也許? ;-)

還有:玩得開心!

+0

謝謝,但請閱讀我上面的編輯。 – 2009-08-13 20:17:37

+0

我已經編輯了幾次我的答案,給出了幾個使用XPath的示例進行輸入並選擇+選項標記的示例。希望這有助於:-) - 對不起,但我肯定不會嘗試寫任何正則表達式來做到這一點;在我的假期前幾天不想結束瘋狂^^ – 2009-08-13 20:48:25