今天我们来了解一下在数据分析领域最为常见一种文件格式:CSV 文件,然后我们再将上一篇文章案例中抓取到的数据保存到 CSV 文件中。

1、什么是CSV文件?

CSV(Comma-Separated Values) 是一种使用逗号分隔来实现存储表格数据的文本文件。

我们都知道表格有多种形式的存储,比如 Excel 的格式或者数据库的格式。CSV 文件也可以存储表格数据,并且能够被多种软件兼容,比如 Excel 就能直接打开 CSV 文件的表格,很多数据库软件也支持导入 CSV 文件。除了兼容性好之外,CSV 格式还是所有能存储表格的格式中最简单的一种。

比如我们新建一个文件,名称改为:info.csv,在文件中输入以下数据:

姓名,年龄,籍贯,部门

小明,22,河北,IT部

小亮,25,广东,IT部

小E,23,四川,财务部

保存成功后,我们使用excel打开这个csv文件,可以看到:

python csv 写入设置编码 python写入csv指定列_CSV


打开后的展示样式与excel基本一样,在这里,我们需要注意csv文件的一些事项:

  • 表格中的一行,对应 CSV 文件中的一行;
  • 一行中不同单元格的内容,在 CSV 文件中用逗号分隔;
  • 务必保证每行的逗号数量是一致的(对应表格中每行的单元格一致)。

在了解csv的格式后,下面我们再来看一下Python中关于csv的模块。

2、Python中的csv模块

了解了 CSV 文件的基本概念,今天我们来看如何使用 Python 来操作 CSV 文件。因为对于数据分析场景而言,最常见的操作就是读取和写入。

(1)从csv文件中读取内容

现在我们来读取上面的info.csv文件内容。

现在VS CODE 中新建一个cell,导入csv模块

import csv

要读取 CSV 文件,我们需要用到 CSV 模块中的 DictReader 类,DictReader 可以将每一行以字典的形式读出来,key 就是表头,value 就是对应单元格的内容。代码如下:

# 通过 open 函数打开 info.csv ,并将文件对象保存在 fo 中

fo = open("info.csv ")

# 通过打开 CSV 文件的文件对象作为参数来创建 DictReader 类的对象,存在 reader 变量中

reader = CSV.DictReader(fo)

# 调用 reader 对象的 fieldnames 属性,获取 CSV 文件中表格的表头

headers = reader.fieldnames

# 关闭文件

fo.close()

# 打印表头的信息

print(headers)

输出如下:

['姓名', '年龄', '籍贯', '部门']

接下来,我们尝试获取表格的实际内容。

# 打开 info.csv 

fo = open("info.csv ")

# 创建 DictReader 对象

reader = CSV.DictReader(fo)

# 创建列表,用于存储读到的行

row_list = []

# 使用遍历循环,直接对 reader 对象进行遍历

# 每次执行循环时,row 变量都存储了当前行的内容

for row in reader:

    # 直接将 row 变量添加到行列表中

    row_list.append(row)

# 关闭文件

fo.close()

# 打印第一行的表格数据

print(row_list[0])

打印的结果显示:

{'姓名': '小明', '年龄': '22', '籍贯': '河北', '部门': 'IT部'}

可以看到,我们拿到了第一行的内容,并且是以字典的形式,字典把每个单元格的内容和表头联系了起来,表头是 key,而具体内容就是 value。每行都是这样的一个字典,所有字典都存储在 row_list 列表中。

接下来,我们来演示对于 row_list 列表的常见操作:打印某一行、某一列的值。

print("打印年龄一列的内容:")

# 遍历循环 row_list,d 为循环变量 

for d in row_list:

    # 因为 d 是字典,直接打印 key 为 年龄的值即可。

    print(d["年龄"])

# 打印一个换行

print("")

print("打印第三行的内容:")

d = row_list[2]

print("姓名:", d["姓名"])

print("年龄:",d["年龄"])

print("籍贯:",d["籍贯"])

print("部门:",d["部门"])

输出如下:

打印年龄一列的内容

22

25

23

打印第三行的内容

姓名: 小E

年龄: 23

籍贯: 四川

部门: 财务部

(2)写入csv文件

与读取类似,Python 的 CSV 模块提供了 DictWriter 方法,使得我们可以将表格数据以字典的形式存在到 CSV 文件中。

