我正在使用scrapy,我需要刮掉这样的东西:任何数字,然后是破折号,后跟任意数字,然后是空格,然后是两个字母(例如1-3毫米)。似乎xpath 1.0不允许使用正则表达式。搜索周围,我发现了一些解决方法,比如使用starts-with()和ends-with(),但是从我看到它们只用字母。请帮忙。
答案 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表达式
<p>
段re:match
来电的结果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']
但这可能会有一些虚假的真相。为避免它们,如果至少有一个数字
,则需要检查子串前后长度