Class 15 - 1 数据存储——文件存储

保存的形式可以多种多样,最简单的形式是 接保存为文本文件,如 TXT、JSON、CSV等。还可以保存到数据库中,如关系型数据库 MySQL ,非关系型数据库 MongoDB、Redis等。

一、TXT文本存储 

  1. 基本实例:
    • 可以用 requests 将网页源代码获取下来,然后使用 pyquery 解析库解析,接下来将提取的标题、 回答者、 回答保存到文本,代码:

      import requests
      from pyquery import PyQuery as pq
      url = 'https://www.zhihu.com/explore'
      headers = {
          'User-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
      }
      html = requests.get(url,headers =headers).text
      doc = pq(html)
      items = doc('.explore-tab .feed-item').items()
      for item in items:
          question = item.find('h2').text()
          author = item.find('.author-link-line').text()
          answers = pq(item.find('.content').html()).text()
          file = open('explore.txt', 'a', encoding='utf-8')
          file.write('\n'.join([question, author, answers]))
          file.write('\n'+'='*50+'\n')
          file.close()

      用 requests 提取知乎的"发现"页面,然后将热门话题的问题、回答者、答案全文提取出来,然后利用 Python 提供的open()方法打开一个文本文件,获取一个文件操作对象,这里赋值为 file,接着利用 file 对 象的 write()方法将提取的内容写入文件,最后调用 ιlose()方法将其关闭,这样抓取的内容即可成功 写入文本中了。

  2. 打开方式
    • open()方法的第二个参数设置成了 a,这样在每次写入文本时不会清空源文件, 而是在文件末尾写入新的内容,这是一种文件打开方式。 

      • r:以只读方式打开文件。 文件的指针将会放在文件的开头。 这是默认模式。

      • rb:以二进制只读方式打开一个文件。 文件指针将会放在文件的开头。
      • r+:以读写方式打开一个文件, 文件指针将会放在文件的开头。 
      • rb+:以二进制读写方式打开一个文件。 文件指针将会放在文件的开头。
      • w:以写入方式打开一个文件。 如果该文件已存在,则将其覆盖。 如果该文件不存在,则创建新文件。 
      • wb:以二进制写入方式打开一个文件。 如果该文件已存在,则将其覆盖。 如果该文件不存 在, 则创建新文件
      • w+:以读写方式打开一个文件。 如果该文件已存在,则将其覆盖。 如果该文件不存在,则创 建新文件
      • wb+:以二进制读写格式打开一个文件。 如果该文件已存在, 则将其覆盖。 如果该文件不存 在, 则创建新文件。
      • a: 以追加方式打开一个文件。 如果该文件已存在,文件指针将会放在文件结尾, 如果该文件不存在, 则创建新文件来写入。
      • ab:以二进制追加方式打开一个文件。 如果该文件已存在,则文件指针将会放在文件结尾,如果该文件不存在,则创建新文件来写入
      • a+:以读写方式打开一个文件。 如果该文件已存在,文件指针将会放在文件的结尾。 文件打 开时会是追加模式。 如果文件不存在,则创建新文件来读写。
      • ab+:以二进制追加方式打开一个文件。 如果该文件已存在,则文件指针将会放在文件结尾。 如果该文件不存在,则创建新文件用于读写
  3. 简化写法
    • 使用 with as 语法。在 with 控制块结束时,文件会自动关闭,不需要再调用 close()方法。示例:
        with open('explore.txt', 'a', encoding='utf-8') as file:
              file.write('\n'.jason([question,author,answers]))
              file.write('\n'+'='*50+'\n')

       如果想保存时将原文清空,那么可以将第二个参数改写为 w,示例:

         with open('explore.txt', 'w', encoding='utf-8') as file:
              file.write('\n'.jason([question,author,answers]))
              file.write('\n'+'='*50+'\n')

二、Json文件存储

