【问题标题】:Python - Remove tab and new line in ObjectPython - 删除对象中的选项卡和新行
【发布时间】:2018-12-11 07:02:21
【问题描述】:

只是一个 scrapy.org 的新用户和 Python 的新手。我在包含制表符空格和换行符的 brandtitle 属性(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'])

【问题讨论】:

  • 它看起来只有前导和尾随空格 - 像x.strip() 这样的东西应该足够好。为什么是正则表达式?

标签: python python-2.7 scrapy scrapy-pipeline


【解决方案1】:

看起来你需要做的所有事情,至少在这个例子中,就是去掉brandtitle 值边缘的所有空白。您不需要正则表达式,只需调用 strip 方法即可。

但是,您的 brand 不是单个字符串;它是一个字符串列表(即使列表中只有一个字符串)。因此,如果您尝试仅使用 strip 或对其运行正则表达式,您将通过尝试将该列表视为字符串而得到 AttributeErrorTypeError

要解决此问题,您需要使用 map 函数或列表推导将 strip 映射到所有字符串:

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,同样的基本观察也适用。同样,它是一个字符串列表,而不仅仅是一个字符串。同样,您可能不需要正则表达式。假设价格始终是 $(或其他单字符货币标记)后跟数字,只需切掉 $ 并调用 floatDecimal 即可:

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

...但是如果您有看起来不同的示例,价格两边有任意额外字符,您可以在此处使用re.search,但您仍然需要对其进行映射,并使用 Unicode 模式。

您还需要从搜索中获取匹配的 group,并以某种方式处理空/无效字符串(它们将返回 None 进行搜索,您无法将其转换为 @ 987654346@)。您必须决定如何处理它,但从您对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)

…或者可能将其包装在一个函数中。

【讨论】:

  • 得到一个错误:item['brand'] = item['brand'].strip() AttributeError: 'list' object has no attribute 'strip' 注意item['brand']有这个值 [u'\n KORAL ACTIVEWEAR\n ']。我不知道左括号 [ 后面的“u”是什么
  • @user1441797 答案解释了为什么你会得到AttributeError,以及如何处理它,还解释了u 前缀。我已经对其进行了编辑以进一步解释。
  • 我喜欢你解释整个事情的方式。解决了我的问题。点赞!非常感谢!
  • 对于retailer_price 的东西。我确实遇到了不同的货币前缀。这取决于网站如何使用货币缩写和符号显示价格。例如。 12.99 澳元、12.99 美元、12.99 美元
  • item['retail_price'] = [float(re.search(ur'[0-9.]+', price)) for price in item['retail_price']] 导致 TypeError: float() 参数必须是字符串或数字
【解决方案2】:

你可以定义一个像下面这样的方法,它接受一个对象并返回所有归一化的叶子。

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 = {'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'}

【讨论】:

    猜你喜欢
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    • 2020-03-21
    • 2012-08-08
    • 2021-11-11
    相关资源
    最近更新 更多