php DOMNode-> nodeValue无法正常工作

时间:2012-05-10 23:14:36

标签: php dom encoding

我正在使用DOM来解析一些网站。 我正在解析这个:

<option value="A26JUYT14N57PY">Aleksander&#39;s Kindle Cloud Reader</option>
<option value="A13400OMTGFDRH">Aleksander&#39;s Kindle for PC</option>
<optgroup label="----OR----" style="color:#999;font-style:normal;font-weight:normal"> </optgroup>
<option value="add-new">Register a new Kindle</option>

我的脚本是:

$dom->getElementsByTagName('option');
foreach($options as $option)
{
    $attr = $option->getAttribute('value');
    $value = $option->nodeValue;
}

在我的电脑上使用PHP 5.3.9,它可以正常工作:

$attr1 = "A26JUYT14N57PY";
$value1 = "Aleksander&#39;s Kindle Cloud Reader";

$attr2 = "A13400OMTGFDRH";
$value2 = "Aleksander&#39;s Kindle for PC";

$attr3 = "add-new";
$value3 = "Register a new Kindle";

但是当我在服务器上上传脚本时,它不再起作用了(我不确定它是什么PHP版本但是它&lt; 5.3.0)。结果是:

$attr1 = "A26JUYT14N57PY";
$value1 = "'";

$attr2 = "A13400OMTGFDRH";
$value2 = "'";

$attr3 = "add-new";
$value3 = "";

所以只有撇号从nodeValues中的字符串中留下 - 我认为它是带编码的东西,但我不确定......奇怪的是只有nodeValues是错的,值属性都没问题......

--------------编辑

这是代码解析网页(它使用的类的来源在上面)。 $page是CURL返回的网页的html源代码 - 我无法直接提供您的网址,因为它是在登录亚马逊后的。

$dom = HtmlDomParser::getDomFromHtml($page);    
            $form = FormDomParser::getFormByName($dom,$this->amazon_config->buy_form_name);

            if($form===false)
            {
                throw new AmazonParseException("Couldn't parse buy form");
            }

            $select = FormDomParser::getSelectByName($dom,$this->amazon_config->buy_deliveryoptions_name);
            if($select === false)
            {

                    throw new AmazonParseException("Couldn't parse options select");

            }

            $options = FormDomParser::getOptions($select);

            $result = array();
            foreach($options as $option)
            {
                //$value = $option->childNodes->item(0)->nodeValue;
                //print_r($value);

                $device_id = $option->getAttribute('value');
                $device_name = $option->nodeValue;

                echo $device_id.' = '.$device_name.'</br>';


            }

HtmlDomParser

// simples class for parsing html files with DOM
    class HtmlDomParser
    {
        // converts html (as string) to DOM object
        public static function getDomFromHtml($html)
        {
            $dom = new DOMDocument;
            $dom->loadHTML($html);
            return $dom;
        }

        // gets all occurances of specified tag from dom object
        // these tags must contain specified (in attributes array) attributes
        public static function getTagsByAttributes($dom,$tag,$attributes = array())
        {
            $result = array();
            $elements = $dom->getElementsByTagName($tag);

            foreach($elements as $element)
            {
                $attributes_ok = true;
                foreach($attributes as $key => $value)
                {
                    if($element->getAttribute($key)!=$value)
                    {
                        $attributes_ok = false;
                        break;
                    }
                }

                if($attributes_ok)
                {
                    $result[] = $element;
                }
            }
            return $result;
        }
    }

FormDomParser

