PHP爬虫开发问题求助:hasAttribute()空调用报错及XML覆盖问题
Hey there! Let's tackle each of your issues step by step—here's how to fix them:
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;
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()) != ""]');
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

