关系型数据库存储

关系型数据库是基于关系模型的数据库,而关系模型是通过二维表保存的,所以它的存储方式就是行列组成的表。
每一列是一个字段,每一行是一条记录。表可以看作某个实体的集合,而实体之间存在联系,就需要表与表之间的关联关系来体现。
例如 主键和外键的关联关系,多个表组成一个数据库,也就是关系型数据库。

关系型数据库有很多种。如SQLite、MySQL、Oracle、SQL Server、DB2等。

1.MySQL的存储

在python2中,连接MySQL的库大多是使用MySQLdb,但是此库的官方并不支持Python3,所以这里推荐使用PyMySQL

确保已经安装好了mysql数据库 并保证能正常运行

安装pymysql :

 pip3 install pymysql

验证:

<<< import pymysql
<<< pymysql.VERSION

输出版本信息 (0, 9, 2, None) 验证成功

1.1 连接数据库

尝试连接数据库 例如 mysql已经运行在本地 用户名为root 密码为123456 端口为3306
利用pymysql先连接mysql 创建一个新的数据库 spider

import pymysql

db = pymysql.connect(host="localhost",user="root",password="",port=3306)#声明一个mysql连接对象db
cursor = db.cursor()#获得mysql的操作游标 利用游标来执行sql语句
cursor.execute('SELECT VERSION()')#execute() 执行sql语句 查询当前mysql版本
data = cursor.fetchone()#获得第一条数据
print('Database version:',data)
cursor.execute("CREATE DATABASE spiders DEFAULT CHARACTER SET utf8")#创建数据库 库名spiders 默认编码utf-8
db.close()#关闭数据库

通常创建数据库只需要执行一次就好了
创建数据库后,连接时需要额外指定一个参数db

1.2 创建表

创建数据表 students
指定三个字段:
字段名 含义 类型
id 学号 varchar
name 姓名 varchar
age 年龄 int

import pymysql

db = pymysql.connect(host='localhost',user='root',password='',port=3306,db='spiders')
cursor = db.cursor()
sql = 'CREATE TABLE IF NOT EXISTS students (id VARCHAR(255) NOT NULL,name VARCHAR(255) NOT NULL,age INT NOT NULL,PRIMARY KEY (id))'
cursor.execute(sql)
db.close()

在爬虫过程中 要根据爬取结果设计特定的字段

1.3 插入数据

示例: 爬取了一个学生信息 学号为20180001 名字为Bob 年龄为20

import pymysql

id = ''
name = 'Bob'
age = 20 db = pymysql.connect(host='localhost',user='root',password='',port=3306,db='spiders')
cursor = db.cursor()
sql = 'INSERT INTO students(id,name,age) values(%s,%s,%s)'
try:
cursor.execute(sql,(id,name,age))
db.commit()#执行数据插入
except:
db.rollback()
db.close()

构造sql语句 没有使用字符串拼接的方式 等同于如下:
sql = 'INSERT INTO students(id,name,age) values('+ id +','+ name +','+ age +')'
采用直接格式化 %s 实现 有多少values 写多少%s 避免字符串拼接 引号冲突的麻烦

commit() 将语句提交到数据库执行 对于数据插入 更新 删除等操作都需要用到

rollback() 执行数据回滚

拓展:事务机制 (可以确保数据一致性)

例如插入一条数据,不会存在插入一半的情况,要么全部插入,要么不插入 这是事务的原子性
还有三个属性 一致性、隔离性、持久性 通常四个属性被称为ACID特性

原子性(atomicity) 事务是不可分割的工作单位 要么做,要么不做。

一致性(consistency)事务必须使数据库从一个一致性变到另一个一致性 与原子性密切相关。

隔离性(isolation) 一个事务执行不能被其他事务干扰,即一个事务内部操作及使用的数据对并发的其他事务是隔离的
并发执行的各个事务之间不能相互干扰。

持久性(durability)指一个事务一旦提交,它对数据库中数据改变就应该是永久的,
接下来的操作或故障不应该对其有任何影响。

插入,更新,删除操作都是对数据库进行更改的操作,更改操作都必须为一个事务,所以标准写法为:

try:
cursor.execute(sql)
db.commit()
except:
db.rollback()

优化

例如 上面的插入操作需要增加一个字段gender sql语句就要更改为

sql = 'INSERT INTO students(id,name,age,gender) values(%s,%s,%s,%s)'

元组参数为

(id,name,age,gender)

更改目标: 插入方法无需变动 传入一个动态的字典例如:
{
'id':'20180001',
'name':'Bob',
'age':20
}

更改为:SQL语句根据动态字典构造,元组参数动态构造

