2

所以在我的scrapy项目中,我能够隔离一些特定的字段,其中一个字段返回如下内容:

[Rank Info] on 2013-06-27 14:26 Read 174 Times

通过表达式选择:

(//td[@class="show_content"]/text())[4]

我通常会进行后处理以提取日期时间信息,即,2013-06-27 14:26现在由于我对 xpath 子字符串操作有了更多了解,我想知道是否有可能首先提取该信息,即,在 xpath 表达式本身?

谢谢,

4

3 回答 3

3

到目前为止,在所有其他答案中,这不仅/text()没有帮助,而且可能(甚至可能)是一个问题。对于档案的读者,他们应该意识到/text()在地址中使用函数参数的问题。text()在我的专业工作中,直接解决的要求非常(非常!)很少。

我说的是其他帖子中的这些表达:

substring-after(//td[@class='show_content']/text(), 'on ')

substring(//td[@class='show_content']/text(), 16, 10)

让我们把不应该使用“//”的问题放在一边。在 XSLT 1.0 中只<td>考虑第一个,而在 XSLT 2.0 中,第一个参数的多个单例将触发运行时错误。

如果它是输入,请考虑这个修改后的 XML:

   <td>[<emphasis>Rank Info</emphasis>] on 2013-06-27 14:26 Read 174 Times</td>

...其中“ on ”在第二个文本节点上(第一个文本节点中有“[”)。在 XSLT 1.0 中,两个表达式都返回空字符串。在 XSLT 2.0 中,这两个表达式都会触发运行时错误。

如果它是输入,请考虑这个修改后的 XML:

   <td>[Rank Info]<emphasis> on </emphasis>2013-06-27 14:26 Read 174 Times</td>

在这两种情况下,text()<td>节点都不包括字符串“on”,因为它是后代文本节点,而不是子文本节点。

那么,在这两个表达式中,以下内容将适用于两个修改后的输入,因为其中一个处理的是元素的值,而不是文本节点的值。元素的值是所有后代文本节点的串联。

所以:

substring-after(td[@class='show_content'], 'on ')

substring(td[@class='show_content'], 16, 10)

将作用于元素中找到的整个字符串值。但是,如果有多个<td>孩子,即使上述内容也会出现基数问题,因此无论如何都必须重写表达式。

我的意思是,使用text()引起了我的注意,我告诉我的学生如果他们认为需要text()在 XPath 表达式中使用,他们需要重新考虑,因为在大多数情况下他们不需要。

于 2013-06-29T00:31:36.163 回答
1

这应该工作

substring(//td[@class="show_content"]/text(), 16, 10)

但我同意 Blender,代码内后处理更适合此目的。

于 2013-06-28T22:19:41.413 回答
1

Scrapy 使用 XPath 1.0,它的字符串操作能力非常有限,尤其是不支持正则表达式。有两种方法可以减少字符串,我通过一个示例来演示这两种方法,以减少您正在寻找的子字符串。

按字符索引

如果字符索引不改变(但内容可以),这很好。

substring($string, $start, $len)
substring(//td[@class="show_content"]/text(), 16, 16)

按前/后缀搜索

如果索引可以更改,这很好,但字符串之前和之后的内容保持不变:

substring-before($string, $needle)
substring-after($string, $needle)
substring-before(
  substring-after(//td[@class="show_content"]/text(), 'on '), ' Read')
于 2013-06-28T22:22:05.540 回答