具体用法如下:

# 打开一个文件,假设是 info2.CSV,因为是写入,所以需要指定模式 "w"

# newline='',在写入 CSV 时,需要指定这个参数,这个记住即可。

fo = open("info2.CSV", "w", newline='')

# 将表头存储在一个列表中

header = ["姓名", "年龄", "籍贯", "部门"]

# 创建一个 DictWriter 对象,第二个参数就是上面创建的表头

writer = CSV.DictWriter(fo, header)

# 写入表头

writer.writeheader()

# 写入一行记录,以字典的形式,key 需要和表头对应。

writer.writerow({"姓名": "小刚", "年龄":"28", "籍贯":"福建", "部门":"行政部"})

# 关闭写入的文件

fo.close()

上述代码的关键点就在于,创建了 DictWriter 后,需要首先调用 writeheader 来写入表头,然后再调用 writerow 来写入行。

执行上述代码之后,并不会有内容输出,但是 源代码文件夹下会多出一个 Info2.csv, 用Excel 打开后,如下图所示。

python csv 写入设置编码 python写入csv指定列_python_02


可以看到,我们的表头和记录已经成功写入 CSV 文件中。

DictWriter 除了提供 writerow 方法来将单个字典保存为 CSV 表格中的一行,还提供了 writerows 方法来一次性地保存多行的内容。

现在我们尝试使用 writerow 方法来一次性写入多条记录。将我们手工建的 CSV 表格的内容存储在 row_list 变量中的数据一起写入新文件中。代码如下:

# 新打开一个 info3.CSV 文件

fo = open("info3.CSV", "w", newline='')

# 将表头存储在一个列表中

header = ["姓名", "年龄", "籍贯", "部门"]

# 创建一个 DictWriter 对象,第二个参数就是上面创建的表头

writer = CSV.DictWriter(fo, header)

# 将小刚的记录插入到row_list 中

row_list.append({"姓名": "小刚", "年龄":"28", "籍贯":"福建", "部门":"行政部"})

# 写表头

writer.writeheader()

# 调用 writerows 方法,一次性写多个字典(一个字典列表)到 CSV 文件中

writer.writerows(row_list)

# 关闭文件

fo.close()

执行完毕后,源代码文件夹下生成了新的 info3.csv,打开后如下图所示,包含了一开始的三条记录,以及我们插入的“小刚”的记录。

python csv 写入设置编码 python写入csv指定列_python_03

3、实现新闻标题保存到csv中

接下来,我们来将上一讲中过滤出来的新闻列表写入 CSV 文件中。

(1)数据准备

我们将前面下载的jandan.html文件复制到本源码文件夹下,再将之前获取新闻标题的代码整理成几个函数,方便调用。

①创建 BeautifulSoup 对象的函数。

from bs4 import BeautifulSoup

# 输入参数为要分析的 html 文件名,返回值为对应的 BeautifulSoup 对象

def create_doc_from_filename(filename):

    fo = open(filename, "r", encoding='utf-8')

    html_content = fo.read()

    fo.close()

    doc = BeautifulSoup(html_content)

    return doc

②实现定位包含新闻的 div 元素的列表函数。

# 输入参数是 BeautifulSoup 对象,返回包含新闻的 div 元素列表

def find_index_labels(doc):

    index_labels = doc.find_all("div", class_="indexs")

    return index_labels

③实现新闻标题的抽取函数。

# 从第一次 find_all 获取的标签对象中抽取标题

def get_title(label_object):

    # 从刚才的参数传入的标签对象中过滤出所有 target=_blank 的 a 标签

    a_labels = label_object.find_all("a",target="_blank")

    # 取第一个标签对象

    my_label = a_labels[0]

    # 将标签的文字内容作为返回值返回

    return my_label.get_text()

④实现获取新闻发布时间的函数

# 和 get_title 函数一样,传入 label_object, 返回发布时间

def get_pub_time(label_object):

    # 找到 class=comment-link 的 span 标签

    spans = label_object.find_all("span", class_="comment-link")

    # 取第一个

    span = spans[0]

    # 返回标题属性

    return span["title"]

至此,我们四个基础函数已经准备好了,以上的 Cell 都需要注意执行,这样我们接下来才可以使用这些函数。

(2)获取文章标题

