Resolve "Fatal Error: Call to a member function children() on null"

Resolve "Fatal Error: Call to a member function children() on null"

我正在使用 PHP HTML DOM 解析器遍历第三方站点上的 table DOM 并打印出一组特定的值在 td 元素中。

<?php

foreach($html->find('td#column2.style3') as $e)

{

$sponsor3 = $e->parent()->next_sibling()->next_sibling()->next_sibling()->children(4)->plaintext;

echo "Sponsor3 <strong>" . $sponsor3 . "</strong><br>";

}

?>

这适用于我遍历的前两列。

然而,在第 3 列中,$e 操作 returns Null。该元素的 HTML 是:


<td style="" id="column5" valign="top" class="style3"></td>

我遇到的问题是,它会在此元素上引发致命错误,因此脚本的其余部分不会 运行。

报错的行是:

$sponsor3 = $e->parent()->next_sibling()->next_sibling()->next_sibling()->children(4)->plaintext;

Fatal error: Uncaught Error: Call to a member function children() on null

即使调用为空,我也需要能够遍历...如果其中一个列元素为空,我该怎么做才能不破坏脚本?

这是我正在抓取的 HTML:

<tbody style="page-break-inside: avoid">
                          <tr>
                             <td style="" id="column1" valign="top"></td>
                             <td style="" id="column2" valign="top" class="style3">R5</td>
                             <td style="" id="column3" valign="top" class="style2">A</td>
                             <td style="" id="column4" valign="top" colspan="2" class="style2">
                                <a target="_blank" href="CoverSheet.aspx?ItemID=19186&amp;MeetingID=779">
                                   <p>AN ORDINANCE OF THE MAYOR AND CITY COMMISSION OF THE CITY OF MIAMI BEACH, FLORIDA, AMENDING CHAPTER 30 OF THE MIAMI BEACH CITY CODE, ENTITLED "CODE ENFORCEMENT," BY AMENDING ARTICLE Il, ENTITLED "SPECIAL MASTER," BY AMENDING SECTION 30-37, ENTITLED "TERMS OF OFFICE; COMPENSATION"; BY AMENDING THE COMPENSATION OF THE SPECIAL MASTER(S); PROVIDING FOR CODIFICATION, REPEALER, SEVERABILITY, AND AN EFFECTIVE DATE.</p>
                                </a>
                             </td>
                             <td style="" id="column6" valign="top"></td>
                             <td style="" id="column7" valign="top"></td>
                             <td style="" id="column8" valign="top"></td>
                          </tr>
                          <tr>
                             <td style="" id="column1" valign="top"></td>
                             <td style="" id="column2" valign="top"></td>
                             <td style="" id="column3" valign="top"></td>
                             <td style="" id="column4" valign="top"></td>
                             <td style="" id="column5" valign="top"></td>
                             <td style="" id="column6" valign="top"></td>
                             <td style="" id="column7" valign="top"></td>
                             <td style="" id="column8" valign="top"></td>
                          </tr>
                          <tr>
                             <td style="" id="column1" valign="top"></td>
                             <td style="" id="column2" valign="top"></td>
                             <td style="" id="column3" valign="top"></td>
                             <td style="" id="column4" valign="top" class="style6">First Reading</td>
                             <td style="" id="column5" valign="top" class="style3">Office of the City Clerk</td>
                             <td style="" id="column6" valign="top"></td>
                             <td style="" id="column7" valign="top"></td>
                             <td style="" id="column8" valign="top"></td>
                          </tr>
                          <tr>
                             <td style="" id="column1" valign="top"></td>
                             <td style="" id="column2" valign="top"></td>
                             <td style="" id="column3" valign="top"></td>
                             <td style="" id="column4" valign="top" class="style7"></td>
                             <td style="" id="column5" valign="top" class="style3">Commissioner Michael Gongora</td>
                             <td style="" id="column6" valign="top"></td>
                             <td style="" id="column7" valign="top"></td>
                             <td style="" id="column8" valign="top"></td>
                          </tr>
                       </tbody>
                       <tr>
                          <td style="" id="column1" valign="top"></td>
                          <td style="" id="column2" valign="top"></td>
                          <td style="" id="column3" valign="top"></td>
                          <td style="" id="column4" valign="top"></td>
                          <td style="" id="column5" valign="top"></td>
                          <td style="" id="column6" valign="top"></td>
                          <td style="" id="column7" valign="top"></td>
                          <td style="" id="column8" valign="top"></td>
                       </tr>
                       <tr>
                          <td style="" id="column1" valign="top"></td>
                          <td style="" id="column2" valign="top"></td>
                          <td style="" id="column3" valign="top"></td>
                          <td style="" id="column4" valign="top"></td>
                          <td style="" id="column5" valign="top" colspan="1" class="style8"></td>
                          <td style="" id="column6" valign="top"></td>
                          <td style="" id="column7" valign="top"></td>
                          <td style="" id="column8" valign="top"></td>
                       </tr>
                       <tbody style="page-break-inside: avoid">
                          <tr>
                             <td style="" id="column1" valign="top"></td>
                             <td style="" id="column2" valign="top" class="style3">R5</td>
                             <td style="" id="column3" valign="top" class="style2">B</td>
                             <td style="" id="column4" valign="top" colspan="2" class="style2">
                                <a target="_blank" href="CoverSheet.aspx?ItemID=19206&amp;MeetingID=779">
                                   <p>SHORT TERM RENTAL FINE REVISIONS</p>
                                   <p>AN ORDINANCE OF THE MAYOR AND CITY
                                      COMMISSION OF THE CITY OF MIAMI BEACH, FLORIDA,
                                      AMENDING MIAMI BEACH CITY CODE CHAPTER 142,
                                      "ZONING DISTRICTS AND REGULATIONS," ARTICLE IV,
                                      "SUPPLEMENTARY DISTRICT REGULATIONS,"
                                      SECTION 142-905, "PERMITTED ACCESSORY USES IN
                                      SINGLE-FAMILY DISTRICTS," AT SUBSECTION (b)(5)
                                      THEREOF, AND AMENDING SECTION 142-1111, "SHORTTERM
                                      RENTAL OF APARTMENT UNITS OR
                                      TOWNHOMES," FOR THE LIMITED PURPOSE OF
                                      DELETING THE FINE AMOUNTS SPECIFIED THEREIN
                                      FOR VIOLATIONS OF THE CITY'S SHORT-TERM RENTAL
                                      RESTRICTIONS (INCLUDING CORRESPONDING
                                      RESTRICTION ON SPECIAL MASTER'S INABILITY TO
                                      WAIVE OR REDUCE SAID FINES), AND SUBSTITUTING
                                      THEREFOR THOSE FINE AMOUNTS WITHIN THE
                                      STATUTORILY-PRESCRIBED LIMITS SET FORTH IN
                                      CHAPTER 162, FLORIDA STATUTES; AND PROVIDING
                                      FOR REPEALER, SEVERABILITY, CODIFICATION, AND
                                      AN EFFECTIVE DATE.
                                   </p>
                                </a>
                             </td>
                             <td style="" id="column6" valign="top"></td>
                             <td style="" id="column7" valign="top"></td>
                             <td style="" id="column8" valign="top"></td>
                          </tr>
                          <tr>
                             <td style="" id="column1" valign="top"></td>
                             <td style="" id="column2" valign="top"></td>
                             <td style="" id="column3" valign="top"></td>
                             <td style="" id="column4" valign="top"></td>
                             <td style="" id="column5" valign="top"></td>
                             <td style="" id="column6" valign="top"></td>
                             <td style="" id="column7" valign="top"></td>
                             <td style="" id="column8" valign="top"></td>
                          </tr>
                          <tr>
                             <td style="" id="column1" valign="top"></td>
                             <td style="" id="column2" valign="top"></td>
                             <td style="" id="column3" valign="top"></td>
                             <td style="" id="column4" valign="top" class="style6">First Reading</td>
                             <td style="" id="column5" valign="top" class="style3">Planning/Office of the City Attorney</td>
                             <td style="" id="column6" valign="top"></td>
                             <td style="" id="column7" valign="top"></td>
                             <td style="" id="column8" valign="top"></td>
                          </tr>
                          <tr>
                             <td style="" id="column1" valign="top"></td>
                             <td style="" id="column2" valign="top"></td>
                             <td style="" id="column3" valign="top"></td>
                             <td style="" id="column4" valign="top" class="style7"></td>
                             <td style="" id="column5" valign="top" class="style3">Mayor Dan Gelber</td>
                             <td style="" id="column6" valign="top"></td>
                             <td style="" id="column7" valign="top"></td>
                             <td style="" id="column8" valign="top"></td>
                          </tr>
                       </tbody>
                       <tr>
                          <td style="" id="column1" valign="top"></td>
                          <td style="" id="column2" valign="top"></td>
                          <td style="" id="column3" valign="top"></td>
                          <td style="" id="column4" valign="top"></td>
                          <td style="" id="column5" valign="top"></td>
                          <td style="" id="column6" valign="top"></td>
                          <td style="" id="column7" valign="top"></td>
                          <td style="" id="column8" valign="top"></td>
                       </tr>
                       <tr>
                          <td style="" id="column1" valign="top"></td>
                          <td style="" id="column2" valign="top"></td>
                          <td style="" id="column3" valign="top"></td>
                          <td style="" id="column4" valign="top"></td>
                          <td style="" id="column5" valign="top" colspan="1" class="style8">Supplemental updated on 9/25/2020 (Memorandum & Ordinance)</td>
                          <td style="" id="column6" valign="top"></td>
                          <td style="" id="column7" valign="top"></td>
                          <td style="" id="column8" valign="top"></td>
                       </tr>
                    </TABLE>

