使用xpath 1.0中的contains函数选择数字

时间:2016-03-24 04:08:27

标签: regex xpath scrapy

我正在使用scrapy,我需要刮掉这样的东西:任何数字,然后是破折号,后跟任意数字,然后是空格,然后是两个字母(例如1-3毫米)。似乎xpath 1.0不允许使用正则表达式。搜索周围,我发现了一些解决方法,比如使用starts-with()和ends-with(),但是从我看到它们只用字母。请帮忙。

2 个答案:

答案 0 :(得分:3)

Scrapy在内部使用lxml,在添加相应的名称空间时使用lxml's XPath has support for regular expressions via EXSLT

默认情况下,Scrapy会将you can use re:test() within XPath expressions作为谓词的布尔值。

boolean re:test(string, string, string?)
  

如果作为第一个参数给出的字符串与作为第二个参数给出的正则表达式匹配,则re:test函数返回true。

请参阅此示例Python2会话:

>>> import scrapy
>>> t = u"""<!DOCTYPE html>
... <html lang="en">
... <body>
... <p>ab-34mm</p>
... <p>102-d mm</p>
... <p>15-22 µm</p>
... <p>1-3 nm</p>
... </body>
... </html>"""
>>> selector = scrapy.Selector(text=t)
>>> selector.xpath(r'//p/text()[re:test(., "\d+-\d+\s\w{2}")]').extract()
[u'15-22 \xb5m', u'1-3 nm']
>>> 

编辑:关于使用EXSLT re:match

的说明

使用EXSLT re:match有点棘手,或者至少不如re:test自然。 re:match类似于Python的re.match,它返回MatchObject

签名与re:test不同:

object regexp:match(string, string, string?)
  

regexp:match函数返回一组匹配元素

因此re:match将返回<match>元素。要从这些<match>元素中捕获字符串,您需要将该函数用作“外部”函数,而不是谓词内部。

以下示例链接XPath表达式

  1. 选择<p>
  2. 然后将每个段落字符串值(规范化)与包含带括号的组
  3. 的正则表达式进行匹配
  4. 最终提取这些re:match来电的结果
  5. Python2 shell:

    >>> for p in selector.xpath('//p'):
    ...     print(p.xpath(ur're:match(normalize-space(.), "(\d+)-(\d+)\s(\w{2})")').extract())
    ... 
    []
    []
    [u'<match>15-22 \xb5m</match>', u'<match>15</match>', u'<match>22</match>', u'<match>\xb5m</match>']
    [u'<match>1-3 nm</match>', u'<match>1</match>', u'<match>3</match>', u'<match>nm</match>']
    >>> 
    

答案 1 :(得分:0)

要使用xpath 1.0执行此操作,您可以使用translate函数。

translate(@test , '1234567890', '..........')将用点替换任何数字(数字)。

如果您的号码总是一位数,您可以尝试以下方式:

 [translate(@test , '1234567890', '..........') = '.-. mm']

如果数字可能比数字更长,您可能会尝试用零替换数字并测试- mm

[translate(@test , '1234567890', '') = '- mm']

但这可能会有一些虚假的真相。为避免它们,如果至少有一个数字

,则需要检查子串前后长度