爬取与数据存储

ch5. 数据存储

  • 文件存储
    • JSON文件存储
  • 关系型数据库存储
    • Mysql

1. JSON文件存储

1. JSON中的对象和数组
  • 对象

​ 格式为{key1:value1, key2:value2}. 其中键名可以为字符串, 整数, 值可以为任意类型

  • 数组

​ 格式为['content1', 'content2', ....], 值可以为任意类型

2. JSON的读取
  • json.loads(): 该方法需要读取对象的格式符合JSON文件格式的要求。输出结果为列表,可以对接过使用索引等操作。

    • 可以接受字符串,也可以接受文本文件。如:

      import json
      with open('data.json', 'r') as f:
          str = file.read()
          data = json.loads(str)
      
    3. JSON的输出
  • json.dumps(): 该方法将json格式的对象转为字符串,若要将其输出至文件,还需要配合write()和open()方法。如:

    import json
    data = ...#data是符合json格式的对象
    with open('data.json','w', encoding = 'utf-8') as f:
        file.write(json.dumps(data, ensure_ascii = False))
    #若json中含有中文就需在open()中指定encoding=‘utf-8', write()中指定ensure_ascii = False
    

2. 关系型数据库—MySQL的存储

1. 链接到数据库及相关基本操作
  • pysql.connect(host = 'localhost', user = 'root', password = '*****', port(3306)): 成功连接后返回一个数据库对象(令之为db),利用该数据库对象我们可以对数据库进行增添改查等操作。

    参数说明

    • host,默认为localhost
    • user,登录数据库的用户名
    • password,数据库的密码
    • port,数据库端口,默认为3306
  • db.close(): 在操作完毕后需要将数据库对象关闭。

  • db.cursor(): 对数据库进行各种操作要通过cursor()方法返回的游标(令之为cr)来进行。

  • cr.execute('sqlSentence') : 执行语句

  • cr.fetchone(): 取回sql中返回的结果

  • db.roolback(): 确保操作为原子操作,保持数据的一致性,即若失败则回退

  • db.commit(): 插入、更行等操作在执行完db.execute()后还需要执行该方法才能真正是的操作生效

2. 创建表

创建表的操作关键在于sql语句的书写,以如下代码为例:

import pymqsql
db = pymysql.connect(host = 'localhost', user = 'root', password = '******', port = 3306, db = 'spider')
cr = db.cursor()
sqlSen = 'CREATE TABLE IF NOT EXISTS stuents(id VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, age INT NOT NULL, PRIMARY KEY(id))'
cr.execute(sql)
db.close()
3. 插入数据(动态)
  • 静态插入语句:用拼接字符串的方式来完成

    id = '1716240306'
    user = 'bob'
    age = '20'
    db = pysql.connect(...)
    cr = db.cursor()
    sqlSen = 'INSERT INTO students(id, name, age)' values(%s, %s, %s)
    try:
        cr.execute(sql, (id, user, age))
        db.commit()
    except:
        db.roolback()
    
  • 动态插入语句

    data = {
        'id':'1716240306',
        'name':'xzy',
        'age':20,
        'gender':'male'
    }
    tableS = 'studentes'# 用变量保存字段,以便于修改、调用
    keysS = ','.join(data.keys())# 用','将data中的键分隔开,以供函数调用使用
    valusS = ','.join(['%s'] * len(data))# '[‘%s’] * 3' == '['%s', '%s', '%s’]'
    sqlSen = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=tableS, keys = keysS, values = valuesS)
    #str.format()用于填补字符串,填补入字符串中的{},format()中填入要填补的内容,从左向右按序填入。若字串中占位符形式为{argName},则需要在参数中使用argName=value的形式来传递参数
    try:
        if cr.execute(sqlSen, tuple(data.values())):  #tuple()元组返回列表,以供sql语句提供参数
            print('successful')
            db.commit()
    except:
        print('failed')
        db.roolback()
    db.close()
    
  • 不重复的更新数据

data = {
    'id':'1716240306',
    'name':'xzy',
    'age':20,
    'gender':'male'
}
tableS = 'students'
keysS = ','.join(data.keys())
valuesS = ','.join(['%s']*len(data))
#['%s']*3 == ['%s','%s','%s']
sqlSen = 'INSERT INTO {table}({keys}) VALUES({values}) ON DUPLICATE KEY UPDATE'.format(table = tableS, keys = kyesS, value = valuesS)
#'ON DUPLICATE KEY UPDATE'表示若主键存在就执行更新操作,否则执行插入操作。
updatePart = ','.join(["{key} = %s".format(key = keyS) for key in data])
#In[13]: (["{key} = %s".format(key = keysS) for key in data])
#Out[13]: ['id = %s', 'name = %s', 'age = %s', 'gender = %s']
sqlSen += updatePart
try:
    if cr.execute(sqlSen, tuple(data.values())*2):
#因为在加入更新语句后sqlSen中共有六处需要填进参数,所以需要参数处需要'*2'
        db.commit()
        print('successful')               
except:
    db.rollback()
    print('failed')
db.close    
  • 查询数据
sqlSen = 'SELECT * FROM students WHERE age >= 20'
try:
    cr.execute(sqlSen)
    print('Count:',cr.rowcount)
    one = cr.fetchone()
    #从sql服务取回了一条结果,随后在sql中的指针自动向后偏移一位
    print('one row: ', one)
    results = cr.fetchall()
    #results保存了sql剩余的所有结果,(有一条结果被fetchone取走)
    pritn('results:', results)
    for aRow in results:
        print(aRow)
except:
    print('error')
posted @ 2022-08-13 09:32  dysonkkk  阅读(29)  评论(0编辑  收藏  举报