You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PHP爬虫获取Picture元素内图片URL的XPath查询问题求助

解决PHP DOMXPath爬取图片URL的问题

看起来你遇到的核心问题是XPath选择器的匹配逻辑错误,以及对多class属性的匹配方式理解有误,我来帮你一步步修正:

问题分析

  1. 绝对路径不可靠:你尝试的第一个XPath用了硬编码的绝对路径,页面结构稍有变动就会失效,完全不适合爬虫场景。
  2. 元素选择错误:第二个XPath选中了span.overlay-thumbnail元素,但data-srcset属性是在它内部的imgsource标签上,不是span本身,自然拿不到值。
  3. 多class匹配错误:第三个XPath用了@class='imageLazy'精确匹配,但实际img的class是"thumbnail img-placeholder imageLazy"(多个class),精确匹配无法命中,这是最关键的问题!

可行的解决方案

根据你提供的HTML结构,我给你两种场景的正确XPath写法,同时添加空值判断避免报错:

场景1:获取主图(带有data-e2e="product-listing-img"的img)

这个data-e2e属性是页面的测试标识,通常比class更稳定,优先推荐:

function parse($html) { 
    try { 
        libxml_use_internal_errors(true); 
        $doc = new DOMDocument(); 
        $doc->loadHTML($html); 
        $xpath = new DomXPath($doc); 
        $nodeList = $xpath->query('//*[@class="productListItem "]'); 
        $res = []; 
        foreach ($nodeList as $node) { 
            $new = new DomDocument; 
            $new->appendChild($new->importNode($node, true)); 
            $N = new DomXPath($new); 
            
            // 原有逻辑:获取链接、名称、价格(添加空值判断避免报错)
            $nodeLink = $N->query("//a[@class='itemImage']")->item(0); 
            $Link = $nodeLink ? $nodeLink->getAttribute('href') : ''; 
            
            $nodeName = $N->query("//span[@class='itemTitle']")->item(0); 
            $Name = $nodeName ? $nodeName->textContent : ''; 
            
            $nodePrice = $N->query("//span[@class='pri']")->item(0); 
            $Price = $nodePrice ? $nodePrice->textContent : ''; 
            
            // 修正后的图片获取逻辑
            $nodeImg = $N->query("//img[@data-e2e='product-listing-img']")->item(0); 
            $Img = '';
            if ($nodeImg) {
                $srcset = $nodeImg->getAttribute('data-srcset');
                // 拆分srcset,只取1x规格的图片URL(按需调整)
                $imgParts = explode(',', $srcset);
                $Img = trim($imgParts[0]);
            }
            
            $res[] = [ 
                'productLink' => $Link, 
                'productName' => $Name, 
                'productImage' => $Img, 
                'productPrice' => $Price 
            ]; 
        } 
        return $res; 
    } catch (Exception $e) { 
        echo $e->getMessage(); 
    } 
} 

场景2:获取overlay缩略图(span.overlay-thumbnail下的img)

如果需要的是第二个picture里的图片,用多class安全匹配的XPath:

// 替换上述代码中的图片获取部分
$nodeImg = $N->query("//span[contains(concat(' ', normalize-space(@class), ' '), ' overlay-thumbnail ')]//img[contains(concat(' ', normalize-space(@class), ' '), ' imageLazy ')]")->item(0); 
$Img = '';
if ($nodeImg) {
    $srcset = $nodeImg->getAttribute('data-srcset');
    $imgParts = explode(',', $srcset);
    $Img = trim($imgParts[0]);
}

关键优化点

  • 避免精确匹配class:用contains(concat(' ', normalize-space(@class), ' '), ' target-class ')的方式,可以安全匹配多class元素,避免因为class顺序或新增class导致匹配失败。
  • 添加空值判断:所有节点查询后都先判断是否存在,再调用属性或方法,防止出现Call to a member function getAttribute() on null的错误。
  • 优先使用稳定属性:比如data-e2e这类专为测试/爬虫设计的属性,比class更不容易随页面样式变化而改动。

内容的提问来源于stack exchange,提问作者logosapp

火山引擎 最新活动