接下来,我们开始使用上面的函数来获得新闻的标题与新闻列表。

# 调用 create_doc_from_filename 函数,创建 BeautifulSoup 对象

doc = create_doc_from_filename("jiandan.html")

# 调用find_index_labels 函数,传入 BeautifulSoup 对象

# 将返回的 div 列表存储在 index_labels 中

index_labels = find_index_labels(doc)

# 使用遍历循环遍历 index_labels 列表,循环变量为 label_object

for label_object in index_labels:

    # 调用 get_title, 传入当前处理的 div 元素对象,获取标题

    title = get_title(label_object)

    # 调用 get_pub_time,传入当前处理的 div 元素对象,获取发布时间

    pub_time = get_pub_time(label_object)

    # 将标题和发布时间打印出来

    print("标题:", title)

    print("发布时间:", pub_time)

上述代码把我们刚才准备的四个函数都串了起来。大概的思路就是首先创建 BeautifulSoup 对象,之后针对该对象查询 class = indexs 的列表,然后使用遍历循环遍历该列表,对于每一个 div 元素,分别调用 get_title 以及 get_pub_time 函数来获得标题与发布时间。

执行上述代码后,输出如下所示。可以看到,我们的新闻标题和时间都已经被成功打印了出来。

标题: 引发普通感冒的鼻病毒会将新冠病毒排挤出细胞!

发布时间: 1小时 ago

标题: 无厘头研究:植入虚假的记忆再抹去它们

发布时间: 4小时 ago

标题: 什么是仇恨犯罪?

发布时间: 8小时 ago

标题: 突发:LHCb发现了违背标准模型的现象

发布时间: 12小时 ago

标题: 今日带货 20210324

发布时间: 14小时 ago

标题: 舌战裸猿:IBM搞出了可以打辩论赛的AI

发布时间: 23小时 ago

标题: 大吐槽:「我没醉,醉的是世界」

发布时间: 1天 ago

标题: 今年世界总发电量的0.6%被用于挖比特币

发布时间: 1天 ago

标题: 接种疫苗后还是感染新冠?不要为此惊讶

发布时间: 1天 ago

标题: 今日带货:蛋友家的血橙

发布时间: 2天 ago

标题: 科学家首次在野外检测到抗多药的超级真菌

发布时间: 2天 ago

标题: 未在iPhone12盒中搭配充电器,苹果被巴西消协罚200万美元

发布时间: 2天 ago

标题: 工程师将解决城市陷坑的问题

发布时间: 2天 ago

标题: 今日带货:粉面专场

发布时间: 3天 ago

标题: 科学家在碟子里培育出了泪腺,并让它哭泣

发布时间: 3天 ago

标题: 疯狂实验进行时:把志愿者禁闭在黑暗的空间里40天

发布时间: 3天 ago

标题: 今日带货 20210321

发布时间: 4天 ago

标题: 我们已向外星人发送了哪些消息?

发布时间: 4天 ago

标题: 脑力小体操:石头+剪刀 VS 石头+布

发布时间: 4天 ago

标题: 发霉啦:今天,我终于向母亲摊牌了

发布时间: 5天 ago

标题: 普渡大学的经济学家计算出世界各地幸福的价格

发布时间: 5天 ago

标题: 人类首次观察到木星上极光黎明风暴的成形过程

发布时间: 5天 ago

标题: 为女儿出头,母亲编辑假裸照败坏高中啦啦队队员的名誉

发布时间: 5天 ago

标题: 今日带货:淘宝京东蛋友推荐

发布时间: 6天 ago

(3)将数据存储为字典形式

要存储到 CSV,首先我们需要将我们的数据创建为字典的形式,我们可以在(2)的循环中将标题和时间存储为字典,然后使用一个字典列表来存储每个新闻对应的字典。最后直接使用 DictWriter 的 writerows 方法来将字典列表写入 CSV 文件即可。

我们直接修改刚才打印标题和发布时间的 Cell,删除原本的打印代码,并添加字典相关操作的代码。

# 调用 create_doc_from_filename 函数,创建 BeautifulSoup 对象

doc = create_doc_from_filename("jiandan.html")

# 调用find_index_labels 函数,传入 BeautifulSoup 对象

# 将返回的 div 列表存储在 index_labels 中

index_labels = find_index_labels(doc)

