3.1 文件存储

文件是存储数据的基本载体,对文件的操作几乎是所有编程语言都会涉及的内容。而使用Python进行爬虫操作,进行数据的解析,文件操作也是必不可少的内容。本节就先来学习一下文件的存储。

3.1.1 TXT文件存储

TXT文件即文本文件,是一种简单的文件类型,用户可以将数据写入文本文件中,在使用时直接读取文件内容即可。Python支持将数据写入文本文件中,在需要使用时可以使用特定方法直接读取。下面就来详细介绍在Python中如何将数据写入文本文件中,以及如何读取。

使用Python来读写文件是非常简单的操作。可以调用Python自带的open()函数来打开一个文件,获取到文件句柄,然后通过文件句柄就可以进行各种各样的操作。

open()函数的语法格式如下:

    open(name[, mode[, buffering]])

其中,参数name为指定需要打开的文件的名称;参数mode为打开的方式,根据打开方式的不同可以进行不同的操作;参数buffering用于指定打开文件时是否寄存。如果buffering取值为0,就不会有寄存;如果buffering取值为1,访问文件时就会寄存;如果将buffering的值设为大于1的整数,就表明这是寄存区的缓冲大小;如果buffering取负值,寄存区的缓冲大小就为系统默认值。

Mode(打开方式)的类型及区别如表3-1所示。

表3-1 open()函数打开方式类型表

调用open()函数打开文件之后,还需要以下file对象的方法来配合实现对文件的读取操作:

  • file.read([size]):该方法用于读取文件,若参数size未指定,则返回整个文件,如果文件大小大于2倍内存,就有问题,f.read()读到文件尾时返回""(空字串)。
  • file.readline():该方法用于返回一行。
  • file.readlines([size]):该方法返回包含size行的列表,若size未指定,则返回全部行。
  • for line in f: print line :这是一种访问文件的方法,通过迭代器访问。
  • f.write("hello\n"):该方法用于将指定内容写入文件,如果要写入字符串以外的数据,就先将其转换为字符串。
  • f.tell():该方法返回一个整数,表示当前文件指针的位置(就是到文件头的比特数)。
  • f.seek(偏移量,[起始位置]):该方法用来移动文件指针。偏移量: 单位为比特,可正可负。起始位置为0,表示文件头,默认值;起始位置为1,表示当前位置;起始位置为2,表示文件尾。
  • f.close():该方法用于关闭已经打开的文件。

下面将通过一组实例说明如何调用open()函数及file对象的方法来实现对文件的读取操作。

首先将以下文本内容保存为test.txt。

【示例3-1】读取文件内容

以上代码调用open()函数打开文件,然后调用read()方法读取文件内容,并将文件内容输出,最后关闭文件。将以上代码保存为3-1.py,执行该代码的结果如图3-1所示。

图3-1 读取TXT文件内容

除了读取外,更多的是写入操作,因为使用爬虫时,爬取到的内容更多情况下要保存到文件中,这时就要使用到文件的写操作。

下面的代码将演示如何将指定内容写入文件中。

【示例3-2】将指定内容写入文件中

以上代码首先使用写入方式打开文件,如果文件不存在就会自动创建,然后调用write()方法将指定内容写入文件中,之后使用与3-1.py相同的代码重新打开文件,读取文件中的内容并输出。将以上代码保存为3-2.py,执行该代码的结果如图3-2所示。

图3-2 写入文件

除了调用read()读取文件外,还可以每次将文件按行读取到列表中,然后通过对列表进行遍历将内容输出。下面的代码将演示了如何以遍历方式读取文件内容。

【示例3-3】按行读取文件内容

以上代码在打开文件之后,调用readlines()方法将文件内容按行读取到列表中,然后使用for遍历列表并输出所有内容。将代码保存为3-3.py,执行代码的结果如图3-3所示。

图3-3 按行读取文件并遍历

3.1.2 JSON文件存储

3.1.1小节介绍了如何实现TXT文件的存储,这一小节将介绍如何使用Python语言来编码和解码JSON对象。

