在php中将html数据解析为数组数据

在php中将html数据解析为数组数据,php,arrays,laravel-5.4,Php,Arrays,Laravel 5.4,我试图使用标记类将html格式的数据解析为数组,但无法获得所需的格式。下面是我的数据 $text ='<div class="result results_links results_links_deep web-result "> <div class="links_main links_deep result__body"> <h2 class="result__title"> <a rel="nofollow" class=

我试图使用标记类将html格式的数据解析为数组,但无法获得所需的格式。下面是我的数据

$text ='<div class="result results_links results_links_deep web-result ">
  <div class="links_main links_deep result__body">
    <h2 class="result__title">
      <a rel="nofollow" class="result__a" href="">Text1</a> 
    </h2>
    <a class="result__snippet" href="">Text1</a> 
    <a class="result__url" href="">
    example.com
    </a>
  </div>
</div>

<div class="result results_links results_links_deep web-result ">
  <div class="links_main links_deep result__body">
    <h2 class="result__title">
      <a rel="nofollow" class="result__a" href="">text3</a> 
    </h2>
    <a class="result__snippet" href="">text23</a> 
    <a class="result__url" href="">
    text.com
    </a>
  </div>
</div>';
但我需要的结果与下面完全相同

array:2 [
  0 => array:3 [
    0 => "Text1"
    1 => "Text1"
    2 => "example.com"
  ]
  1 => array:3 [
    0 => "text3"
    1 => "text23"
    2 => "text.com"
  ]
]
演示:

就连我在拉雷维尔也在尝试下面的dom:

$dom = new DOMDocument;
$dom->loadHTML($text);
foreach($dom->getElementsByTagName('a') as $node)
{
    $array[] = $dom->saveHTML($node);
}

print_r($array);

因此,我如何使用这些类来分离我想要的数据。请提供任何建议。谢谢。

在这里,尝试一下,如果需要更多帮助,请告诉我:

<?php
$test = <<<EOS
<div class="result results_links results_links_deep web-result ">
  <div class="links_main links_deep result__body">
    <h2 class="result__title">
      <a rel="nofollow" class="result__a" href="">Text1</a>
    </h2>
    <a class="result__snippet" href="">Text1</a>
    <a class="result__url" href="">
    example.com
    </a>
  </div>
</div>

<div class="result results_links results_links_deep web-result ">
  <div class="links_main links_deep result__body">
    <h2 class="result__title">
      <a rel="nofollow" class="result__a" href="">text3</a>
    </h2>
    <a class="result__snippet" href="">text23</a>
    <a class="result__url" href="">
    text.com
    </a>
  </div>
</div>
EOS;

$document = new DOMDocument();
$document->loadHTML($test);

// first extract all the divs with the links_deep class
$divs = [];
foreach ($document->getElementsByTagName('div') as $div) {
    $classes = $div->attributes->getNamedItem('class')->nodeValue;
    if (!$classes) continue;

    $classes = explode(' ', $classes);

    if (in_array('links_main', $classes)) {
        $divs[] = $div;
    }
}

// now iterate through them and retrieve all the links in order
$results = [];
foreach ($divs as $div) {
    $temp = [];
    foreach ($div->getElementsByTagName('a') as $link) {
        $temp[] = $link->nodeValue;
    }
    $results[] = $temp;
}

var_dump($results);

给你,试试这个,如果你需要更多帮助,告诉我:

<?php
$test = <<<EOS
<div class="result results_links results_links_deep web-result ">
  <div class="links_main links_deep result__body">
    <h2 class="result__title">
      <a rel="nofollow" class="result__a" href="">Text1</a>
    </h2>
    <a class="result__snippet" href="">Text1</a>
    <a class="result__url" href="">
    example.com
    </a>
  </div>
</div>

<div class="result results_links results_links_deep web-result ">
  <div class="links_main links_deep result__body">
    <h2 class="result__title">
      <a rel="nofollow" class="result__a" href="">text3</a>
    </h2>
    <a class="result__snippet" href="">text23</a>
    <a class="result__url" href="">
    text.com
    </a>
  </div>
</div>
EOS;

$document = new DOMDocument();
$document->loadHTML($test);

// first extract all the divs with the links_deep class
$divs = [];
foreach ($document->getElementsByTagName('div') as $div) {
    $classes = $div->attributes->getNamedItem('class')->nodeValue;
    if (!$classes) continue;

    $classes = explode(' ', $classes);

    if (in_array('links_main', $classes)) {
        $divs[] = $div;
    }
}