class FormDomParser
    {
        // gets form (as dom object) with specified name
        public static function getFormByName($dom,$form_name)
        {
            $attributes['name'] = $form_name;
            $forms = HtmlDomParser::getTagsByAttributes($dom,'form',$attributes);
            if(count($forms)<1)
            {
                return false;
            }
            else
            {
                return $forms[0];
            }
        }

        // gets all <input ...> tags from specified DOM object
        public static function getInputs($dom)
        {
            $inputs = HtmlDomParser::getTagsByAttributes($dom,'input');
            return $inputs;
        }

        // internal / converts array of Dom objects into assiosiative array
        public static function convertInputsToArray($inputs)
        {
            $inputs_array = array();
            foreach($inputs as $input)
            {
                $name = $input->getAttribute('name');
                $value = $input->getAttribute('value');

                if($name!='')
                {
                    $inputs_array[$name] = $value;
                }
            }   
            return $inputs_array;
        }


        // gets all <select ...> tags from DOM object
        public static function getSelects($dom)
        {
            $selects = HtmlDomParser::getTagsByAttributes($dom,'select');
            return $selects;
        }

        // gets <select ...> tag with specified name from DOM object
        public static function getSelectByName($dom,$name)
        {
            $attributes['name'] = $name;
            $selects = HtmlDomParser::getTagsByAttributes($dom,'select',$attributes);
            if(count($selects)<1)
            {
                return false;
            }
            else
            {
                return $selects[0];
            }
        }

        // gets <option ...> tags from DOM object
        public static function getOptions($dom)
        {
            $options = HtmlDomParser::getTagsByAttributes($dom,'option');
            return $options;
        }

        // gets action value from form (as DOM object)
        public static function getAction($dom)
        {
            $action =  $dom->getAttribute('action');
            if($action == "")
            {
                return false;
            }
            else
            {
                return $action;
            }
        }
    }

---------编辑

这是我试图解析的http标头od网站(由curl返回):

HTTP/1.1 200 OK Date: Fri, 11 May 2012 08:54:23 GMT Server: Server x-amz-id-1: 
0CHN2KA4VD4FTXF7K62J p3p: policyref=&quot;http://www.amazon.com/w3c/p3p.xml&quot;,CP=&quot;CAO 
DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN 
COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC &quot; x-frame-options: SAMEORIGIN 
x-amz-id-2: fFWynUQG0oqudmoDO+2FEraC2H+wWl0p9RpOyGxwyXKOc9u/6f2v8ffWUFkaUKU6 
Vary: Accept-Encoding,User-Agent Content-Type: text/html; charset=ISO-8859-1 
Set-cookie: ubid-main=190-8691333-9825146; path=/; domain=.amazon.com; 
expires=Tue, 01-Jan-2036 08:00:01 GMT Set-cookie: session-id-time=2082787201l; 
path=/; domain=.amazon.com; expires=Tue, 01-Jan-2036 08:00:01 GMT Set-cookie: 
session-id=187-8097468-1751521; path=/; domain=.amazon.com; expires=Tue, 
01-Jan-2036 08:00:01 GMT Transfer-Encoding: chunked

----------------------- edit

我刚刚使用了http://simplehtmldom.sourceforge.net,效果很好。

4 个答案:

答案 0 :(得分:0)

问题必须是'。 DOM在XML文档上运行,你需要一个CDATA部分才能拥有&amp;值中的字符。

删除'并检查它是否有效。如果是,那么你需要CDATA

答案 1 :(得分:0)

尝试获取文本节点本身的nodeValue

$value = $option->firstChild->nodeValue;

答案 2 :(得分:0)

你可以尝试很少的东西。上传到您的服务器后再试一次。不是在你自己的机器上。

  1. 使用$dom->loadXML()$dom->loadHTML()方法进行测试。
  2. $value = $option->childNodes->item(0)->nodeValue;
  3. 上查看Kolink的答案
  4. $array = simplexml_load_string($dom->saveXML($option))并查看数组是否满足您的需求。
  5. 执行$ dom-&gt; loadHTML(html_entity_decode($ html));

答案 3 :(得分:0)

我会说(猜测)它的配置差异比PHP版本更多。这是因为有时DOMDocument会替换实体,有时也不会(在How can I use PHP's various XML libraries to get DOM-like functionality and avoid DoS vulnerabilities, like Billion Laughs or Quadratic Blowup?中攻击DOMDocument组件时也会讨论过这个问题。)

一个有趣的配置设置是LIBXML_NOENT

$doc->loadXML($src, LIBXML_NOENT);

您尚未共享任何代码,因此我不知道这是否适用于您。

你应该看一下(正如我所经历的那样),是文档的编码。重新保存文档/将其正确转换为UTF-8可能会有所帮助。如果在保存HTML时可以替换实体,则通常是。

第三个选项是您自己编写一些代码,用textnodes替换entitiy元素,然后再次规范化文档以组合可以组合的文本节点。