JSON(JavaScript Object Notation, JS对象标记)是一种轻量级的数据交换格式。它基于ECMAScript(W3C制定的JavaScript规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON成为理想的数据交换语言。JSON格式易于阅读和编写,同时也易于机器解析和生成,能够有效地提升网络传输效率。

JSON支持的数据格式如下:

  • 对象(字典),使用花括号。
  • 数组(列表),使用方括号。
  • 整型、浮点型、布尔类型,还有null类型。
  • 字符串类型(字符串必须要用双引号引住,不能用单引号)。
  • 多个数据之间使用逗号分开。

注意

JSON本质上就是一个字符串。

字典、列表是Python中的特殊数据类型,字典和列表能够转换为JSON数据。在Python中,要想操作JSON类型文件,可以通过导入JSON库来实现。JSON对象常用的方法有两个:

(1)json.dumps:该方法将Python对象编码成JSON字符串。其语法格式如下:

    json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8",
default=None, sort_keys=False, **kw)

obj为需要进行编码的Python对象;skipkeys用于指定是否跳过关键字;ensure_ascii指定是否编码为ASCII码。

(2)json.loads:该方法将已编码的JSON字符串解码为Python对象。

下面我们将通过一个实例来说明如何将字典、列表转换为JSON数据。

【示例3-4】将字典和列表转换为JSON数据

以上代码调用JSON的dumps()方法将指定的列表(包含字典)数据转化为JSON字符串。因为JSON在转储(Dump)的时候,只能存放ASCII的字符,因此会将中文进行转义,这时我们可以使用ensure_ascii=False关闭这个特性。将以上代码保存为3-4.py,执行该代码的结果如图3-4所示。

图3-4 将字典和列表转换为JSON数据

在Python中,只有基本数据类型才能转换成JSON格式的字符,即int、float、str、list、dict、tuple。

JSON模块中除了dumps函数外,还有一个dump函数,这个函数可以传入一个文件指针,直接将字符串dump到文件中。

【示例3-5】将JSON数据dump到文件中

以上代码调用JSON的dump()方法将指定的列表(包含字典)数据直接转储到了指定文件中,其中第一个参数为需要转储的数据,第二个参数为打开的文件指针。其中调用open()方法打开文件。将以上代码保存为3-5.py,执行该代码将会在当前目录下生成一个a.JSON文件,其内容如图3-5所示。

图3-5 生成的JSON文件内容

前面介绍了如何将Python数据转化为JSON字符串,另外Python也支持逆向操作,即将JSON字符串加载为Python对象,这时只需要调用JSON的loads()方法即可。下面通过实例来说明。

【示例3-6】将JSON数据字符串加载为对象

    import json
    json_str='[{"title": "钢铁是怎样练成的", "price": 9.8}, {"title": "红楼梦",
"price": 9.9}]'
    books=json.loads(json_str,encoding='utf-8')
    print(type(books))
    print(books)

以上代码调用JSON的loads()方法将JSON字符串加载为Python对象,并输出对象的类型及内容。其中,使用encoding参数用于指定加载的编码,这样可以防止出现乱码。将以上代码保存为3-6.py,执行该代码的结果如图3-6所示。

图3-6 将JSON字符串加载为Python对象

Python还支持将文件中包含的JSON数据读取出来,再进行后续操作。调用load()方法打开包含JSON数据的文件指针即可。

在读取前,假设当前目录中有a.JSON文件,其内容如下:

    [{"name": "\u5c0f\u738b", "score": 95}, {"name": "\u5c0f\u660e", "score":
99}, {"name": "\u5c0f\u7ea2", "score": 99}]

【示例3-7】从文件中读取JSON数据

    import json
    with open('a.JSON','r',encoding='utf-8') as fp:
    json_str=json.load(fp)
    print(json_str)

以上代码调用JSON的load()方法从打开的文件中读取JSON数据,并将结果进行输出。在打开文件时需要注意,使用到了encoding参数用于指定加载的编码,这样可以防止出现乱码。将以上代码保存为3-7.py,执行该代码的结果如图3-7所示。

图3-7 从文件中读取JSON数据

3.1.3 CSV文件存储

CSV(Comma-Separated Values,逗号分隔值),有时也称为字符分隔值,因为分隔字符也可以不是逗号。CSV文件是一类文件的简称,它的文件以纯文本形式存储表格数据(数字和文本)。

