Python:如何在namedtuple中存储和检索动态数据以写入CSV?我应该只使用对象属性吗?

时间:2018-08-03 16:50:16

标签: python csv selenium namedtuple

目标是从网页上为每张发票编写csv文件。我正在尝试使用网络爬虫来完成此任务,主要是使用硒

每个发票都有自己的编号,日期,截止日期,金额和记录列表

发票中的每个记录都有自己的编号,描述,存储,重量,价格和数量

我能够将所需的所有数据成功打印到控制台。像这样:

Going to: https://thewebsite/thing/my_account.whatever?is=checkout#invoices/429807/paid-invoices
Extracting...
------------------------------
ID: 30795 Description: YOGURT, BLUEBERRY, LOW FAT, DANNON
Storage:  35 Degree Cooler Weight:  110 Price:  $0.00 Quantity:  22
------------------------------
ID: 86546 Description: SWEET POTATOES, P/L
Storage:  55 Degree Cooler Weight:  240 Price:  $0.00 Quantity:  6
------------------------------
ID: 36446 Description: PINEAPPLE, FRESH, P/L
Storage:  55 Degree Cooler Weight:  560 Price:  $0.00 Quantity:  20

我是用这些做的:

class myRecord(object):
    id = ""
    description = ""
    storage = ""
    weight = ""
    price = ""
    quantity = ""

    def _init_(self, id, description, storage, weight, price, quantity):
        self.id = id
        self.description = description
        self.storage = storage
        self.weight = weight
        self.price = price
        self.quantity = quantity    

class myInvoice(object):
    number = ""
    date = ""
    close_date = ""
    amount = ""

    def _init_(self, number, date, close_date, amount, formatted_records_list = None):
        self.number = number
        self.date = date
        self.close_date = close_date
        self.amount = amount
        if formatted_records_list is None:
            self.formatted_records_list = []
        else:
            self.formatted_records_list = formatted_records_list

我从html元素中为每个属性分配了值(我将仅以“ number”属性为例)

invoice_number_list = []
invoice_number_list = browser.find_elements_by_class_name("tranid") 
i = 0
for invoice_link in invoice_link_list:     #invoice links are basically urls to each invoice
    invoice = myInvoice()         
    invoice.number = invoice_number_list[i].get_attribute('innerHTML')         
    i += 1

根据我在网上看到的内容,如何用我使用的对象制作一个csv文件并不是很明显

我发现了这个:Writing list of objects to csv file

那个家伙基本上说我应该使用namedtuple,据我了解,namedtuple就像是在预算上精简的对象。有了这些,我(应该)可以更轻松地制作csv文件。所以我做了这个:

Record = namedtuple('Record', ['id', 'description', 'storage', 'weight', 'price', 'quantity'])
Invoice = namedtuple('Invoice', ['number', 'date', 'close_date', 'amount', 'Record_list'])

警钟已经响起。我可以将namedtuples列表作为namedtuple的属性吗?每张发票我需要一个csv文件。每张发票只有一个数字,日期,截止日期和金额。但是,它可以有大量的记录。我的思考过程告诉我,我需要在每个发票上附加一个记录列表。

我尝试将值分配给一个命名元组且有问题的发票。

Invoice_number_list = []
invoice_number_list = browser.find_elements_by_class_name("tranid") 
i = 0
for Invoice_link in Invoice_link_list:
            #Invoice.number = Invoice_number_list[i].get_attribute('innerHTML') #doesn't work
            Invoice_list.extend(Invoice._make((Invoice_number_list[i].get_attribute('innerHTML'), None, None, None, None)))  
            i +=0

日期,结束日期和金额的其他发票值进入索引[1],[2]和[3]。我将[4]保留为“无”,因为这是发票记录列表所在的位置。

“ extend()”最终使我的发票清单变成一个字符串,这看起来对制作字典可能很有用(如果我很难制作一个csv,我可能需要它-我认为使用正确的namedtuple这几乎就像说“将数据写入csv”一样简单),但是我需要能够将记录列表附加到每个单独的发票上-我不能使用字符串来做到这一点。

以下是我认为我的选择:

  • 将发票设为常规对象,将Record设为常规对象->将其中的csv设为
  • 将发票命名为一个元组并记录一个命名元组->从其中创建csv
  • 将一个命名为元组,另一个作为常规对象->将其中的csv制成

目前,对我来说,没有什么是显而易见的。

TL; DR:我正在尝试找出如何从数据写入csv文件的方法。我应该坚持尝试使用namedtuples来制作csvs,还是尝试找出如何使用对象属性来实现?我该怎么办?

1 个答案:

答案 0 :(得分:0)

我认为这里最直接的解决方案之一是为to_dict类实现类似get_csv_fieldsmyInvoice的方法,然后使用内置的{{1} }。

当然,如果您使用的是Python 3.6和更高版本,data classes的实现方法要优雅得多,但是想法仍然相同。

csv.DictWriter

然后您可以将对象写入csv,如下所示:

class myInvoice(object):
    number = ""
    date = ""
    close_date = ""
    amount = ""
    def __init__(self, number, date, close_date, amount, formatted_records_list = None):
        self.number = number
        self.date = date
        self.close_date = close_date
        self.amount = amount
        if formatted_records_list is None:
            self.formatted_records_list = []
        else:
            self.formatted_records_list = formatted_records_list

    @staticmethod
    def get_csv_fields():
        return ['number', 'date', 'close_date', 'amount', 'formatted_records_list']

    def to_dict(self):
        return {el: getattr(self, el) for el in self.get_csv_fields()}