Цикл через csv, запись новых значений в csv

#python #python-3.x #regex #loops #csv

#python #python-3.x #регулярное выражение #циклы #csv

Вопрос:

Введение

Поскольку я работал со scrapy последние два месяца, я сделал перерыв и начал изучать форматирование текста с помощью python. Я получил некоторые данные, доставленные моим webcrawler, которые хранятся в файле .CSV, как вы можете видеть ниже:

Мой CSV-файл .CSV

 SKU
"
                Article nr. : 560821800 / D26 x H10 cm
            "
"
                Article nr. : 560828100 / D14 x H11 cm
            "
"
                Article nr. : 560821400 / D13 x H10 cm
            "
"
                Article nr. : 560821900 / L17 x W17 x H14
            "
"
                Article nr. : 560828900 / L17 x W17 x H14
            "
"
                Article nr. : 560821600 / D16 x H13 cm
            "
"
                Article nr. : 560828300 / D16 x H13 cm
            "
"
                Article nr. : 560827900 / D13 x H10 cm
            "
"
                Article nr. : 560829000 / L17 x W17 x H14
            "
  

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

Теперь я немного поиграл, и мне удалось удалить все пробелы и другие ненужные цифры, поэтому у меня есть только f.e 560821800 , который обозначает идентификаторы определенных продуктов.

Теперь я открыл файл .csv, отредактировал значения и попытался записать его в новый файл .csv, который я назвал output .

«Выходной» файл содержит только один столбец, который я хотел назвать «SKU».

Код

 import csv
import re
    
with open(r'C:Usersy.yOneDrive - company namePython3_Textformatierungsku.csv', 'r') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    for row in csv_reader:
        sku = row.pop()
        sku = re.sub(r'[stn] |(.) |(:)', '', sku)
        sku = sku.replace('Articlenr', '')
        print(sku)#string splitted to ['560827900', 'D13xH10cm']
        string_to_list = sku.split('/')#splits string to list
        print(string_to_list)
        sku_string = string_to_list.pop(0)
        print(sku_string)#only value of sku remains
  

После запуска этого кода я получил следующий вывод:

 SKU
['SKU']
SKU
560821800/D26xH10cm
['560821800', 'D26xH10cm']
560821800
560828100/D14xH11cm
['560828100', 'D14xH11cm']
560828100
560821400/D13xH10cm
['560821400', 'D13xH10cm']
560821400
560821900/L17xW17xH14
['560821900', 'L17xW17xH14']
560821900
560828900/L17xW17xH14
['560828900', 'L17xW17xH14']
560828900
560821600/D16xH13cm
['560821600', 'D16xH13cm']
560821600
560828300/D16xH13cm
['560828300', 'D16xH13cm']
560828300
560827900/D13xH10cm
['560827900', 'D13xH10cm']
560827900
560829000/L17xW17xH14
['560829000', 'L17xW17xH14']
560829000
  

Моя проблема
Я хочу собрать каждое отдельное значение sku_string и записать их в output.csv-файл, но в новый файл передается только имя поля.

Я попробовал эту задачу со следующим кодом:

 #write data to csv with fieldname['SKU']
with open(r'C:PathtoOutput.csv', 'w') as csv_file:
    fieldname = ['SKU']
    csv_writer = csv.DictWriter(csv_file, fieldnames=fieldname, delimiter=',')
    csv_writer.writeheader()
    print(sku_string)
    for s in row:
        csv_writer.writerow(['SKU', sku_string])
  

Я также признал, что последний оператор печати, который я использовал (только для тестирования), содержит только одно значение, чего мне не хватает?

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

Обновить

Я переработал свой код, но он по-прежнему записывает только последний вывод в файл Output.csv ._.

 import csv
import re


with open(r'Pathtosku.csv', 'r') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    for row in csv_reader:
        row = row.pop()#convert from list to str        
        row = row.split('/')#convert str to list with 2 elements, splitted by '/'
        sku_string = row.pop(0)#string with Articlenr   SKU
        sku_string = sku_string.split(':')
        only_sku = sku_string.pop()
        #every string contains only sku now
        print(only_sku)     
        
with open(r'C:PathtoOutput.csv', 'w') as csv_file:
    fieldname = ['SKU']
    writer = csv.DictWriter(csv_file, delimiter=',', fieldnames=fieldname)
    writer.writeheader()
    for x in only_sku:
        writer.writerow({'SKU' : only_sku})
  

Output.csv

output.csv

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

1. Почему вы используете csvreader? Ваш файл не является csv или, если на то пошло, файлом с разделенными значениями <anything> .

2. @PranavHosangadi Это исходный результат, который предоставил мне мой поисковый робот. Как вы думаете, почему это не файл csv? Как вы думаете, pandas будет лучше, чем csvreader?

