0

我有一个生成 CSV(从网站解析的数据)的 Python 脚本。以下是 CSV 文件的示例:

文件 1.csv

China;Beijing;Auralog Software Development (Deijing) Co. Ltd.;;;
United Kingdom;Oxford;Azad University (Ir) In Oxford Ltd;;;
Italy;Bari;Bari, The British School;;Yes;
China;Beijing;Beijing Foreign Enterprise Service Group Co Ltd;;;
China;Beijing;Beijing Ying Biao Human Resources Development Limited;;Yes;
China;Beijing;BeiwaiOnline BFSU;;;
Italy;Curno;Bergamo, Anderson House;;Yes;

文件2.csv

China;Beijing;Auralog Software Development (Deijing) Co. Ltd.;;;
United Kingdom;Oxford;Azad University (Ir) In Oxford Ltd;;;
Italy;Bari;Bari, The British School;;Yes;
China;Beijing;Beijing Foreign Enterprise Service Group Co Ltd;;;
China;Beijing;Beijing Ying Biao Human Resources Development Limited;;Yes;
This;Is;A;New;Line;;
Italy;Curno;Bergamo, Anderson House;;Yes;

如你看到的,

中国;北京;北外在线 北外;;; ==> File1.csv 中的这一行不再出现在 File2.csv 和This;Is;A;New;Line;; ==> File2.csv 中的这一行是新的(在 File1.csv 中不存在)。

我正在寻找一种方法来比较这两个 CSV 文件(要知道的重要一点是行的顺序不重要......它们不能在任何地方)。

我想要的是一个可以告诉我的脚本: - 一个新行:This;Is;A;New;Line;; - 删除一条线:中国;北京;北外在线;;; 等等 ... !

我试过但没有任何成功:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import csv

f1 = file('now.csv', 'r')
f2 = file('past.csv', 'r')

c1 = csv.reader(f1)
c2 = csv.reader(f2)

now = [row for row in c2]
past = [row for row in c1]

for row in now:
    #print row
    lol = past.index(row)
    print lol

f1.close()
f2.close()

_csv.Error: new-line character seen in unquoted field - do you need to open the file in universal-newline mode?

知道最好的方法吗?非常感谢你;)

编辑:

import csv

f1 = file('now.csv', 'r')
f2 = file('past.csv', 'r')

c1 = csv.reader(f1)
c2 = csv.reader(f2)

s1 = set(c1)
s2 = set(c2)

lol = s1 - s2
print type(lol)
print lol

这似乎是个好主意,但是:

Traceback (most recent call last):
  File "compare.py", line 20, in <module>
    s1 = set(c1)
TypeError: unhashable type: 'list'

编辑2(请不要关心上面的内容): *在您的帮助下,这是我正在编写的脚本: *

#!/usr/bin/python
# -*- coding: utf-8 -*-
import os
import csv


### COMPARISON THING ###
x=0

fichiers = os.listdir('/me/CSV')
for fichier in fichiers:
    if '.csv' in fichier:
        print('%s -----> %s' % (x,fichier))
        x=x+1

choice = raw_input("Which file do you want to compare with the new output ? ->>>")
past_file = fichiers[int(choice)]
print 'We gonna compare %s to our output' % past_file

s_now = frozenset(tuple(row) for row in csv.reader(open('/me/CSV/now.csv', 'r'), delimiter=';')) ## OUR OUTPUT
s_past = frozenset(tuple(row) for row in csv.reader(open('/me/CSV/'+past_file, 'r'), delimiter=';')) ## CHOOSEN ONE

added = [";".join(row) for row in s_now - s_past]  # in "now" but not in "past"
removed = [";".join(row) for row in s_past - s_now]  # in "past" but not in "now"

c = csv.writer(open("CHANGELOG.csv", "a"),delimiter=";" )
line = ['AD']
for item_added in added:
    line.append(item_added)
    c.writerow(['AD',item_added])

line = ['RM']
for item_removed in removed:
    line.append(item_removed)
    c.writerow(line)