// now iterate through them and retrieve all the links in order
$results = [];
foreach ($divs as $div) {
    $temp = [];
    foreach ($div->getElementsByTagName('a') as $link) {
        $temp[] = $link->nodeValue;
    }
    $results[] = $temp;
}

var_dump($results);

我将使用
DOMDocument
DOMXPath
更轻松地定位感兴趣的部分。为了更精确,我注册了一个函数,用于检查class属性是否包含一组类:

function hasClasses($attrValue, $requiredClasses) {
    $requiredClasses = explode(' ', $requiredClasses);
    $classes = preg_split('~\s+~', $attrValue, -1, PREG_SPLIT_NO_EMPTY);
    return array_diff($requiredClasses, $classes) ? false : true;
}

$dom = new DOMDocument;
$state = libxml_use_internal_errors(true);
$dom->loadHTML($html);
libxml_use_internal_errors($state);

$xp = new DOMXPath($dom);
$xp->registerNamespace('php', 'http://php.net/xpath');
$xp->registerPhpFunctions('hasClasses');

$mainDivClasses = 'result results_links results_links_deep web-result';
$childDivClasses = 'links_main links_deep result__body';

$divNodeList = $xp->query('//div[php:functionString("hasClasses", @class, "' . $mainDivClasses . '")]
                           /div[php:functionString("hasClasses", @class, "' . $childDivClasses . '")]');

$results = [];
foreach ($divNodeList as $divNode) {
    $results[] = [
        trim($xp->evaluate('string(./h2/a[@class="result__a"])', $divNode)),
        trim($xp->evaluate('string(.//a[@class="result__snippet"])', $divNode)),
        trim($xp->evaluate('string(.//a[@class="result__url"])', $divNode))
    ];
}

print_r($results);

在不注册函数的情况下,还可以在谓词中使用XPath函数
contains
。它不太精确,因为它只检查子字符串是否在较大的字符串中(而不是类属性是否具有特定的类,如
hasClasses
函数),但它必须足够:

$dom = new DOMDocument;
$state = libxml_use_internal_errors(true);
$dom->loadHTML($html);
libxml_use_internal_errors($state);

$xp = new DOMXPath($dom);

$divNodeList = $xp->query('//div[contains(@class, "results_links_deep")]
                                [contains(@class, "web-result")]
                           /div[contains(@class, "links_main")]
                               [contains(@class, "links_deep")]
                               [contains(@class, "result__body")]');

$results = [];
foreach ($divNodeList as $divNode) {
    $results[] = [
        trim($xp->evaluate('string(./h2/a[@class="result__a"])', $divNode)),
        trim($xp->evaluate('string(.//a[@class="result__snippet"])', $divNode)),
        trim($xp->evaluate('string(.//a[@class="result__url"])', $divNode))
    ];
}

print_r($results);

我将使用
DOMDocument
DOMXPath
更轻松地定位感兴趣的部分。为了更精确,我注册了一个函数,用于检查class属性是否包含一组类:

function hasClasses($attrValue, $requiredClasses) {
    $requiredClasses = explode(' ', $requiredClasses);
    $classes = preg_split('~\s+~', $attrValue, -1, PREG_SPLIT_NO_EMPTY);
    return array_diff($requiredClasses, $classes) ? false : true;
}

$dom = new DOMDocument;
$state = libxml_use_internal_errors(true);
$dom->loadHTML($html);
libxml_use_internal_errors($state);

$xp = new DOMXPath($dom);
$xp->registerNamespace('php', 'http://php.net/xpath');
$xp->registerPhpFunctions('hasClasses');

$mainDivClasses = 'result results_links results_links_deep web-result';
$childDivClasses = 'links_main links_deep result__body';

$divNodeList = $xp->query('//div[php:functionString("hasClasses", @class, "' . $mainDivClasses . '")]
                           /div[php:functionString("hasClasses", @class, "' . $childDivClasses . '")]');

$results = [];
foreach ($divNodeList as $divNode) {
    $results[] = [
        trim($xp->evaluate('string(./h2/a[@class="result__a"])', $divNode)),
        trim($xp->evaluate('string(.//a[@class="result__snippet"])', $divNode)),
        trim($xp->evaluate('string(.//a[@class="result__url"])', $divNode))
    ];
}

print_r($results);

在不注册函数的情况下,还可以在谓词中使用XPath函数
contains
。它不太精确,因为它只检查子字符串是否在较大的字符串中(而不是类属性是否具有特定的类,如
hasClasses
函数),但它必须足够:

$dom = new DOMDocument;
$state = libxml_use_internal_errors(true);
$dom->loadHTML($html);
libxml_use_internal_errors($state);

$xp = new DOMXPath($dom);

$divNodeList = $xp->query('//div[contains(@class, "results_links_deep")]
                                [contains(@class, "web-result")]
                           /div[contains(@class, "links_main")]
                               [contains(@class, "links_deep")]
                               [contains(@class, "result__body")]');

$results = [];
foreach ($divNodeList as $divNode) {
    $results[] = [
        trim($xp->evaluate('string(./h2/a[@class="result__a"])', $divNode)),
        trim($xp->evaluate('string(.//a[@class="result__snippet"])', $divNode)),
        trim($xp->evaluate('string(.//a[@class="result__url"])', $divNode))
    ];
}

print_r($results);


您应该使用或XmlReader/XmlParser或DOM解析类。分解
是不可靠的。即使我也尝试过,但没有得到准确的结果:
$dom=newdomdocument$dom->loadHTML($text);foreach($dom->getElementsByTagName('a')作为$node){$array[]=$dom->saveHTML($node);}print\r($array)您的html示例没有再现真实html内容的结构。@CasimiritHippolyte:请用我的实际数据检查下面的链接[但是当我尝试使用
preg\u replace从代码中删除\n时(“/\r\n | \r | \n |'/”,“”,$text);
,它给了我尝试非对象错误的
。你应该使用或XmlReader/XmlParser或DOM解析类。分解
是不可靠的。即使我也尝试过,但没有得到确切的结果:
$DOM=new DOMDocument;$DOM->loadHTML($text);foreach($DOM->getElementsByTagName('a')as$node){$array[]=$dom->saveHTML($node);}print_r($array);
您的html示例不会再现真实html内容的结构。@CasimiretHippolyte:请使用我的实际数据检查下面的链接[但是当我尝试使用
preg_replace(/\r\n | \r | \n |“/”,“,”,“,$text)从代码中删除相同概念时);
,它给了我
尝试非对象错误
DOMDocument::loadHTML():htmlParseEntityRef:Entity中没有名称,第22行
我遇到这样的错误你能发布你正在使用的全部代码和哪个php版本吗?你可以看到我的示例在这里工作:我是否需要添加
否你不需要…这是php字符串的heredoc语法-。你能确保你正在检索的数据正确格式化为HTM吗L?当我使用Laravel5.4时,它支持PHP>=5.6.4。知道我为什么会出现这个错误吗?
DOMDocument::loadHTML():htmlParseEntityRef:Entity中没有名称,第22行
我遇到这样的错误你能发布你正在使用的全部代码和哪个php版本吗?你可以看到我的示例在这里工作:我是否需要添加
否你不需要…这是php字符串的heredoc语法-。你能确保你正在检索的数据正确格式化为HTM吗L?当我使用laravel 5.4时,它支持PHP>=5.6.4。知道我为什么会出现这个错误吗?哇..它工作了。非常感谢@Casimir et Hippolyte。如何在laravel中调用
RegisterHPFunctions
中的
hasClasses
函数?我会遇到这样的错误
DOMXPath::query():无法调用处理程序hasClasses()
?在laravelI中,我只是试图像下面这样传递函数:
$xp->query('//div[php:functionString('.$this->hasClasses('.$attrValue,$mainDivClasses)。]/div[php:functionString('.$this->hasClasses($attrValue,$childDivClasses)。'));
然后它开始给我另一个错误
允许的内存大小134217728字节用尽(试图分配68719476720字节)
。有什么建议吗?@Casimircan你能帮我解决这个问题吗?@5367683:我不知道上下文是什么,但是可以将静态方法与
DOMXPath::RegisterHPFunctions
结合使用。类似于
$xp->RegisterHPFunctions('YourClass::staticMethod')的东西然后在XPath查询中以相同的方式使用它:
/div[php:functionString('YourClass::staticMethod',arg1,arg2…)
.Wow..很好用。非常感谢@Casimir et Hippolyte。如何在laravel中调用
RegisterHPFunctions
中的
hasClasses
函数?我遇到了如下错误
DOMXPath::query():无法调用处理程序hasClasses()
?在laravelI中,我只是试图像这样传递函数
$xp->->query('//div[php:functionString('.$this->hasClasses('.$attrValue,$mainDivClasses)。)]/div[php:functionString('.$this->hasClasses('.$attrValue,$childDivClasses)。);
然后它开始给我另一个错误
允许的内存大小为134217728字节(试图分配68719476720字节)
。有什么建议吗?@Casimircan你能帮我解决这个问题吗?@5367683:我不知道上下文是什么,但可以将静态方法与
DOMXPath::RegisterHPFunctions
结合使用。类似于
$xp->RegisterHPFunctions('YourClass::staticMethod');