• Class 15


    保存的形式可以多种多样,最简单的形式是 接保存为文本文件,如 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('
        '.join([question, author, answers]))
            file.write('
        '+'='*50+'
        ')
            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('
        '.jason([question,author,answers]))
                file.write('
        '+'='*50+'
        ')

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

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

    二、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 文件的方法。

  • 相关阅读:
    Windows Phone 7之初体验(三.开发问答(转发))
    Windows phone 7 之初体验(一.安装Windows phone 7 sdk)
    python 程序的性能分析优化(huffman编码程序性能分析的一个小结论)
    图的深度优先遍历,及常见的扩展算法
    递归回溯与迭代回溯算法框架,打印在n个数字中取k个数字的所有可能
    python 实现的范式huffman压缩,解压缩
    <读书笔记> Thinking in python (Python 设计模式) 3. Proxy and State模式
    二分查找极其变形算法
    <读书笔记> Thinking in python (Python 设计模式) 1. Singlton的c++与python的实现
    <转载>openmesh文档的非专业翻译by kidux(学习generative programming非常好的库)
  • 原文地址:https://www.cnblogs.com/Mack-Yang/p/10098776.html
Copyright © 2020-2023  润新知