两种错误:

  File "programcompare.py", line 21, in <genexpr>
    s_past = frozenset(tuple(row) for row in csv.reader(open('/me/CSV/'+past_file, 'r'), delimiter=';')) ## CHOOSEN ONE
_csv.Error: line contains NULL byte

或者

  File "programcompare.py", line 21, in <genexpr>
    s_past = frozenset(tuple(row) for row in csv.reader(open('/me/CSV/'+past_file, 'r'), delimiter=';')) ## CHOOSEN ONE
_csv.Error: newline inside string

几分钟前它还在工作,但我已经更改了 CSV 文件以使用不同的数据进行测试,我在这里:-)

对不起,最后一个问题!

4

2 回答 2

7

如果您的数据不是太大,将它们加载到集合(或 freezeset)中将是一种简单的方法:

s_now = frozenset(tuple(row) for row in csv.reader(open('now.csv', 'r'), delimiter=';'))
s_past = frozenset(tuple(row) for row in csv.reader(open('past.csv', 'r'), delimiter=';'))

要获取已添加的条目列表:

added = [";".join(row) for row in s_now - s_past]  # in "now" but not in "past"
# Or, simply "added = list(s_now - s_past)" to keep them as tuples.

同样,被删除的条目列表:

removed = [";".join(row) for row in s_past - s_now]  # in "past" but not in "now"

为了解决您为什么会看到的更新问题,csv在迭代时TypeError: unhashable type: 'list'将每个条目作为 a 返回。不可散列,因此不能插入到.listlistsset

为了解决这个问题,您需要在将条目添加到集合之前将list条目转换为s。tuple有关如何完成此操作的示例,请参阅我的答案中的上一部分。


为了解决您看到的其他错误,它们都是由 CSV 文件的内容引起的。

_csv.Error:字符串内的换行符

看起来您"在数据中的某处有引号字符 (),这会使解析器感到困惑。我对 CSV 模块不够熟悉,无法准确地告诉您出了什么问题,无论如何都不能不看一下您的数据。

但是,我确实设法重现了这样的错误:

>>> [e for e in csv.reader(['hello;wo;"rld'], delimiter=";")]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
_csv.Error: newline inside string

在这种情况下,可以通过指示读者不要对引号进行任何特殊处理来修复它(参见csv.QUOTE_NONE)。(请注意,这将禁用引用数据的处理,从而分隔符可以出现在带引号的字符串中,而不会将字符串拆分为单独的条目。)

>>> [e for e in csv.reader(['hello;wo;"rld'], delimiter=";", quoting=csv.QUOTE_NONE)]
[['hello', 'wo', '"rld']]

_csv.Error:行包含 NULL 字节

我猜这可能取决于您的 CSV 文件的编码。请参阅以下问题:

于 2012-05-23T15:35:48.363 回答
2

将 csv 文件逐行读取到集合中。比较集合。

>>> s1 = set('''China;Beijing;Auralog Software Development (Deijing) Co. Ltd.;;;
... United Kingdom;Oxford;Azad University (Ir) In Oxford Ltd;;;
... Italy;Bari;Bari, The British School;;Yes;
... China;Beijing;Beijing Foreign Enterprise Service Group Co Ltd;;;
... China;Beijing;Beijing Ying Biao Human Resources Development Limited;;Yes;
... China;Beijing;BeiwaiOnline BFSU;;;
... Italy;Curno;Bergamo, Anderson House;;Yes;'''.split('\n'))
>>> s2 = set('''China;Beijing;Auralog Software Development (Deijing) Co. Ltd.;;;
... United Kingdom;Oxford;Azad University (Ir) In Oxford Ltd;;;
... Italy;Bari;Bari, The British School;;Yes;
... China;Beijing;Beijing Foreign Enterprise Service Group Co Ltd;;;
... China;Beijing;Beijing Ying Biao Human Resources Development Limited;;Yes;
... This;Is;A;New;Line;;
... Italy;Curno;Bergamo, Anderson House;;Yes;'''.split('\n'))
>>> s1 - s2
set(['China;Beijing;BeiwaiOnline BFSU;;;'])
>>> s2 - s1
set(['This;Is;A;New;Line;;'])
于 2012-05-23T15:28:00.757 回答