# 【新增代码】存储新闻的字典列表

news_dict_list = []

# 使用遍历循环遍历 index_labels 列表,循环变量为 label_object

for label_object in index_labels:

    # 调用 get_title, 传入当前处理的 div 元素对象,获取标题

    title = get_title(label_object)

    # 调用 get_pub_time,传入当前处理的 div 元素对象,获取发布时间

    pub_time = get_pub_time(label_object)

    # 【新增代码】创建单条新闻的字典

    news = {"标题": title, "发布时间": pub_time}

    # 【新增代码】将新闻字典添加到字典列表

    news_dict_list.append(news)

# 【新增代码】打印出字典列表

print(news_dict_list)

通过循环,我们将新闻以字典的形式逐个添加到了字典列表中,然后在最后打印出列表,输出如下所示。

[{'标题': '引发普通感冒的鼻病毒会将新冠病毒排挤出细胞!', '发布时间': '1小时 ago'}, {'标题': '无厘头研究:植入虚假的记忆再抹去它们', '发布时间': '4小时 ago'}, {'标题': '什么是仇恨犯罪?', '发布时间': '8小时 ago'}, {'标题': '突发:LHCb发现了违背标准模型的现象', '发布时间': '12小时 ago'}, {'标题': '今日带货 20210324', '发布时间': '14小时 ago'}, {'标题': '舌战裸猿:IBM搞出了可以打辩论赛的AI', '发布时间': '23小时 ago'}, {'标题': '大吐槽:「我没醉,醉的是世界」', '发布时间': '1天 ago'}, {'标题': '今年世界总发电量的0.6%被用于挖比特币', '发布时间': '1天 ago'}, {'标题': '接种疫苗后还是感染新冠?不要为此惊讶', '发布时间': '1天 ago'}, {'标题': '今日带货:蛋友家的血橙', '发布时间': '2天 ago'}, {'标题': '科学家首次在野外检测到抗多药的超级真菌', '发布时间': '2天 ago'}, {'标题': '未在iPhone12盒中搭配充电器,苹果被巴西消协罚200万美元', '发布时间': '2天 ago'}, {'标题': '工程师将解决城市陷坑的问题', '发布时间': '2天 ago'}, {'标题': '今日带货:粉面专场', '发布时间': '3天 ago'}, {'标题': '科学家在碟子里培育出了泪腺,并让它哭泣', '发布时间': '3天 ago'}, {'标题': '疯狂实验进行时:把志愿者禁闭在黑暗的空间里40天', '发布时间': '3天 ago'}, {'标题': '今日带货 20210321', '发布时间': '4天 ago'}, {'标题': '我们已向外星人发送了哪些消息?', '发布时间': '4天 ago'}, {'标题': '脑力小体操:石头+剪刀 VS 石头+布', '发布时间': '4天 ago'}, {'标题': '发霉啦:今天,我终于向母亲摊牌了', '发布时间': '5天 ago'}, {'标题': '普渡大学的经济学家计算出世界各地幸福的价格', '发布时间': '5天 ago'}, {'标题': '人类首次观察到木星上极光黎明风暴的成形过程', '发布时间': '5天 ago'}, {'标题': '为女儿出头,母亲编辑假裸照败坏高中啦啦队队员的名誉', '发布时间': '5天 ago'}, {'标题': '今日带货:淘宝京东蛋友推荐', '发布时间': '6天 ago'}]

(4)存储到csv文件中

现在,我们已经将网页中抓取到的数据都保存在一个字典列表中:news_dict_list ,接下来就是将这个列表写入到 CSV 文件中即可。
代码如下:

# 创建 news.CSV 文件

fo = open("news.CSV", "w", newline='', encoding='utf_8_sig')

# 这一次的表头

header = ["标题", "发布时间"]

# 使用文件对象和表头初始化 DictWriter 对象

writer = CSV.DictWriter(fo, header)

# 写入表头

writer.writeheader()

# 将上一步计算的字典列表写入 CSV 文件中

writer.writerows(news_dict_list)

# 关闭文件对象

fo.close()

执行之后,在源代码文件夹下会生成 news.CSV 文件,用 Excel 打开后如下图所示。可以看到,我们的数据已经成功以表格的形式呈现了。

python csv 写入设置编码 python写入csv指定列_Python读取文件内容_04