python更新符合条件的csv单元格

时间:2016-01-31 03:09:04

标签: python csv pandas

我正在设置一个汽车销售网站的预定刮刮器。我有一个csv,其中包含以前格式的广告(大多数列都是为了整洁而省略):

id              year    first scan  last scan   active
OAG-AD-5459832  2005    31/01/2016  31/01/2016  Y
OAG-AD-12013782 2013    31/01/2016  31/01/2016  Y
OAG-AD-10487293 2015    31/01/2016  31/01/2016  Y
OAG-AD-12358252 1972    31/01/2016  31/01/2016  Y
AGC-AD-17247844 2015    31/01/2016  31/01/2016  Y

每个连续的scrape当前都会返回一个dicts列表,如下所示:

[{'body': u'\xa0Coupe','id': u'SSE-AD-3469148', 'odo': u'288', 'adtype': u'Private Seller Car'},
 {'body': u'\xa0Coupe', 'id': u'OAG-AD-12014474', 'odo': u'0', 'adtype': u'Dealer: Demo',}]

我需要处理三个案例:

  • a)如果抓取的广告不在csv中,请将其追加到最后。
  • b)如果 已删除的广告位于csv中且已激活=' Y',更新'最后一次扫描'至 今天的日期
  • c)对于任何有效的=' Y' csv中的广告不在 已删除广告的列表,将更改生效至' N'

我目前的a)代码如下。我不知道如何有效地完成b)和c),而无需为现有广告复制新行。另外 - 我正在使用pandas来打开csv文件,不确定我是否应该继续使用它进行操作或使用dicts。

date = datetime.datetime.now().strftime('%d/%m/%y') #last scan date     
addb = pd.read_csv('pd output.csv') #csv of previously scraped ads
ids = addb['id'].tolist() 
addbdict = addb.to_dict(orient='records')

newads = []
for ad in adscrape:
    ad['last scan'] = date
    ad['active'] = 'Y'
    if ad['id'] not in ids:
        ad['first scan'] = date
        newads.append(ad)

addb2 = addb.append(newads)           
addb2.to_csv('pd output2.csv', index=False)

2 个答案:

答案 0 :(得分:0)

以下是我如何使用Pandas功能实现这一点:

import pandas as pd
import datetime
adscrape = [{'body': u'\xa0Coupe','id': u'SSE-AD-3469148', 'odo': u'288', 'adtype': u'P\
rivate Seller Car'},
            {'body': u'\xa0Coupe', 'id': u'OAG-AD-12014474', 'odo': u'0', 'adtype': u'D\
ealer: Demo',}]

date = datetime.datetime.now().strftime('%d/%m/%Y') #last scan date
addb = pd.read_csv('pd_output.csv') #csv of previously scraped ads
ids = addb['id'].tolist()
addbdict = addb.to_dict(orient='records')

newads = pd.DataFrame(adscrape)

existing = newads['id'].isin(addb['id'])
newads_to_be_appended = newads[~existing]
newads_to_be_appended['first scan'] = date
newads_to_be_appended['last scan'] = date
newads_to_be_appended['active'] = 'Y'
newads_to_be_appended['year'] = 999  # or something
addbplus = pd.concat([addb, newads_to_be_appended])

existing = addbplus['id'].isin(newads['id'])
addbplus.loc[existing,'last scan'] = date

addbplus.loc[~existing,'active'] = 'N'

addbplus.to_csv('pd_output.csv', index=False)

注意existing索引变量:第一次,它用于匹配数据库中的抓取广告(步骤a /)。第二次和第三次,它是另一种方式:它将数据库与刮下的广告相匹配(步骤b /和c /)。如果它让你感到困惑,可以随意重命名变量。

这是熊猫,可能还有其他方式 例如,我可以设想使用addbnewads之间的“外部”联接创建一个大型数据框,并从那里开始工作。

注意:我会避免文件名中的空格。它有效,但更有可能在某些时候导致错误。对这样的数据库文件使用下划线(pd_output.csv或更合适的名称)或破折号(连字符)-来分隔单词。

答案 1 :(得分:0)

不会简单地迭代新广告,将它们添加到您现有的DataFrame工作中吗? 这种做法全部三合一:

    router.get('/orders');
    router.post('/customers');
    router.put('/products');
    router.delete('/employees');

如果addb['active'] = 'N' # Set all ads to inactive addb.set_index('id', inplace=True) for ad in adscrape: fs = addb.loc[ad['id']]['first scan'] if ad['id'] in addb.index else date addb.loc[ad['id']] = pd.Series({'first scan': fs, 'last scan': date, 'active': 'Y'}) 存在,则会更新ad['id']last_scan 如果active不存在,则会创建一个新行(不确定从哪里获取ad['id']信息,因此它将是Year