在Python中解析不可用的csv文件

时间:2014-04-13 18:18:08

标签: python csv

我的朋友让我帮他解析eBay csv文件并只保存几个重要字段,所以我认为这将是学习Python的好机会(现在主要用C语言写作)。

问题是,eBay csv文件格式让我很难过:

    Numer rekordu sprzedaży,Nazwa użytkownika,Imię i nazwisko kupującego,Numer telefonu kupującego,Adres e-mail kupującego,Adres 1 kupującego,Adres 2 kupującego,Miejscowość kupującego,Województwo kupującego,Kod pocztowy kupującego,Kraj kupującego,Numer przedmiotu,Nazwa przedmiotu,Etykieta niestandardowa,Ilość,Cena sprzedaży,Wysyłka i obsługa,Ubezpieczenie,Koszt płatności za pobraniem,Cena łączna,Forma płatności,Data sprzedaży,Data realizacji transakcji,Data zapłaty,Data wysyłki,Opinia wystawiona,Opinia otrzymana,Uwagi własne,Identyfikator transakcji PayPal,Usługa wysyłkowa,Opcja płatności za pobraniem,Identyfikator transakcji,Identyfikator zamówienia,Szczegóły wersji

"610","xxx","John Rodriguez","(860) 000-00000","mail@yahoo.com","0 Branford Ave Bldg 11","","City","CT","00000","Stany Zjednoczone","330972592582","Honda CBR 900 RR","","1","US $21,49","US $5,50","US $0,00","","US $26,99","PayPal","23-03-2014","23-03-2014","23-03-2014","","Nie","","","4EP58","Standard Shipping from outside US","","9639014","",""
"627","yyy","Name","063100000","mail@orange.fr","Rue barillettes","","st main","Rhône","00000","Francja","3311071","Suzuki SV 650","","1","EUR 15,99","EUR 4,00","EUR 0,00","","EUR 19,99","PayPal","31-03-2014","31-03-2014","31-03-2014","","Nie","","","6E03683046","Livraison standard ? partir de l'étranger","","9659014","",""

Pobrano rekordów: 8,,od ,23-03-2014,15:06:14, do ,11-04-2014,14:32:17
Nazwa sprzedawcy: mail@gmail.com

使用csv.DictReader解析它,就像在手册中一样,每行都会像none : list[]

那样进行解析
import csv

filename = "SalesHistory.csv"

csvfile = open(filename, encoding="iso-8859-2")
input_file = csv.DictReader(csvfile, quotechar='"', skipinitialspace=True)

for row in input_file:
    print (row)
{None: ['\tNumer rekordu sprzedaży', 'Nazwa użytkownika', 'Imię i nazwisko kupującego', 'Numer telefonu kupującego',
        'Adres e-mail kupującego', 'Adres 1 kupującego', 'Adres 2 kupującego', 'Miejscowość kupującego',
        'Województwo kupującego', 'Kod pocztowy kupującego', 'Kraj kupującego', 'Numer przedmiotu', 'Nazwa przedmiotu',
        'Etykieta niestandardowa', 'Ilość', 'Cena sprzedaży', 'Wysyłka i obsługa', 'Ubezpieczenie',
        'Koszt płatności za pobraniem', 'Cena łączna', 'Forma płatności', 'Data sprzedaży',
        'Data realizacji transakcji', 'Data zapłaty', 'Data wysyłki', 'Opinia wystawiona', 'Opinia otrzymana',
        'Uwagi własne', 'Identyfikator transakcji PayPal', 'Usługa wysyłkowa', 'Opcja płatności za pobraniem',
        'Identyfikator transakcji', 'Identyfikator zamówienia', 'Szczegóły wersji']}

而不是,第一行读取为其他行中的事务的键。

我阅读了Python CSV手册,查看了一些示例,搜索了Stack Overflow,但我仍然不知道下一步该做什么 - 其中大多数都涵盖了更多'标准'版本的csv。

让我朝着正确的方向前进的任何提示都会很棒。

2 个答案:

答案 0 :(得分:0)

那很奇怪...你的代码没有给我你在你的问题中发布的错误(尽管我使用的是Python 2.7,你似乎使用的是3.x ,也许是因为那个)。

