Полоса\n\t\r в scrapy

Я пытаюсь вырезать символы \r\n\t с помощью scrapy spider, создавая json файл.

У меня есть объект описания, который заполнен новыми строками, и он не выполняет то, что я хочу: сопоставление каждого описания с заголовком.

Я попытался с картой (unicode.strip()), но на самом деле это не работает. Являясь новатором для исследования, я не знаю, есть ли еще один более простой способ или как работает unicode карты.

Это мой код:

def parse(self, response):
    for sel in response.xpath('//div[@class="d-grid-main"]'):
        item = xItem()
        item['TITLE'] = sel.xpath('xpath').extract()
        item['DESCRIPTION'] = map(unicode.strip, sel.xpath('//p[@class="class-name"]/text()').extract())

Я попробовал также:

item['DESCRIPTION'] = str(sel.xpath('//p[@class="class-name"]/text()').extract()).strip()

Но это вызвало ошибку. Какой лучший способ?

Ответы

Ответ 1

unicode.strip использует только пробельные символы в начале и конце строк

Верните копию строки с удалением ведущих и завершающих символов.

не с \n, \r, или \t в середине.

Вы можете использовать собственный метод для удаления этих символов внутри строки (используя модуль регулярных выражений) или даже использовать XPath normalize-space()

возвращает строку аргумента с пробелом, нормализованным путем удаления начального и конечного пробелов и замены последовательностей пробельных символов на единое пространство.

Пример сеанса оболочки python:

>>> text='''<html>
... <body>
... <div class="d-grid-main">
... <p class="class-name">
... 
...  This is some text,
...  with some newlines \r
...  and some \t tabs \t too;
... 
... <a href="http://example.com"> and a link too
...  </a>
... 
... I think we're done here
... 
... </p>
... </div>
... </body>
... </html>'''
>>> response = scrapy.Selector(text=text)
>>> response.xpath('//div[@class="d-grid-main"]')
[<Selector xpath='//div[@class="d-grid-main"]' data=u'<div class="d-grid-main">\n<p class="clas'>]
>>> div = response.xpath('//div[@class="d-grid-main"]')[0]
>>> 
>>> # you'll want to use relative XPath expressions, starting with "./"
>>> div.xpath('.//p[@class="class-name"]/text()').extract()
[u'\n\n This is some text,\n with some newlines \r\n and some \t tabs \t too;\n\n',
 u"\n\nI think we're done here\n\n"]
>>> 
>>> # only leading and trailing whitespace is removed by strip()
>>> map(unicode.strip, div.xpath('.//p[@class="class-name"]/text()').extract())
[u'This is some text,\n with some newlines \r\n and some \t tabs \t too;', u"I think we're done here"]
>>> 
>>> # normalize-space() will get you a single string on the whole element
>>> div.xpath('normalize-space(.//p[@class="class-name"])').extract()
[u"This is some text, with some newlines and some tabs too; and a link too I think we're done here"]
>>> 

Ответ 2

Поскольку paul trmbrth предлагает в своем ответе,

div.xpath('normalize-space(.//p[@class="class-name"])').extract()

скорее всего будет тем, что вы хотите. Однако normalize-space также конденсирует пробелы, содержащиеся в строке, в одно пространство. Если вы хотите удалить только \r, \n и \t, не нарушая другие пробелы, вы можете использовать translate() для удалить символы.

trans_table = {ord(c): None for c in u'\r\n\t'}
item['DESCRIPTION] = ' '.join(s.translate(trans_table) for s in sel.xpath('//p[@class="class-name"]/text()').extract())

Это все равно оставит пробелы ведущего и конечного пробелов, которые не входят в набор \r, \n или \t. Если вы также хотите избавиться от этого, просто вставьте вызов strip():

item['DESCRIPTION] = ' '.join(s.strip().translate(trans_table) for s in sel.xpath('//p[@class="class-name"]/text()').extract())

Ответ 3

Я питон, новичок в scrapy, сегодня у меня была аналогичная проблема, решил это с помощью следующего модуля/функции w3lib. html.replace_escape_chars Я создал процессор ввода по умолчанию для моего загрузчика товаров, и он работает без каких-либо проблем, вы можете связать это с конкретной scrapy.Field() также и хорошо, что он работает с css-селекторами и Экспорт кормов csv:

from w3lib.html import replace_escape_chars
yourloader.default_input_processor = MapCompose(relace_escape_chars)