2016-05-05 23 views
0

我一直試圖解析一個網站,通過使用DOMelements。 一切工作正常,除了這個問題對我沒有意義。PHP - DOMelement select不返回選項值

有一個選擇框,我需要它的所有可能的選項值的內容:

<select name="super_attribute[141]" id="attribute141" class="required-entry super-attribute-select"> 
    <option value="">Choose size</option> 
    <option value="36" price="0">36</option> 
    <option value="38" price="0">38</option> 
    <option value="41" price="0">40</option> 
    <option value="43" price="0">42</option> 
    <option value="45" price="0">44</option> 
    <option value="47" price="0">46</option> 
    <option value="49" price="0">48</option> 
</select> 

我想要檢索包含值(任一個的innerHTML或「值」屬性)的陣列。我使用此代碼:

foreach ($dom->getElementsByTagName('option') as $option_tag) { 
    $sizes_list[] = $option_tag->getAttribute('value'); 
} 

但是,總是隻有一個「選項」標記返回,並且爲空值。 所以我嘗試了不同的方法:

$item_options = $dom->getElementById('attribute141'); 
print(sizeof($item_options->childNodes)); // Prints "1" 
foreach ($item_options->childNodes as $child) { 
    $sizes_list[] = $child->getAttribute('value'); 
} 
$cloth_item->setSizes($sizes_list); 

而且又似乎在尋找這個空單值...爲什麼我不能訪問的其餘的選項?

+0

我無法重現您的問題。我對代碼1和代碼2都有正確的值。上面是你的真正的HTML /代碼? – fusion3k

+0

是的。我一直在閱讀和進一步檢查,也許這個問題可能會在頁面加載時出現(然後我捕獲$ dom),然後它又改變了嗎? 例如,某些腳本在頁面完全加載後的一小會兒,從其他地方加載select的值。我不確定它在PHP中如何工作,但是這意味着我所持有的$ dom是「舊」嗎? – Calus

+1

你能發佈抓取頁面的真實URL嗎? – fusion3k

回答

0

從URL解析HTML頁面時,您絕對不能引用瀏覽器頁面檢查器,因爲檢查器在DOM/js解析後顯示源文件。您需要請參閱「查看頁面源代碼」瀏覽器的命令,或者 - 更好 - 要做到這一點在PHP中:

$html = file_get_contents('http://www.example.com/your/url.html'); 
file_put_contents('/Path/Local/Download/Page.html', $html); 

然後,用文本編輯器打開下載的文件看真正的HTML與你加工。

<div class="input-box"> 
    <select name="super_attribute[141]" id="attribute141" class="required-entry super-attribute-select"> 
     <option>בחר אפשרות...</option> 
    </select> 
</div> 

其他選項是由JavaScript加載:

在特定情況下,你可以因爲......只有一個<option>在加載頁面檢索只有一個<option>。它們的值以JSON格式存儲在同一頁面的腳本中。沒有一種乾淨的方式來檢索它。你可以使用PhantomJS,但是 - 你可以看到hereother Stack Overflow questions - 這種方式使用php並不容易。

一個骯髒的方式可以是這樣的:在看HTML源代碼,你可以看到你的數據的格式如下:

<script type="text/javascript"> 
    var spConfig = new Product.Config({ (...) }); 
</script> 

所以,你可以檢索所有<script>節點和搜索new Product.Config值。

純DOM:

$nodes = $dom->getElementsByTagName('script'); // Result: 70 nodes 

使用DOMXPath

$xpath = new DOMXPath($dom); 
$nodes = $xpath->query('//script[@type="text/javascript"]'); // Result: 58 nodes 

然後,遍歷所有節點,找到一個正則表達式模式,並對其進行解碼:

foreach($nodes as $node) 
{ 
    if(preg_match('~new Product\.Config\((.+?)\);~', $node->nodeValue, $matches)) 
    { 
     $data = json_decode($matches[1]); 
     break; 
    } 
} 

在這一點,在$data你有這個解碼的JSON:

stdClass Object 
(
    [attributes] => stdClass Object 
     (
      [141] => stdClass Object 
       (
        [id] => 141 
        [code] => size 
        [label] => מידה 
        [options] => Array 
         (
          [0] => stdClass Object 
           (
            [id] => 36 
            [label] => 36 
            [price] => 0 
            [oldPrice] => 0 
            [products] => Array 
             (
              [0] => 93548 
             ) 
           ) 
          (...) 
         ) 
       ) 
     ) 
) 

因此,要獲得第一<option> ID,您可以使用此:

echo $data->attributes->{141}->options[0]->id; // Output: 36 
#      ↑ note curly brackets to access to a not-valid property key 

等等:

echo $data->attributes->{141}->options[1]->id; // Output: 38 
echo $data->attributes->{141}->options[1]->label; // Output: 38 
echo $data->attributes->{141}->options[1]->price; // Output: 0 
+0

非常感謝!這很有見地。 :) – Calus