You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP爬虫开发问题求助:hasAttribute()空调用报错及XML覆盖问题

Hey there! Let's tackle each of your issues step by step—here's how to fix them:

1. Fixing the "Fatal error: Call to a member function hasAttribute() on null"

This error pops up because you're trying to call hasAttribute() on a variable that's null. That means the DOM node you're targeting doesn't exist (your query didn't find anything).

To fix this, always add a check to make sure the node exists before calling any methods on it:

// Bad: No check for null
$targetNode = $xpath->query('//div[@class="target"]')->item(0);
if ($targetNode->hasAttribute('data-id')) {
    // Your logic here
}

// Good: Check if node exists first
$targetNode = $xpath->query('//div[@class="target"]')->item(0);
if ($targetNode !== null && $targetNode->hasAttribute('data-id')) {
    // Safe to run your logic now
}

If you're using PHP 8 or newer, you can use the null safe operator to make this cleaner:

$hasDataId = $targetNode?->hasAttribute('data-id') ?? false;
2. Why the first record is always empty

This usually happens for one of two reasons:

  • You're initializing an empty record before your scraping loop starts, then accidentally adding it to your results. Double-check your code for any lines that create a record object outside the loop and push it to your list without filling it.
  • Your DOM query is picking up an empty/whitespace node as the first match. To fix this, filter out empty nodes in your XPath query or trim the content before saving:
foreach ($nodes as $node) {
    $content = trim($node->nodeValue);
    // Only save if content isn't empty
    if (!empty($content)) {
        // Add your record logic here
    }
}

Or adjust your XPath to skip empty nodes entirely:

$nodes = $xpath->query('//div[@class="item"][normalize-space(text()) != ""]');
3. Append to XML instead of overwriting

By default, when you save an XML file with DOMDocument->save(), it overwrites the entire file. To append new elements, you need to load the existing XML first, add your new elements, then save it back. Here's how to do it correctly:

$xmlPath = 'your_file.xml';
$dom = new DOMDocument();
$dom->formatOutput = true; // Makes the XML pretty-printed

// Load existing XML if the file exists; create a root node if not
if (file_exists($xmlPath)) {
    $dom->load($xmlPath);
    $root = $dom->documentElement;
} else {
    $root = $dom->createElement('records');
    $dom->appendChild($root);
}

// Create your new record element
$newRecord = $dom->createElement('record');
// Add child elements (example: title and content)
$title = $dom->createElement('title', $scrapedTitle);
$content = $dom->createElement('content', $scrapedContent);
$newRecord->appendChild($title);
$newRecord->appendChild($content);

// Add the new record to the root node
$root->appendChild($newRecord);

// Save the updated XML back to the file
$dom->save($xmlPath);

Avoid using simple file append (like file_put_contents($xmlPath, $newXml, FILE_APPEND)), as this will break the XML structure (XML requires a single root node, and appending directly will create invalid markup).

内容的提问来源于stack exchange,提问作者Jakub Jóźwiak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:23:49