JSON,全称为 JavaScript Object Notation, 是 JavaScript对象标记, 通过对象和数组的组合来表示数据,构造简洁但结构化程度非常高,是一种轻量级的数据交换格式。

  1. 对象和数组
    • 在 JavaScript语言中,一切都是对象。 因此,任何支持的类型都可以通过 JSON来表示,如:字符串、数字、对象、数组等,对象和数组是比较特殊且常用的两种类型

      • 对象:在 JavaScript 中是使用花括号{}包裹起来的内容,数据结构为{key1: value1, key2: value2,… }的键值对结构。 在面向对象的语言中, key 为对象的属性, value 为对应的值。 键名可以使用整数和字符串来表示。 值的类型可以是任意类型。 
      • 数组:数组在 JavaScript 中是方括号[]包裹起来的内容,数据结构为["java","javascript","vb",.... ]的索引结构。在JavaScript 中, 数组是一种比较特殊的数据类型,也可以像对象那样使用键值对,但还是索引用得多。 同样,值的类型可以是任意类型。
        • 所以,一个JSON对象可以写成如下形式:
          [{
              "name": "Bob",
              "gender": "male",
              "birthday": "1992-10-18",},
              {"name": "Snlina",
               "gender": "female",
               "birthday": "1995-10-18"
          }]

          由中括号包围的就相当于列表类型,列表中的每个元素可以是任意类型,这个示例中它是字典类型,由大括号包围。
          JSON 可以由以上两种形式自由组合而成,可以无限次嵌套,结构清晰,是数据交换的极佳方式。

  2. 读取JSON
    • 可以调用 JSON 库 的 loads()方法将 JSON 文本字符串转为 JSON对象,可以通过 dumps()方法将 JSON 对象转为文本字符串。
      例:一段 JSON 形式的字符串,是 str 类型,可以用 Python 将其转换为可操作的数据结构——列表或字典:

      import json
      str = '''
          [{ "name":"Bob",
               "gender":"male",
               "birthday": "1992-10-18"
               },{
               "name": "Selina",
              "gender":"female",
              "birthday": "1995-10-18"
      }]
      '''
      print(type(str))
      data = json.loads(str)
      print(data)
      print(type(data))
      输出:
      <class 'str'>
      [{'name': 'Bob', 'gender': 'male', 'birthday': '1992-10-18'}, {'name': 'Selina', 'gender': 'female', 'birthday': '1995-10-18'}]
      <class 'list'>
      View Code

      使用 loads()方法将字符串转为 JSON 对象。 由于最外层是中括号,所以最终的类型是列表类型

      针对列表,可以用索引来获取对应的内容。 如,想取第一个元素里的 name 属性, 可以使用如下方式:

      data[0]['name']
      data[0].get('name')
      输出:
      Bob

      中括号加 0 索引,可以得到第一个字典元素,再调用键名即可得到相应的键值。 获取键值时有两种方式:一种是中括号加键名 ,另一种是通过 get()方法传人键名推荐使用 get()方法,这样如果键名不存在,则不会报错,会返回 None 另外, get()方法还可以传入第二个参数(即 .. 默认值),示例:

      data[0].get('age')
      data[0].get('age',25)
      输出:
      None
      25

      尝试获取年龄 age,在原字典中该键名不存在,此时默认会返回 None。 如果传入第 二个参数( 即默认值),那么在不存在的情况下返回该默认值

      注意:

      JSON 的数据需要用双引号来包围 , 不能使用单引号。 例:若使用如下形式表示,则会出现错误:

      import json
      str = '''
          [{ 'name':'Bob',
               'gender':'male',
               'birthday': '1992-10-18'
               },{
               'name': 'Selina',
              'gender':'female',
              'birthday':'1995-10-18'
      }]
      '''
      data = json.loads(str)
      输出:
      json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 2 column 8 (char 8)
      View Code

      出现 JSON解析错误提示。注意:JSON 字符串的表示需要用双引号,否则 loads()方法会解析失败

    • 从 JSON 文本中读取内容,例:有一个 data.json 文件,内容是刚才定义的 JSON 字符串,可以先将文本文件内容读出,然后再利用 loads()方法转化

      import json
      with open('data.json','r') as file:
          str = file.read()
          data = json.loads(str)
          print(data) 
  3. 输出JSON

    • 可以调用 dumps()方法将 JSON 对象转化为字符串。 例:将例中的列表重新写入文本:

      import json
      data = '''
          [{
          "name": "Bob",
          "gender": "male",
          "birthday": "1992-10-18"
      }]
      '''
      with open('data.json','a',encoding='utf-8') as f:
          f.write(json.dumps(data))

      利用 dumps()方法,可以将 JSON 对象转为字符串,然后再调用文件的 write()方法写入文本

    • 如果想保存 JSON 的格式,可以再加一个参数 indent,代表缩进字符个数。 示例:

      with open('data.json','a',encoding='utf-8') as f:
          f.write(json.dumps(data,indent=2))

      这样得到的内容会自动带缩进,格式更加清晰。

    • 如果 JSON 中包含中文字符,需要指定参数 ensure_ascii 为 False,还要规定文件输出的编码:

      with open('data.json','w',encoding='utf-8') as f:
          f.write(json.dumps(data,indent=2,ensure_ascii= False))

