【问题标题】:parse the html data to array data in php将html数据解析为php中的数组数据
【发布时间】:2017-03-02 12:37:15
【问题描述】:

我正在尝试使用 a 标记类将 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>';

我正在尝试使用以下代码获取结果

$lines = explode("\n", $text);
$out = array();
foreach ($lines as $line) {
    $parts = explode(" > ", $line);
    $ref = &$out;
    while (count($parts) > 0) {
        if (isset($ref[$parts[0]]) === false) {
            $ref[$parts[0]] = array();
        }
        $ref = &$ref[$parts[0]];
        array_shift($parts);
    }
}
print_r($out);

但我需要完全像下面的结果

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

演示:https://eval.in/746170

即使我在 laravel 中尝试 dom 如下所示:

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

print_r($array);

那么我怎样才能使用这些类来分离我想要的数据。请有任何建议。谢谢。

【问题讨论】:

  • 您应该使用SimpleXML 或 XmlReader/XmlParser 或 DOM 解析类。爆破&gt;不靠谱。
  • 即使我也尝试过,但没有得到准确的结果:
  • $dom = new DOMDocument; $dom-&gt;loadHTML($text); foreach($dom-&gt;getElementsByTagName('a') as $node) { $array[] = $dom-&gt;saveHTML($node); } print_r($array);
  • 您的 html 示例无法重现您的真实 html 内容的结构。
  • @CasimiretHippolyte :请检查下面的链接与我的实际数据 [eval.in/746302] 但是当我尝试使用相同的概念从代码中删除 \n 使用 preg_replace("/\r\n|\r|\n|'/", ' ', $text); 时,它给了我trying to non object error .

标签: php arrays laravel-5.4


【解决方案1】:

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

<?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);

工作版 - http://sandbox.onlinephpfunctions.com/code/e7ed2615ea32c5b9f0a89e3460da28a2702343f1

【讨论】:

  • DOMDocument::loadHTML(): htmlParseEntityRef: no name in Entity, line: 22 我遇到这样的错误
  • 你能发布你正在使用的整个代码以及哪个 php 版本吗?你可以在这里看到我的例子:sandbox.onlinephpfunctions.com/code/…
  • 我需要在html数据的顶部和底部添加&lt;&lt;&lt;EOS吗?因为我在这里动态获取数据,所以无法添加。该怎么办 ?我正在使用 laravel
  • 不,你不会...这是 php 字符串的 heredoc 语法 - php.net/manual/en/language.types.string.php。您能否确保您检索的数据正确格式化为 HTML?
  • 因为我使用 laravel 5.4 它支持 PHP >= 5.6.4 。知道为什么我会收到这个错误吗?
【解决方案2】:

我将使用DOMDocumentDOMXPath 来更轻松地定位有趣的部分。为了更准确,我注册了一个函数来检查一个类属性是否包含一组类:

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

【讨论】:

  • 哇..它的工作原理。非常感谢@Casimir et Hippolyte。
  • 如何在laravel的registerPhpFunctions里面调用hasClasses里面的函数?我收到这样的错误DOMXPath::query(): Unable to call handler hasClasses()?在 laravel 中
  • 我只是想传递这样的函数$xp-&gt;query('//div[php:functionString('.$this-&gt;hasClasses($attrValue,$mainDivClasses).')] /div[php:functionString('.$this-&gt;hasClasses($attrValue,$childDivClasses).')]'); 然后它开始给我另一个错误Allowed memory size of 134217728 bytes exhausted (tried to allocate 68719476720 bytes)。有什么建议么 ? @卡西米尔
  • 你能帮我解决这个问题吗? ?
  • @5367683:我不知道上下文是什么,但可以使用带有DOMXPath::registerPhpFunctions 的静态方法。 $xp-&gt;registerPhpFunctions('YourClass::staticMethod'); 之类的东西,然后在 XPath 查询中以相同的方式使用它:/div[php:functionString('YourClass::staticMethod', arg1, arg2...)]
猜你喜欢
  • 2021-09-18
  • 2014-05-19
  • 2013-08-26
  • 1970-01-01
  • 1970-01-01
  • 2012-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多