data = {
'id':'',
'name':'Mike',
'age':24
}
table = 'students'#自定义表名
keys = ','.join(data.keys())#利用keys()函数 取出data中的键名 并用逗号拼接
values = ','.join(['%s'] * len(data))#自定义%s列表 获取到data长度 相乘 并用逗号拼接
sql = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=table,keys=keys,values=values)#利用format()函数构造表名、字段名和占位符
try:
if cursor.execute(sql,tuple(data.values())):#execute函数传入第二个参数 元组参数
print('Successful')
db.commit()
except:
print('Failed')
db.rollback()
db.close()

1.4 更新数据

sql = 'UPDATE students SET age = %s WHERE name = %s'#占位符构造sql
try:
cursor.execute(sql,(25,'Bob'))#执行execute 传入元组参数
db.commit()
except:
db.rollback()
db.close()

简单数据更新 完全可以使用以上方法

实际爬取过程中 大部分需要插入数据 涉及到有没有重复的数据 如果有就更新 不需要重复保存数据
实现数据去重 如果数据存在 更新数据 数据不存在就 插入数据

示例:

data = {
'id':'',
'name':'Bod',
'age':26
}
table = 'students'#自定义表名
keys = ','.join(data.keys())#利用keys()函数 取出data中的键名 并用逗号拼接
values = ','.join(['%s'] * len(data))#自定义%s列表 获取到data长度 相乘 并用逗号拼接
sql = 'INSERT INTO {table}({keys}) VALUES ({values}) ON DUPLICATE KEY UPDATE'.format(table=table,keys=keys,values=values)#利用format()函数构造表名、字段名和占位符
update = ','.join([" {key} = %s".format(key=key) for key in data])
sql += update
try:
if cursor.execute(sql,tuple(data.values())*2):#execute函数传入第二个参数 元组参数
print('Successful')
db.commit()
except:
print('Failed')
db.rollback()
db.close()

实际构造的是插入语句 ON DUPLICATE KEY UPDATE 如果主键存在 就执行更新操作
完整的sql应该是:
sql = 'INSERT INTO students(id,name,age) VALUES(%s,%s,%s) ON DUPLICATE KEY UPDATE id = %s,name=%s,age=%s'
%s 变成了6个 所以乘2

1.5 删除数据

删除操作相对简单 只需要执行DELETE语句 指定删除表名和条件

示例:

table = 'students'
condition = 'age > 20' sql = 'DELETE FROM {table} WHERE {condition}'.format(table=table,condition=condition) try:
if cursor.execute(sql):
print('Successful')
db.commit()
except:
print('Failed')
db.rollback()
db.close()

将条件当作字符串传递 实现删除操作。

1.6 查询数据

查询SELECT语句 示例如下:

sql = 'SELECT * FROM students WHERE age >= 20'

try:
cursor.execute(sql)
print('Count:',cursor.rowcount)#获取查询结果条数
one = cursor.fetchone()#获取第一条数据 返回元组形式
print('One:',one)
results = cursor.fetchall()#获取结果的所有数据
print('Results:',results)
print('Result Type:',type(results))#二维元组
for row in results:#遍历输出
print(row)
except:
print('Error')

内部查询时 偏移指针用来指向查询结果

此外还可以使用 while循环加 fetchone() 获取所有数据
fetchall() 会将结果以元组形式全部返回 如果数据量很大 占用的资源会非常高

推荐使用以下方法逐条获取数据

sql = 'SELECT * FROM students WHERE age >= 20'

try:
cursor.execute(sql)
print('Count:',cursor.rowcount)
row = cursor.fetchone()
while row:
print('Row:',row)
row = cursor.fetchone()
except:
print('Error')

每循环一次 指针偏移一条数据 随用随取 简单高效。

