Python - Удалить вкладку и новую строку в объекте - PullRequest
0 голосов
/ 03 июля 2018

Просто новый пользователь scrapy.org и новичок в Python. У меня есть эти значения в brand и title properties ( JAVA OOP Term ), который содержит символы табуляции и новую строку. Как мы можем обрезать его, чтобы сделать следующие 2 свойства объекта, чтобы иметь это простое строковое значение

item['brand'] = "KORAL ACTIVEWEAR"
item['title'] = "Boom Leggings"

Ниже приведена структура данных

{'store_id': 870, 'sale_price_low': [], 'brand': [u'\n                KORAL ACTIVEWEAR\n              '], 'currency': 'AUD', 'retail_price': [u'$140.00'], 'category': [u'Activewear'], 'title': [u'\n                Boom Leggings\n              '], 'url': [u'/boom-leggings-koral-activewear/vp/v=1/1524019474.htm?folderID=13331&fm=other-shopbysize-viewall&os=false&colorId=68136'], 'sale_price_high': [], 'image_url': [u'  https://images-na.sample-store.com/images/G/01/samplestore/p/prod/products/kacti/kacti3025868136/kacti3025868136_q1_2-0._SH20_QL90_UY365_.jpg\n'], 'category_link': 'https://www.samplestore.com/clothing-activewear/br/v=1/13331.htm?baseIndex=500', 'store': 'SampleStore'}

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

price = re.compile('[0-9\.]+')
item['retail_price'] = filter(price.search, item['retail_price'])

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

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

import six

def normalize(obj):
    if isinstance(obj, six.string_types):
        return ' '.join(obj.split())
    elif isinstance(obj, list):
        return [normalize(x) for x in obj]
    elif isinstance(obj, dict):
        return {k:normalize(v) for k,v in obj.items()}
    return obj

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

Для вашего примера item

>> item = {'store_id': 870, 'sale_price_low': [], 'brand': [u'\n                KORAL ACTIVEWEAR\n              '], 'currency': 'AUD', 'retail_price': [u'$140.00'], 'category': [u'Activewear'], 'title': [u'\n                Boom Leggings\n              '], 'url': [u'/boom-leggings-koral-activewear/vp/v=1/1524019474.htm?folderID=13331&fm=other-shopbysize-viewall&os=false&colorId=68136'], 'sale_price_high': [], 'image_url': [u'  https://images-na.sample-store.com/images/G/01/samplestore/p/prod/products/kacti/kacti3025868136/kacti3025868136_q1_2-0._SH20_QL90_UY365_.jpg\n'], 'category_link': 'https://www.samplestore.com/clothing-activewear/br/v=1/13331.htm?baseIndex=500', 'store': 'SampleStore'}

>> print (normalize(item))
>> {'category': [u'Activewear'], 'store_id': 870, 'sale_price_low': [], 'title': [u'Boom Leggings'], 'url': [u'/boom-leggings-koral-activewear/vp/v=1/1524019474.htm?folderID=13331&fm=other-shopbysize-viewall&os=false&colorId=68136'], 'brand': [u'KORAL ACTIVEWEAR'], 'currency': 'AUD', 'image_url': [u'https://images-na.sample-store.com/images/G/01/samplestore/p/prod/products/kacti/kacti3025868136/kacti3025868136_q1_2-0._SH20_QL90_UY365_.jpg'], 'category_link': 'https://www.samplestore.com/clothing-activewear/br/v=1/13331.htm?baseIndex=500', 'sale_price_high': [], 'retail_price': [u'$140.00'], 'store': 'SampleStore'}
0 голосов
/ 03 июля 2018

Похоже, что все, что вам нужно сделать, по крайней мере для этого примера, это убрать все пробелы с краев значений brand и title. Для этого вам не нужно регулярное выражение, просто вызовите метод strip.

Однако ваш brand не является единственной строкой; это список строк (даже если в списке только одна строка). Таким образом, если вы попытаетесь просто strip или запустить регулярное выражение, вы получите AttributeError или TypeError от попытки обработать этот список как строку.

Чтобы это исправить, вам нужно отобразить strip по всем строкам, либо с помощью функции map, либо со списком:

item['brand'] = [brand.strip() for brand in item['brand']]
item['title'] = map(str.strip, item['title'])

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


Если у вас есть другие примеры со встроенными пробелами пробелов, и вы хотите превратить каждый такой пробел в ровно один пробел, вам нужно использовать метод sub с вашим регулярным выражением:

item['brand'] = [re.sub(ur'\s+', u' ', brand.strip() for brand in item['brand']]

Обратите внимание на префиксы u. В Python 2 вам нужен префикс u, чтобы сделать литерал unicode вместо литерала str (закодированные байты). И важно использовать шаблоны Unicode против строк Unicode, даже если сам шаблон не заботится о любых не-ASCII символах. (Если все это кажется бессмысленной болью и магнитом ошибки - ну, это так; это главная причина, по которой существует Python 3.)


Что касается retail_price, применяются те же основные наблюдения. Опять же, это список строк, а не просто строка. И опять же, вам, вероятно, не нужно регулярное выражение. Предполагая, что цена всегда равна $ (или другой односимвольный маркер валюты), за которым следует число, просто отрежьте $ и назовите float или Decimal:

item['retail_price'] = [float(price[1:]) for price in item['retail_price']]

… но если у вас есть примеры, которые выглядят по-разному, с произвольными дополнительными символами по обе стороны от цены, вы можете использовать re.search здесь, но вам все равно потребуется сопоставить его и использовать шаблон Unicode.

Вам также нужно извлечь соответствующий group из поиска и каким-то образом обработать пустые / недействительные строки (они будут возвращать None для поиска, и вы не можете преобразовать это в float). Вы должны решить, что с этим делать, но после попытки с filter похоже, что вы просто хотите их пропустить. Это достаточно сложно, так что я бы сделал это в несколько шагов:

prices = item['price']
matches = (re.search(r'[0-9.]+', price) for price in prices)
groups = (match.group() for match in matches if match)
item['price'] = map(float, validmatches)

… или, может быть, обернуть это в функцию.

...