【问题标题】:Web scraping table elements - Uncaught ErrorWeb 抓取表格元素 - 未捕获的错误
【发布时间】:2019-05-23 17:33:23
【问题描述】:

我正在尝试使用 Simple htm dom 和 PHP 从网站上抓取数据

网站: http://portal.chmi.cz/aktualni-situace/aktualni-stav-pocasi/ceska-republika/stanice/profesionalni-stanice/tabulky/teplota

但是我的代码不起作用,我遇到了一个致命错误。 谁能帮帮我?

错误:

致命错误:未捕获的错误:调用数组上的成员函数 find() 在 C:\xampp\htdocs\simple_dom\index.php:20 堆栈跟踪:#0 {main} 在第 20 行的 C:\xampp\htdocs\simple_dom\index.php 中抛出

我的代码:

<?php
      include('simple_html_dom.php');

      $html = file_get_html('http://portal.chmi.cz/aktualni-situace/aktualni-stav-pocasi/ceska-republika/stanice/profesionalni-stanice/tabulky/teplota',false);

      $table = $html->find('table');
      $Data = array();

      foreach($table->find('tr[class=portlet-table-alternate]') as $row) {

          $rowData = array();

              foreach($row->find('td') as $cell) {

                  $rowData[] = $cell->innertext;
                  }

          $Data[] = $rowData;
      }
      print_r($Data);
?>

【问题讨论】:

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


    【解决方案1】:

    该错误会告诉您确切的问题所在。你会得到一个array 作为file_get_html function 的响应。在下一行中,当您调用时

    $table = $html->find('table');
    

    您试图调用arrayfind 方法,这违反了PHP 规则。您需要找出为什么会收到array,它的内容是什么。直观地说,我认为您会得到一个array,其中一个项目(可能索引为 0)包含您要查找的项目。因此,您需要调查您的array。如果这是一个错误,那么您将成功地向前迈出一步,了解问题的本质。如果它是具有有用属性的结果,那么您将能够使用它。更多参考,file_get_html的实现:

    /**
     * All of the Defines for the classes below.
     * @author S.C. Chen <me578022@gmail.com>
     */
    define('HDOM_TYPE_ELEMENT', 1);
    define('HDOM_TYPE_COMMENT', 2);
    define('HDOM_TYPE_TEXT',    3);
    define('HDOM_TYPE_ENDTAG',  4);
    define('HDOM_TYPE_ROOT',    5);
    define('HDOM_TYPE_UNKNOWN', 6);
    define('HDOM_QUOTE_DOUBLE', 0);
    define('HDOM_QUOTE_SINGLE', 1);
    define('HDOM_QUOTE_NO',     3);
    define('HDOM_INFO_BEGIN',   0);
    define('HDOM_INFO_END',     1);
    define('HDOM_INFO_QUOTE',   2);
    define('HDOM_INFO_SPACE',   3);
    define('HDOM_INFO_TEXT',    4);
    define('HDOM_INFO_INNER',   5);
    define('HDOM_INFO_OUTER',   6);
    define('HDOM_INFO_ENDSPACE',7);
    define('DEFAULT_TARGET_CHARSET', 'UTF-8');
    define('DEFAULT_BR_TEXT', "\r\n");
    define('DEFAULT_SPAN_TEXT', " ");
    define('MAX_FILE_SIZE', 600000);
    // helper functions
    // -----------------------------------------------------------------------------
    // get html dom from file
    // $maxlen is defined in the code as PHP_STREAM_COPY_ALL which is defined as -1.
    function file_get_html($url, $use_include_path = false, $context=null, $offset = -1, $maxLen=-1, $lowercase = true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT)
    {
        // We DO force the tags to be terminated.
        $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText);
        // For sourceforge users: uncomment the next line and comment the retreive_url_contents line 2 lines down if it is not already done.
        $contents = file_get_contents($url, $use_include_path, $context, $offset);
        // Paperg - use our own mechanism for getting the contents as we want to control the timeout.
        //$contents = retrieve_url_contents($url);
        if (empty($contents) || strlen($contents) > MAX_FILE_SIZE)
        {
            return false;
        }
        // The second parameter can force the selectors to all be lowercase.
        $dom->load($contents, $lowercase, $stripRN);
        return $dom;
    }
    

    编辑

    原来错误发生在foreach这一行,调用了一个空的array的方法。一个简洁优雅的方法foreach 是定义一个助手function

    function myFind($input, $what) {
        if (!is_array($input)) {
            return $input->find($what);
        }
        $result = [];
        foreach ($input as $element) {
            $found = $element->find($what);
            foreach ($found as $f) $result[]=$f;
        }
        return $result;
    }
    
    and then call this like:
    
    foreach(myFind($table, 'tr[class=portlet-table-alternate]') as $row) {
        //...
    }
    

    【讨论】:

    • 感谢您的评论 :],第 20 行出错,其中包含这部分代码 foreach($table-&gt;find('tr[class=portlet-table-alternate]') as $row) {$table = $html-&gt;find('table') 的结果是一个空数组。
    • @SebastianRygl 感谢您指出这一点,事实上,我的回答假设错误发生在与实际发生位置不同的行中。我将使用更多信息编辑我的答案。
    • 它工作得很好,谢谢,但我还是不明白,为什么数组是空的,因为我知道网站上没有空表:DD
    • @SebastianRygl 这确实很奇怪。您是否能够成功查询其他内容?如果关闭 Javascript,表格会加载吗?为什么指定第二个参数(use_include_path)为false?
    • @SebastianRygl 您正在运行 GET 请求并且未执行 Javascript,因此这就是您看不到表格的原因。您需要查看页面发出的请求列表,在该页面中请求为表格加载需要加载的数据,并将您的请求发送到那里。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 2018-12-27
    • 2017-09-06
    • 2016-02-22
    • 2015-02-24
    • 2014-05-04
    • 2017-04-29
    相关资源
    最近更新 更多