三、CSV文件存储    

  1. 写入
    • import csv
      with open('data.csv','w') as csvfile:
          writer =csv.writer(csvfile)
          writer.writerow(['id','name','age'])
          writer.writerow(['10001','Mike',20])
          writer.writerow(['10002','Bob',22])
          writer.writerow(['10003','Jordan',21])

      首先打开 data.csv 文件,然后指定打开的模式为 w(写入),获得文件句柄,随后调用 csv 库 的 writer()方法初始化写人对象,传入该句柄,然后调用 writerow()方法传入每行的数据即可完成写入。

      写人的文本默认以逗号分隔,调用一次 writerow()方法即可写入一行数据
    • 如果想修改列与列之间的分隔符,可以传入 delimiter 参数,代码如下:

      import csv
      with open('data.csv','w') as csvfile:
          writer =csv.writer(csvfile,delimiter='')
          --snip--

      里在初始化写入对象时传入 delimiter 为空格, 此时输出结果的每一列就是以空格分隔

    • 也可以调用 writerows()方法同时写入多行, 此时参数需要为二维列表,例:

      import csv
      with open('data.csv','w') as csvfile:
          writer =csv.writer(csvfile)
          writer.writerow(['id','name','age'])
          writer.writerow(['10001','Mike',20],['10002','Bob',22],['10003','Jordan',21])

      输出内容相同。

    • 是一般情况下,爬虫爬取的都是结构化数据,一般会用字典来表示。在 CSV 库中也提供了字典的写入方式,示例:

      import csv
      with open('data.csv','w') as csvfile:
          filenames = ['id','name','age']
          writer = csv.DictWriter(csvfile,fieldnames=filenames)
          writer.writeheader()
          writer.writerow({'id':'10001','name':'Mike','age':20})
          writer.writerow({'id':'10002','name':'Bob','age':22})
          writer.writerow({'id':'10003','name':'Jordan','age':21})

      先定义 3 个字段,用 fieldnames 表示,再将其传给 DictWriter 来初始化一个字典写人对 象,接着调用 writeheader()方法先写人头信息,然后再调用 writerow()方法传人相应字典。

    • 如果想追加写人,可以修改文件的打开模式,即将 open()函数的第二个参数改成 a,示例:

      import csv
      with open('data.csv','a') as csvfile:
          filenames = ['id','name','age']
          writer = csv.DictWriter(csvfile,fieldnames=filenames)
          writer.writerow({'id':'10004','name':'Durant','age':22})
    • 如果要写入中文内容,可能会遇到字符编码的问题,此时需要给 open()参数指定编码格式。 例如,再写入一行包含中文的数据,代码需要改写:

      import csv
      with open('data.csv','a',encoding='utf-8') as csvfile:
          filenames = ['id','name','age']
          writer = csv.DictWriter(csvfile,fieldnames=filenames)
          writer.writerow({'id':'10005','name':'王伟','age':22})

      这里需要给 open()函数指定编码,否则可能发生编码错误。

    • 如果接触过 pandas 库的话,可以调用 DataFrame 对象的 to_csv()方法来将数据写人 csv 文件中。

  2. 读取

    • 同样可以使用 csv 库来读取 csv 文件。 如,将写入的文件内容读取出来,如下:

      import csv
      with open('data.csv','r',encoding='utf-8') as csvfile:
          reader =csv.reader(csvfile)
          for row in reader:
              print(row)

      这里构造的是 Reader 对象,通过遍历输出了每行的内容,每一行都是一个列表形式。 注意, 如果 csv 文件中包含中文的话,还需要指定文件编码。

    • 如果知道 pandas库,可以利用 read_csv()方法将数据从 csv 中读取出来,如:

      import pandas as pd
      df=pd.read_csv('data.csv')
      print(df)

      在做数据分析的时候,此种方法用得比较多,也是一种比较方便地读取 csv 文件的方法。

猜你喜欢

转载自www.cnblogs.com/Mack-Yang/p/10098776.html
今日推荐