Как бы вы очистили этот словарь в Python?

#python #dictionary #web-scraping

#python #словарь #очистка веб-страниц

Вопрос:

Это моя первая попытка создать что-то не веб-и включающее логическое кодирование.

Пожалуйста, взгляните на этот ужасный словарь ниже:

   Messy_Dict=
    {
        'name': "['\r\n                  NASDAQ: BKEP\r\n          ']", 
        'underlying': "['1.12']", 
        'strike_prices_list': ["['2.50'", " '5.00'", " '7.50']"], 
        'call_bid': ["['\r\n0.05            '", " '\r\n0.00            '", " '\r\n0.00            ']"], 
        'put_ask': ["['\r\n2.10            '", " '\r\n4.50            '", " '\r\n7.00            ']"]
    }
  

Что я хочу сделать, так это очистить ненужные подстроки внутри каждого значения словаря, чтобы получить что-то вроде этого:

 Clean_Dict=
    {
        'name': "BKEP", 
        'underlying': "1.12", 
        'strike_prices_list': ["2.50", "5.00", "7.50"], 
        'call_bid': ["0.05", "0.00", "0.00"], 
        'put_ask': ["2.10", "4.50", "7.00"]
    }
  

Мне удалось перейти от Messy_Dict к Clean_Dict, но я использовал для этого очень варварские средства. Я просто скажу, что он включал цикл for и несколько методов strip(), replace(«, «). И мне больно смотреть на этот блок кода в моем файле .py.

Итак, я думаю, есть ли более элегантный метод для выполнения желаемой задачи преобразования Messy_Dict в Clean_Dict? Я чувствую, что мне чего-то не хватает в моих основах.

Редактировать

 def parse(self, response):
        strike_prices_main = response.css('.highlight , .aright .strike-col').css('::text').extract()
        if not strike_prices_main:
            pass
        else:
            name = response.css('#instrumentticker::text').extract()
            strike_prices_list = response.css('.aright .strike-col').css('::text').extract()
            call_bid = response.css('.aright td:nth-child(5)').css('::text').extract()
            put_ask = response.css('.aright td:nth-child(14)').css('::text').extract()
            underlying = response.css('.pricewrap .bgLast').css('::text').extract()
            file.write('%s|%s|%s|%s|%sn'%(name,underlying,strike_prices_list,call_bid,put_ask))
  

Используя пауков для обхода!

Комментарии:

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

2. правильный вопрос в этом случае заключается в том, откуда берется «беспорядочный» dict. Это очень похоже на JSON, который каким-то образом подвергся злоупотреблениям, чтобы стать таким… Возможно, ответ json, который не был обработан должным образом?

3. Сколько циклов for и операторов регулярных выражений это заняло бы?

4. @buran я очищал Yahoo Finance, чтобы получить некоторые данные! И, черт возьми, это было напечатано в моем cmd prmt, хахаха, ой

5. @LowaiisTan, Итак, мое предположение верно, и лучшим подходом было бы показать ваш код, который запрашивает Yahoo finance, и получить помощь с ним. В нынешнем виде это проблема XY. Вы можете получить идеально отформатированный действительный ответ в формате JSON от yahoo finance

Ответ №1:

Может быть, вот так:

 import re
Messy_Dict= 
{
    'name': "['\r\n                  NASDAQ: BKEP\r\n          ']", 
    'underlying': "['1.12']", 
    'strike_prices_list': ["['2.50'", " '5.00'", " '7.50']"], 
    'call_bid': ["['\r\n0.05            '", " '\r\n0.00            '", " '\r\n0.00            ']"], 
    'put_ask': ["['\r\n2.10            '", " '\r\n4.50            '", " '\r\n7.00            ']"]
}
regexstr = "\\(r|n)|s|[|]|'|NASDAQ:"

dict_clean = {}
for k, v in Messy_Dict.items():
    if isinstance(v, list):
        list_clean = []
        for el in v:            
            el_clean = re.sub(regexstr, "", el)
            list_clean.append(el_clean)
        dict_clean[k] = list_clean
    else:
        dict_clean[k] = re.sub(regexstr, "", v)
dict_clean
  

Ответ №2:

Вы можете использовать регулярные выражения.

Пример:

 import re

messy_dict = {
    'name': "['\r\n                  NASDAQ: BKEP\r\n          ']", 
    'underlying': "['1.12']", 
    'strike_prices_list': ["['2.50'", " '5.00'", " '7.50']"], 
    'call_bid': ["['\r\n0.05            '", " '\r\n0.00            '", " '\r\n0.00            ']"], 
    'put_ask': ["['\r\n2.10            '", " '\r\n4.50            '", " '\r\n7.00            ']"]
}

for key in messy_dict:
    stripfunc = lambda x: re.sub('[^d.]', '', str(x))
    if type(messy_dict[key]) is list:
        messy_dict[key] = [stripfunc(x) for x in messy_dict[key]]
    else:
        messy_dict[key] = stripfunc(messy_dict[key])

print(messy_dict)
  

Объяснение: [^ ] соответствует всему, чего нет в наборе. d предназначен для числовых значений, а обратная косая черта скрывает точку. Используя str (val) для создания строк из списков.

Вывод: {'name': '', 'underlying': '1.12', 'strike_prices_list': ['2.50', '5.00', '7.50'], 'call_bid': ['0.05', '0.00', '0.00'], 'put_ask': ['2.10', '4.50', '7.00']}

Редактировать: только что заметил, что вы также хотите сохранить точку. Обновил код.

Комментарии:

1. Упс, я этого не делал. Исправлено.

2. Предпочел бы немного большую точность в обмен на меньшую краткость!

3. Ага, это генерирует результат, о котором вы просили?