【问题标题】:Simple Html Dom Scraping half the page简单的 Html Dom 抓取页面的一半
【发布时间】:2018-10-02 00:42:48
【问题描述】:

我正在尝试使用 simple-html-dom 抓取此 url https://nrg91.gr/nrg-airplay-chart/,但它似乎没有获得完整的 html 源代码。这段代码:

        include_once('simple_html_dom.php');
        $html = file_get_html('https://nrg91.gr/nrg-airplay-chart');

        echo $html->plaintext;

将内容显示到 h1,就在我之后的内容之前。从 simple-html-dom 手动示例中,这应该显示来自该 url 的所有链接:

        foreach($html->find('a') as $e) 
        echo $e->href . '<br>';

但它只显示到主导航菜单的链接,而不是来自主体或页脚的链接。

我还尝试使用 prerender.com,在将 url 传递给 file_get_html 之前完全加载它,但结果是一样的。我究竟做错了什么?

【问题讨论】:

  • 查看 nrg91.gr/nrg-airplay-chart(而不是 dom 检查器)的原始源代码会显示您正在尝试获取的数据。
  • 完全正确。那么为什么 simple-html-dom 不能在这个页面上工作呢?
  • 您是要获取整个 HTML 布局还是进入该表的原始数据?
  • 我正在尝试获取图表数据:排名数字、艺术家、标题、Youtube 链接。每个都有 id,所以这应该不是 simple-html-dom 的问题。

标签: php web-scraping simple-html-dom


【解决方案1】:

那个库看起来已经 7 年没有更新过了。我总是推荐使用PHP's built-in functions:

$url = "https://nrg91.gr/nrg-airplay-chart/";
$dom = new DomDocument();
libxml_use_internal_errors(true);
$dom->load($url);
foreach($dom->getElementsByTagName("a") as $e) {
    echo $e->getAttribute("href") . "\n";
}

【讨论】:

  • 仅供参考,真正的 URL 是https://nrg91.gr/nrg-airplay-chart/(斜杠)。前者重定向到后者,因此您可以保存 HTTP 请求
  • 是的,简单的 HTML DOM 是垃圾:)
  • 我认为 simple-html-dom 是解析/抓取的正确方法。感谢您的回复,我可能会使用您的 DOMDocument 方法。
  • 似乎简单的 HTML DOM 可以工作一半,而 PHP 的内置函数根本不起作用。伤心。
【解决方案2】:

这是我使用 DOMDocument 和 SimpleXML 获取排名/艺术家/标题/youtube 数据的超级肮脏方法。

这个概念是通过 xpath //ul[@id="chart_ul"]/li 定位数据的每一“行”,然后使用 dom_import_simplexml( $outer )-&gt;getNodePath() 构建一个新的 xpath 来选择可以定位所需数据的各个元素。

$temp = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'nrg-airplay-chart.html';

if( file_exists( $temp ) === false or filemtime( $temp ) < time() - 3600 )
{
  file_put_contents( $temp, $html = file_get_contents('https://nrg91.gr/nrg-airplay-chart/') );
}
else
{
  $html = file_get_contents( $temp );
}

$dom = new DOMDocument();
$dom->loadHTML( $html );
$xml = simplexml_import_dom( $dom );
$array = array();

foreach( $xml->xpath('//ul[@id="chart_ul"]/li') as $index => $set )
{
  $basexpath = dom_import_simplexml( $set )->getNodePath();
  $array[] = array(
    'ranking' => (string) $xml->xpath( $basexpath . '//span[@id="ranking"]' )[0],
    'artist' => (string) $xml->xpath( $basexpath . '//p[@id="artist"]/b' )[0],
    'title' => (string) $xml->xpath( $basexpath . '//p[@id="title"]' )[0],
    'youtube' => (string) $xml->xpath( $basexpath . '//div[@id="media"]/a/@href' )[0],
  );
}

print_r( $array );

【讨论】:

  • 感谢您的帮助,非常感谢。我很快就会测试你的代码。
【解决方案3】:

您可能想要遵循的另一种方法:

<?php
    function get_content($url) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_exec($ch);
        $htmlContent = curl_exec($ch);
        curl_close($ch);
        return $htmlContent;
    }
    $link = "https://nrg91.gr/nrg-airplay-chart/"; 
    $xml = get_content($link);

    $dom = @DOMDocument::loadHTML($xml);
    $xpath = new DOMXPath($dom);
    foreach($xpath->query('//li[contains(@id,"wprs_chart-")]') as $items){
        $artist = $xpath->query('.//p[@id="artist"]/b',$items)->item(0)->nodeValue;
        $title = $xpath->query('.//p[@id="title"]',$items)->item(0)->nodeValue;
        echo "{$artist} -- {$title}<br>";
    }
?>

你应该得到如下输出:

PORTOGAL THE MAN -- Feel It Still
JAX JONEW Feat INA WROLDSEN -- Breathe
CAMILA CABELLO -- Havana
CARBI B, J BALVIN & BAD BUNNY -- I Like It
ZAYN Feat SIA -- Dusk Till Dawn

【讨论】:

  • 太好了,我也会试试你的代码。感谢您的回复!
猜你喜欢
  • 2021-05-18
  • 2013-07-30
  • 2014-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-07
  • 2012-04-20
  • 2013-12-26
相关资源
最近更新 更多