此外,文件不以空白(空行)开头,是吗?如果是这样,它将搞乱csv模块。它使用第一行来猜测csv.DictReader将使用的键。如果开头有空行,则无法猜出密钥。你应该"清洁"在尝试使用csv解析它之前的文件(删除空行应该可以做到这一点)或者你可以逐行读取空行,但这会使用csv.DictReader变得复杂(你应该得到第一个非空行,考虑其值为结果字典的,然后读取其余行,将其值视为结果字典的 ... I&#39 ; d只是在解析之前从文件中删除空行)

在下面的代码中,我添加了一个try/catch块来处理不完整的行(例如示例文件中的最后两行),但即使没有它,它也能正常工作

import csv

filename = "SalesHistory.csv"
read_dcts = []

with open(filename, 'r') as csvfile:
    input_file = csv.DictReader(csvfile, quotechar='"', skipinitialspace=True)
    for i, dct in enumerate(input_file):
        try:
            utf_dict=dict((k.decode('utf-8'), v.decode('utf-8')) \
                          for k, v in dct.items())
            read_dcts.append(utf_dict)
        except AttributeError:
            print "Weird line %d found" % (i + 1)

# Verify:
for i, dct in enumerate(read_dcts):
    print "Dict %d" % (i + 1)
    for k, v in dct.iteritems():
        print "\t%s: %s" % (k, v)

如果我执行上面的代码,我会得到:

Weird line 3 found
Weird line 4 found
Dict 1
        Opinia otrzymana: 
        Cena sprzedaży: US $21,49
        [ . . . ]
        Wysyłka i obsługa: US $5,50
        Opcja płatności za pobraniem: 
Dict 2
        Opinia otrzymana: 
        Cena sprzedaży: EUR 15,99
        [ . . . ]
        Wysyłka i obsługa: EUR 4,00
        Opcja płatności za pobraniem

为了清楚起见,我删除了许多加载的行,但除此之外,它应该加载您想要的内容。

如果您有更新,请通过评论告诉我。

修改

如果文件中包含空行并且您不想预先清理它,您几乎可以手动操作" DictReader类为您做什么(使用第一个非空行作为键,将其余非空行作为值):

import csv

filename = "SalesHistory.csv"
read_dcts = []
keys = []
with open(filename, 'r') as csvfile:
    reader = csv.reader(csvfile, quotechar='"', skipinitialspace=True)
    for i, row  in enumerate(reader):
        try:
            if len(row) == 0:
                raise IndexError("Row %d is empty. Should skip" % (i + 1))
            if len(keys) == 0:
                keys = [ val.decode('utf-8') for val in row ]
            elif len(row) == len(keys):
                utf_dict = dict(zip(keys, [ val.decode('utf-8') for val in row ]))
                read_dcts.append(utf_dict)
        except (IndexError, AttributeError), e:
            print "Weird line %d found (got %s)" % ((i + 1), e)

# Verify:
for i, dct in enumerate(read_dcts):
    print "Dict %d" % (i + 1)
    for k, v in dct.iteritems():
        print "\t%s: %s" % (k, v)

答案 1 :(得分:0)

一个合理的simlpe函数,用于读取csv文件并生成文件中第一行的键和其他行的值。

import csv

def dict_from_csv(filename):
    '''
    (file)->list of dictionaries
    Function to read a csv file and format it to a list of dictionaries.
    The headers are the keys with all other data becoming values
    '''

    #open the file and read it using csv.reader()
    #read the file. for each row that has content add it to list mf
    #the keys for our user dict are the first content line of the file mf[0]
    #the values to our user dict are the other lines in the file mf[1:]
    mf = []
    with open(filename, 'r') as f:
        my_file = csv.reader(f)
        for row in my_file:
            if any(row):
                mf.append(row)
    file_keys = mf[0]
    file_values = mf[1:]

    #Combine the two lists, turning into a list of dictionaries, using the keys list as the key and the value list as the values
    my_list = []
    for value in file_values:
        my_list.append(dict(zip(file_keys, file_values)))

    #return the list of dictionaries
    return my_list