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

时间:2012-02-27 17:14:12

标签: python xpath amazon lxml

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

  

// div [@ class ='pTitle'] / span [@ class ='small itemByline'] | // DIV [@类= 'pTitle'] /跨度[否(文本())]

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

例如,以“A Ditadura”开头的3个标题应该使用我正在构建的XPath返回作者条目。他们不是。它使上面的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相应地返回第二段和第三段'value'字符串。没关系,但我正在寻找4个结果,而不是2个,就像这样:

    None
    value
    value
    None

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

1 个答案:

答案 0 :(得分:1)

您可以使用像这样的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中,每当布尔值是算术运算符的参数时,首先使用以下规则将其转换为数字:

   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