3. Это не файл csv, потому что csv обозначает значения, разделенные запятыми, что означает, что он похож на лист Excel, за исключением того, что столбцы разделены запятыми. Файл csv с одним столбцом — это, по сути, обычный файл с одной записью в строке.

4. хорошо, я проверяю это, он взял некоторые значения из моего «реального csv» просто для практики, но я никогда не думал об этом, что это может вызвать мою ошибку, спасибо за это, приятель!

Ответ №1:

Я использовал немного другой подход и изменил ваш .csv файл на .txt файл, поскольку, честно говоря, все, что у вас там есть, не похоже на структуру CSV.

Вот что я придумал:

 import csv

with open("sample.txt") as f:
    lines = f.readlines()

parsed_lines = [l for l in [l.strip() for l in lines] if l != '"' and l != "SKU"]
parsed_lines = [l.replace("Article nr. : ", "").split("/") for l in parsed_lines]

with open("output.csv", "w") as output:
    w = csv.writer(output)
    w.writerow(["Article nr.", "Dimensions"])
    w.writerows(parsed_lines)
  

Вывод:

   Article nr.  Dimensions
-------------  ---------------
   560821800   D26 x H10 cm
   560828100   D14 x H11 cm
   560821400   D13 x H10 cm
   560821900   L17 x W17 x H14
   560828900   L17 x W17 x H14
   560821600   D16 x H13 cm
   560828300   D16 x H13 cm
   560827900   D13 x H10 cm
   560829000   L17 x W17 x H14
  

Или в .csv файле:

введите описание изображения здесь

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

1. эй, бадукер, ваше предложение также сработало для меня 🙂 Мне никогда не приходила в голову мысль, что мой csv сломан. Ваше решение сделано хорошо, но для моего уровня квалификации на данный момент, я думаю, слишком высоко:> ваша биография забавная, теперь мне жаль, что я не могу поставить вам галочку:(

2. @y.y рад, что это сработало. Если это кажется немного подавляющим, взгляните на список понимания Python, это может многое объяснить.

3. мне определенно нужно подробно изучить некоторые функции python. хорошего дня 🙂

Ответ №2:

Новые значения из каждой строки записываются в вашу only_sku строку внутри for row in csv_reader: цикла. Если вы хотите получить доступ к этим значениям вне цикла, вам нужно будет где-то их собрать, например, добавив их в список.

Таким образом, ваш цикл чтения становится:

 all_sku = []
with open(r'Pathtosku.csv', 'r') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    for row in csv_reader:
        row = row.pop()#convert from list to str        
        row = row.split('/')#convert str to list with 2 elements, splitted by '/'
        sku_string = row.pop(0)#string with Articlenr   SKU
        sku_string = sku_string.split(':')
        only_sku = sku_string.pop().strip()
        #every string contains only sku now
        print(only_sku)     
        all_sku.append(only_sku)
  

Обратите внимание, как мы добавляем последнее значение, которое мы читаем, в наш список всех используемых значений all_sku.append() . Мы также хотим удалить начальные и конечные пробелы из наших значений.

И затем вы можете написать в другом цикле следующим образом:

 with open(r'C:PathtoOutput.csv', 'w') as csv_file:
    fieldname = ['SKU']
    writer = csv.DictWriter(csv_file, delimiter=',', fieldnames=fieldname)
    writer.writeheader()
    for x in all_sku:
        writer.writerow({'SKU' : x})
  

Обратите внимание, что теперь мы перебираем all_sku и записываем каждый элемент этого списка.


Теперь, если вы хотите, чтобы измерения также были записаны в ваш новый файл csv, вам также нужно будет отслеживать это значение. Вместо создания списка строк, как мы делали ранее, проще создать список dict строк, к которым мы хотим перейти writer.writerow() позже. Таким образом, у нас было бы:

 all_rows = []
with open(r'Pathtosku.csv', 'r') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    for row in csv_reader:
        row = row.pop() #convert from list to str        
        row = row.split('/')#convert str to list with 2 elements, splitted by '/'
        sku_string = row[0]
        dims_string = row[1].strip()
        sku_string = sku_string.split(':')
        only_sku = sku_string[1].strip()
        all_sku.append({'SKU': only_sku, 'Dimensions': dims_string})
  

А затем напишите так:

 with open(r'C:PathtoOutput.csv', 'w') as csv_file:
    fieldname = ['SKU', 'Dimensions']
    writer = csv.DictWriter(csv_file, delimiter=',', fieldnames=fieldname)
    writer.writeheader()
    for row_dict in all_rows:
        writer.writerow(row_dict)
  

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

1. я также пытался передать значения в список раньше, но я неправильно записал его в своем цикле. Спасибо за все и добрый день!