Skip to main content
 首页 » 编程设计

python之如果在 xpath (lxml) 中找不到节点/标记,如何返回字符串或匹配空

2025年05月04日20shangdawei

我有以下 XPath 来匹配亚马逊页面中的作者姓名:

//div[@class='pTitle']/span[@class='small itemByline'] | //div[@class='pTitle']/span[not(text())]

这个 XPath 的第一部分匹配得很好,但是页面中的一些项目在 pTitle 类的 div 之后没有跨度,所以没有什么可以匹配的,但我想得到一个 '' 或其他东西, 要知道作者没有被发现而不是跳过它。我想第二个 XPath 无效,因为它不起作用...

例如,对于使用我正在构建的 XPath 的作者条目,以“A Ditadura”开头的 3 个标题应该返回“”。他们不是。它使上述 XPath 返回 179 个项目而不是 209 个。

目标是 http://www.amazon.com/wishlist/3MCYFXCFDH4FA/ref=cm_wl_act_print_o?_encoding=UTF8&layout=standard-print&disableNav=1&visitor-view=1&items-per-page=1000

这是我的 Python 模块代码的一部分 https://github.com/caio1982/Amazon-Wishlist (顺便说一句,感谢到目前为止所有的好答案,感谢你们,我学会了 XPath)。

为了提供信息,我尝试使用 Firefox 的 XPath Checker 扩展,并使用 Python (lxml) 实现它。

这听起来类似于 How do I return '' for an empty node's text() in XPath?但我不确定。

我怀疑答案可能是围绕 XPath 轴的某些东西和某种 [notcontains] 限制?

EDIT1:根据 Dimitre 的建议稍微改写一下……是否可以使用 –– 如果可以,您是否有 –– Becker 的 XPath 方法使用 lxml 的工作示例?

EDIT2:样本树和预期结果:

    <html> 
        <body> 
            <h1>Title</h1> 
            <p>First Paragraph</p> 
            <p>Second paragraph: <span>value</span></p> 
            <p>Third paragraph: <span>value</span></p> 
            <p>Forth paragraph:</p> 
        </body> 
    </html> 

XPath//p/span 相应地返回第二段和第三段的“值”字符串。没关系,但我正在寻找 4 个结果而不是 2 个,如下所示:

    None 
    value 
    value 
    None 

我知道//p/span 对此不起作用,因此我正在寻找一些字符串魔术、节点比较或条件等。

请您参考如下方法:

您可以使用像这样的 XPath 表达式:

concat( 
//div[@class='pTitle']/span[@class='small itemByline'], 
substring('UNKNOWN',  
          1 + 7*(boolean(//div[@class='pTitle']/span[@class='small itemByline']) 
          ) 
       ) 

当这个 XPath 表达式被求值时,如果 //div[@class='pTitle']/span[@class='small itemByline'] 存在,那么它的字符串值(与生成空字符串)。

当//div[@class='pTitle']/span[@class='small itemByline']不存在时,则结果为字符串'UNKNOWN' -- 空字符串与 substring('UNKNOWN', 1+0) 连接。

这里我们使用的事实是,在 XPath 1.0 中,每当 bool 值是算术运算符的参数时,它首先会使用以下规则转换为数字:

   number(true()) = 1 

和

   number(false()) = 0 

更新:这是一个基于 XSLT 的验证,使用 OP 编辑​​ 2 中的 XML 文档并生成完全想要的结果(相同的 XPath 表达式(仅更新索引)是评估 4 次并输出所有产生的值——每个都在单独的行上):

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 <xsl:output omit-xml-declaration="yes" indent="yes"/> 
 
 <xsl:template match="/"> 
  <xsl:for-each select="(//node())[not(position() > count(//p))]"> 
   <xsl:variable name="vPos" select="position()"/> 
   <xsl:value-of select= 
     "concat((//p)[position() = $vPos]/span, 
             substring('UNKNOWN', 
                       1 +7*boolean((//p)[position() = $vPos]/span) 
                       ) 
             ) 
     "/> 
 
     <xsl:text>&#xA;</xsl:text> 
  </xsl:for-each> 
 </xsl:template> 
</xsl:stylesheet> 

当此转换应用于最新提供的 XML 文档时:

<html> 
    <body> 
        <h1>Title</h1> 
        <p>First Paragraph</p> 
        <p>Second paragraph:  
            <span>value</span> 
        </p> 
        <p>Third paragraph:  
            <span>value</span> 
        </p> 
        <p>Forth paragraph:</p> 
    </body> 
</html> 

XPath 表达式被求值 N (4) 次并生成该求值的结果——如我们所见,这些正是想要的结果:

UNKNOWN 
value 
value 
UNKNOWN