2016-02-12 4 views
3

В моем Scrapy паука, я хочу, чтобы выбрать только <p> с содержанием текста:Scrapy: Выберите тег с неразрывный пробел с помощью XPath

item['Description'] = response.xpath('//*[@id="textepresentation"]//p[string(.)]').extract() 

Он отлично работает, но, к сожалению, делать это, я также получить пустой <p> с неразрывным пробелом

u'<p>\xa0</p>', 

Как избежать выбора <p> с неразрывным пробелом с помощью XPath?

ответ

2

Вы можете использовать XPath's normalize-space() строковую функцию для этого с несколькими предикатами:

  • [normalize-space()] так, что вы получите элементы с непустой строки представления, исключающие начальные и конечные пробелы
  • [not(contains(normalize-space(), "\u00a0"))] потому что NO-BREAK SPACE не удаляется (см. this other answer where I checked which ones work, вы можете добавить другие символы для проверки)

Пример:

>>> 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>'] 
>>> 

Edit:

следуя на из @ ответа Киого, вот альтернатива с 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>'] 
>>> 
+0

Спасибо за это ценное подробное объяснение! Он работает так, как ожидалось. Благодаря ! – jacquesseite

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

Хорошая попытка, но 'объект [ 'Описание'] = response.xpath (» // * [@ id = "textepresentation"] // p [translate (string (.), '\ xa0', '')] '). extract() SyntaxError: неожиданный символ после символа продолжения строки – jacquesseite

+0

@jacquesseite Конфликт разделителей строк. Последовательно используйте двойные кавычки в выражении XPath. I.e 'translate (string (.)," \ Xa0 "," ")' – har07

+0

Отредактировано для использования двойных кавычек. –