纯文本意味着该文件是一个字符序列,不包含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔。每条记录由字段组成,字段间的分隔符是其他字符或字符串,常见的是逗号或制表符。通常所有记录都有完全相同的字段序列。通常都是纯文本文件。

Python提供了对CSV文件的支持,这一小节将学习如何使用Python对CSV文件进行读写操作。

对CSV文件进行操作,读取文件内容是基本的操作之一。调用CSV的reader()方法即可实现对CSV文件的读取操作。

在开始编写具体代码前,先在当前目录下建立data.csv文件,其内容如下:

    name,price,author
    三国演义,48,罗贯中
    红楼梦,50,曹雪芹
    西游记,45,吴承恩
    三体,20,刘慈欣

把以上代码保存为data.csv文件备用。

【示例3-8】读取CSV文件

    import csv
    with open('data.csv','r') as fp:
    reader=csv.reader(fp)
    titles=next(reader)
    for x in reader:
        print(x)

以上代码这样操作,以后获取数据的时候,就要通过下标来获取数据。将以上代码保存为3-8.py,执行代码的结果如图3-8所示。

图3-8 读取CSV文件

如果想要在获取数据的时候通过标题来获取,那么可以调用DictReader方法。

【示例3-9】读取CSV文件II

    import csv
    with open('data.csv','r') as fp:
    reader=csv.DictReader(fp)
    titles=next(reader)
    for x in reader:
        print(x['author'],end="\t")
        print(x['name'],end="\t")
        print(x['price'])

以上代码调用DictReader()方法进行读取,之后就可以使用标题方式来获取内容,这里的标题即为首列的标题。将以上代码保存为3-9.py,执行代码的结果如图3-9所示。

图3-9 通过标题来获取CSV文件数据

由于代码3-9.py是用标题形式来读取CSV文件的,因此可以自己决定先显示哪一列。同时也不再以列表形式输出。

写入数据到CSV文件需要创建一个writer对象,主要用到两个方法:一个是writerow(),用于写入一行;另一个是writerows(),用于写入多行。下面分别演示单行写入与多行写入。

【示例3-10】写入CSV文件

    import csv
    headers = ['name','price','author']
    values = [
        ('流浪地球',18,'刘慈欣'),
        ('梦的解析',30,'弗洛伊德'),
        ('时间简史',35,'斯蒂芬·威廉·霍金')
    ]
    with open('book.csv','w',encoding='utf-8',newline='') as fp:
        writer=csv.writer(fp)
        writer.writerow(headers)
        writer.writerows(values)

将以上代码保存为3-10.py,执行代码将会在当前目录生成一个名为book.csv的文件,其内容如图3-10所示。

图3-10 生成的book.csv的内容

除了按行写入CSV文件之外,也可以使用字典的方式写入数据。这时就需要调用DictWriter方法了。

【示例3-11】以字典方式写入CSV文件

    import csv
    headers = ['name','price','author']
    values = [
        {"name":'流浪地球',"price":18,"author":'刘慈欣'},
        {"name":'梦的解析',"price":30,"author":'弗洛伊德'},
        {"name":'时间简史',"price":35,"author":'斯蒂芬·威廉·霍金'}
    ]
    with open('book2.csv','w',newline='') as fp:
        writer=csv.DictWriter(fp,headers)
        writer.writerow({"name":'三体',"price":20,"author":'刘慈欣'})
        writer.writerows(values)

以上代码定义了一组字典列表,然后调用CSV的DictWriter()方法初始化对象,最后调用writerow()方法将字典内容写入CSV文件中。将以上代码保存为3-11.py,执行代码将会在当前目录生成一个名为book2.csv的文件,其内容如图3-11所示。

图3-11 生成的book2.csv的内容

下面将综合前面的内容做一个小练习,自定义一组函数实现对CSV文件的综合操作。

【示例3-12】自定义函数综合处理CSV文件

以上代码综合了对CSV文件的读写操作,并将它们整合到函数中,在实际应用中,用户可以根据自己的需要对系统已有的内容进行扩充,甚至可以自己创建类与模块,以实现复杂的要求。将以上代码保存为3-12.py,执行该代码,将会在当前目录下创建名为classroom2.csv的文件,其内容如图3-12所示。

图3-12 练习对CSV文件的操作