Scrapy:使用XPath选择包含非断空格的标签

3
在我的Scrapy爬虫中,我希望只选择文本内容为<p>的标签:
item['Description'] = response.xpath('//*[@id="textepresentation"]//p[string(.)]').extract()

它的功能正常,但不幸的是,在这样做的情况下,我也得到了一个带有不间断空格的空<p>
u'<p>\xa0</p>',

如何使用xpath避免选择带有非断空格的<p>元素?
2个回答

2
您可以使用XPath的normalize-space()字符串函数,并添加一些谓词来实现此功能:
  • [normalize-space()],以便获取具有非空字符串表示且不包括前导和尾随空格的元素
  • [not(contains(normalize-space(), "\u00a0"))],因为NO-BREAK SPACE不会被移除(请参见我检查哪些字符有效的另一个答案,您可能需要添加其他字符进行测试)

示例:

>>> import scrapy
>>> selector = scrapy.Selector(text=u'''
... <html>
...     <p>&nbsp;</p>
...     <p>something</p>
...     <p>  </p>
...     <p><a href="http://example.com">some link</a></p>
... </html>
... ''')
>>> selector.xpath(u'''
...     //p[normalize-space()]
...        [not(contains(normalize-space(), "\u00a0"))]
... ''').extract()
[u'<p>something</p>', u'<p><a href="http://example.com">some link</a></p>']
>>> 

编辑:
在 @Kimmy 答案的基础上,这里提供了一种使用 1 个谓词的替代方案,适用于其他空白字符:
  • 取出未被 normalize-space() 替换的空白字符
  • 并将它们放入一个带有 ' ' 的 XPath translate() 调用中
  • 规范化空格,修剪前导和尾随空格
下面是具体实现:
>>> chars = '''
... #CHARACTER TABULATION
... #LINE FEED
... #LINE TABULATION
... #FORM FEED
... #CARRIAGE RETURN
... #SPACE
... #NEXT LINE
... NO-BREAK SPACE
... OGHAM SPACE MARK
... MONGOLIAN VOWEL SEPARATOR
... EN QUAD
... EM QUAD
... EN SPACE
... EM SPACE
... THREE-PER-EM SPACE
... FOUR-PER-EM SPACE
... SIX-PER-EM SPACE
... FIGURE SPACE
... PUNCTUATION SPACE
... THIN SPACE
... HAIR SPACE
... ZERO WIDTH SPACE
... ZERO WIDTH NON-JOINER
... ZERO WIDTH JOINER
... LINE SEPARATOR
... PARAGRAPH SEPARATOR
... NARROW NO-BREAK SPACE
... MEDIUM MATHEMATICAL SPACE
... WORD JOINER
... IDEOGRAPHIC SPACE
... ZERO WIDTH NO-BREAK SPACE
... '''
>>> import unicodedata
>>> wsp = [unicodedata.lookup(c)
...        for c in chars.splitlines()
...        if c.strip() and not c.startswith('#')]
>>> 
>>> # somehow NEXT LINE (U+0085) does not work with unicodedata
... wsp.append(u'\u0085')
>>> 
>>> selector.xpath(u'''
...     //p[normalize-space(translate(., "%(in)s", "%(out)s"))]
...     ''' % {'in': ''.join(wsp),
...            'out': ' '*len(wsp)
...     }).extract()
[u'<p>something</p>', u'<p><a href="http://example.com">some link</a></p>']
>>> 

非常感谢您提供这么有价值的详细解释!它的效果符合预期。谢谢! - jacquesseite

0
//p[translate(string(.),"\xa0","")]

尝试不错,但是item['Description'] = response.xpath('//*[@id="textepresentation"]//p[translate(string(.),'\xa0','')]').extract() SyntaxError: 行继续字符后出现意外字符 - jacquesseite
@jacquesseite 字符串分隔符冲突。在您的XPath表达式中始终使用双引号,例如 translate(string(.),"\xa0","") - har07
已编辑为使用双引号。 - Kim Homann
感谢@har07。这次出现了“ValueError: All strings must be XML compatible: Unicode or ASCII, no NULL bytes or control characters”错误,正在努力解决中... - jacquesseite

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接