如果我是你,我会添加一些辅助方法来避免类似情况:

<?php

foreach($html->find('td#column2.style3') as $e)
{ 
    // $sponsor3 = $e->parent()->next_sibling()->next_sibling()->next_sibling()->children(4)->plaintext;

    $parent = getParentSafe($e);
    $firstSibling = getNextSiblingSafe($parent);
    $secondSibling = getNextSiblingSafe($firstSibling);
    $thirdSibling = getNextSiblingSafe($secondSibling);
    $fourthChild = getChildSafe($thirdSibling, 4);
    
    $sponsor3 = is_null($fourthChild) ? "" : $fourthChild->plaintext;

    echo "Sponsor3 <strong>" . $sponsor3 . "</strong><br>";   
}
    
function getParentSafe( $node ) {
    return is_null($node) ? $node : $node->parent();
}

function getNextSiblingSafe( $node ) {
    return is_null($node) ? $node : $node->next_sibling();
}

function getChildSafe( $node, $index ) {
    if (is_null($node)) {
        return $node;
    }
    
    $children = $node->children();
    return count($children) > $index ? $children[$index] : $node;
}

?>

这将确保 php 不会崩溃。话虽如此,您的代码中还有很多清理工作要做。

尝试使用 XPath,

$html=getHTML();
@($domd=new DOMDocument())->loadHTML($html);
$xp=new DOMXPath($domd);
foreach($xp->query(".//tbody[1]/tr/td[5]") as $sponsor){
    var_dump($sponsor->textContent);
}
$sponsor3 = $xp->query(".//tbody[1]/tr[4]/td[5]")->item(0)->textContent;
echo "spnosor3: ",$sponsor3;

打印:

string(0) ""
string(0) ""
string(24) "Office of the City Clerk"
string(28) "Commissioner Michael Gongora"
spnosor3: Commissioner Michael Gongora