Python3编写网络爬虫11-数据存储方式四-关系型数据库存储的更多相关文章

  1. python3编写网络爬虫13-Ajax数据爬取

    一.Ajax数据爬取 1. 简介:Ajax 全称Asynchronous JavaScript and XML 异步的Javascript和XML. 它不是一门编程语言,而是利用JavaScript在 ...

  2. Python3编写网络爬虫12-数据存储方式五-非关系型数据库存储

    非关系型数据库存储 NoSQL 全称 Not Only SQL 意为非SQL 泛指非关系型数据库.基于键值对 不需要经过SQL层解析 数据之间没有耦合性 性能非常高. 非关系型数据库可细分如下: 键值 ...

  3. Python3编写网络爬虫10-数据存储方式三-CSV文件存储

    3.CSV文件存储 CSV 全称 Comma-Separated Values 中文叫做逗号分隔值或者字符分隔值,文件以纯文本形式存储表格数据.文件是一个字符序列 可以由任意数目的记录组成相当于一个结 ...

  4. Python3编写网络爬虫08-数据存储方式一-文件存储

    数据存储 用解析器解析出数据之后,就是存储数据了.保存的形式可以多种多样,最简单的形式是直接保存为文本文件,如TXT JSON CSV等.另外还可以保存到数据库中,如关系型数据库MySQL 非关系型数 ...

  5. python3编写网络爬虫20-pyspider框架的使用

    二.pyspider框架的使用 简介 pyspider是由国人binux 编写的强大的网络爬虫系统 github地址 : https://github.com/binux/pyspider 官方文档 ...

  6. python3编写网络爬虫18-代理池的维护

    一.代理池的维护 上面我们利用代理可以解决目标网站封IP的问题 在网上有大量公开的免费代理 或者我们也可以购买付费的代理IP但是无论是免费的还是付费的,都不能保证都是可用的 因为可能此IP被其他人使用 ...

  7. python3编写网络爬虫19-app爬取

    一.app爬取 前面都是介绍爬取Web网页的内容,随着移动互联网的发展,越来越多的企业并没有提供Web页面端的服务,而是直接开发了App,更多信息都是通过App展示的 App爬取相比Web端更加容易 ...

  8. python3编写网络爬虫23-分布式爬虫

    一.分布式爬虫 前面我们了解Scrapy爬虫框架的基本用法 这些框架都是在同一台主机运行的 爬取效率有限 如果多台主机协同爬取 爬取效率必然成倍增长这就是分布式爬虫的优势 1. 分布式爬虫基本原理 1 ...

  9. [Python3网络爬虫开发实战] 5.2-关系型数据库存储

    关系型数据库是基于关系模型的数据库,而关系模型是通过二维表来保存的,所以它的存储方式就是行列组成的表,每一列是一个字段,每一行是一条记录.表可以看作某个实体的集合,而实体之间存在联系,这就需要表与表之 ...

随机推荐

  1. nginx介绍 - 部署到linux中

    前言: tomcat理论并发处理能力, 大概500左右吧, 即使通过一些优化, 能提升一点, 但是, 并不能达到质变, 最多涨几百. 对于非互联网项目, 确实够用了. 在企业中, 如果要达到500并发 ...

  2. 一篇极好的Git 总结

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯工蜂发表于云+社区专栏 常用命令 简单的,常用的命令也就几个.但是想非常熟练使用,怕是要记住几十个. Workspace:工作区( ...

  3. 使用com.aspose.words将word模板转为PDF乱码解决方案(window下正常)

    最近在做电子签名过程中,需要将合成的电子签名的word文件(正常)转换为pdf文件时,在开发平台window下转换没有问题,中文也不会出现乱码.但是将项目部署到正式服务器(Linux)上,转换出来的p ...

  4. angular监听dom渲染完成,判断ng-repeat循环完成

    一.前言 最近做了一个图片懒加载的小插件,功能需要dom渲染完成后,好获取那些需要懒加载的dom元素.那么问题来了,如果只是感知静态的dom用ready,onload都可以,但项目用的angular, ...

  5. Deep learning with Python 学习笔记(7)

    介绍一维卷积神经网络 卷积神经网络能够进行卷积运算,从局部输入图块中提取特征,并能够将表示模块化,同时可以高效地利用数据.这些性质让卷积神经网络在计算机视觉领域表现优异,同样也让它对序列处理特别有效. ...

  6. Docker系列之Docker镜像(读书笔记)

    一.基本概念 Docker包括三个基本概念镜像.容器.仓库. Docker镜像:就是一个只读的模板.例如:一个镜像可以包含一个完整的ubuntu操作系统环境,里面仅安装了Apache或其他应用程序.用 ...

  7. 搭建前端监控系统(四)Js截图上报篇

    ===================================================================== 前端监控系统: DEMO地址  GIT代码仓库地址 ==== ...

  8. 一张图读懂PBN旁切转弯计算

    当DOC8168进入PBN章节以后,所有的保护区不再标注风螺旋的字母位置点.似乎ICAO已经有了精确计算的方法,只是没有告诉我们.沿着风螺旋的轨迹一路走来,切线与角度的换算方法想必已经相当熟悉了吧,这 ...

  9. [转]完整记录在 windows7 下使用 docker 的过程

    本文转自:https://www.jianshu.com/p/d809971b1fc1 借助 docker 可以不在开发电脑中安装环境,比如 nodejs,记录下如何实现. 下载安装 根据自己的电脑系 ...

  10. 浅谈c#的三个高级参数ref out 和Params

    c#的三个高级参数ref out 和Params 前言:在我们学习c#基础的时候,我们会学习到c#的三个高级的参数,分别是out .ref 和Params,在这里我们来分别的讲解一下,在这里的我们先不 ...