一、json文件操作
什么是json:
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。它基于 ECMAScript (w3c制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。更多解释请见:https://baike.baidu.com/item/JSON/2462549?fr=aladdin
JSON支持数据格式:
- 对象(字典)。使用花括号。
- 数组(列表)。使用方括号。
- 整形、浮点型、布尔类型还有null类型。
- 字符串类型(字符串必须要用双引号,不能用单引号)。
多个数据之间使用逗号分开。
注意:json本质上就是一个字符串。
字典和列表转JSON:
import json
books = [
{
'title': '钢铁是怎样练成的',
'price': 9.8
},
{
'title': '红楼梦',
'price': 9.9
}
]
json_str = json.dumps(books,ensure_ascii=False)
print(json_str)
因为json
在dumps
的时候,只能存放ascii
的字符,因此会将中文进行转义,这时候我们可以使用ensure_ascii=False
关闭这个特性。
在Python
中。只有基本数据类型才能转换成JSON
格式的字符串。也即:int
、float
、str
、list
、dict
、tuple
。
将json数据直接dump
到文件中:
json
模块中除了dumps
函数,还有一个dump
函数,这个函数可以传入一个文件指针,直接将字符串dump
到文件中。示例代码如下:
books = [
{
'title': '钢铁是怎样练成的',
'price': 9.8
},
{
'title': '红楼梦',
'price': 9.9
}
]
with open('a.json','w') as fp:
json.dump(books,fp)
将一个json字符串loads成Python对象:
json_str = '[{"title": "钢铁是怎样练成的", "price": 9.8}, {"title": "红楼梦", "price": 9.9}]'
books = json.loads(json_str,encoding='utf-8')
print(type(books))
print(books)
直接从文件中读取json:
import json
with open('a.json','r',encoding='utf-8') as fp:
json_str = json.load(fp)
print(json_str)
区别:json.load 和json.loads json.dump和json.dumps
参考:https://www.cnblogs.com/bigtreei/p/10466518.html
loads: 是将string转换为dict
dumps: 是将dict转换为string
load: 是将里json格式字符串转化为dict,读取文件
dump: 是将dict类型转换为json格式字符串,存入文件
二、csv文件操作
1.读取csv文件:
def read_csv_demo1():
with open('stock.csv', 'r') as fp:
# reader是一个迭代器
reader = csv.reader(fp)
next(reader) #跳过第一行
for x in reader:
name = x[3] #secShortName
volumn = x[-1] #turnoverVol
print({'name': name, 'volumn': volumn})
如果csv文件的列更换了顺序,再通过下标获取会出错,那么可以使用DictReader
通过标题来获取数据。示例代码如下:
import csv
with open('stock.csv','r') as fp:
reader = csv.DictReader(fp)
# 使用DictReader创建的reader对象
# 不会包含标题那行的数据,即从索引为1开始
# reader是一个迭代器,遍历这个迭代器,返回来的是一个有序的字典(即与csv文件中列表顺序保持一致)
for x in reader:
value = {"name":x['secShortName'],'volumn':x['turnoverVol']}
print(value)
2.写入数据到csv文件:
写入数据到csv文件,需要创建一个writer
对象,主要用到两个方法。一个是writerow
,这个是写入一行。一个是writerows
,这个是写入多行。示例代码如下:
import csv
headers = ['name','age','classroom'] #表头可以是列表或元组
values = [
('zhiliao',18,'111'),
('wena',20,'222'),
('bbc',21,'111')
]
#encoding='utf-8' 指定编码, newline='' 默认是'\n' 指定不用空行
with open('test.csv','w',encoding='utf-8', newline='') as fp:
writer = csv.writer(fp)
writer.writerow(headers) #写入一行
writer.writerows(values) #写入多行
也可以使用字典的方式把数据写入进去。这时候就需要使用DictWriter
了。示例代码如下:
import csv
headers = ['name','age','classroom']
values = [
{"name":'wenn',"age":20,"classroom":'222'},
{"name":'abc',"age":30,"classroom":'333'}
]
with open('test.csv','w',newline='') as fp:
writer = csv.DictWriter(fp,headers)
# 写入表头数据的时候,需要调用writeheader方法
writer = csv.writeheader()
writer.writerow({'name':'zhiliao',"age":18,"classroom":'111'})
writer.writerows(values)
三、pymysql 操作数据库
1、准备工作
安装mysql:
- 在官网:https://dev.mysql.com/downloads/windows/installer/5.7.html
- 推荐下载免安装版本的MySQL
navicat:
navicat是一个操作mysql数据库非常方便的软件。使用他操作数据库,就跟使用excel操作数据是一样的。
安装驱动程序:
Python要想操作MySQL。必须要有一个中间件,或者叫做驱动程序。驱动程序有很多。比如有mysqldb
、mysqlclient
、pymysql
等。在这里,我们选择用pymysql
。安装方式也是非常简单,通过命令pip install pymysql
即可安装。
2、基本用法
2.1 数据库连接:
数据库连接之前。首先先确认以下工作完成,这里我们以一个pymysql_test
数据库.以下将介绍连接mysql
的示例代码:
import pymysql
#1、连接数据库
conn = pymysql.connect(
host="127.0.0.1",
user='root',
password='root',
database='pymysql_test',
port=3306 #必须是整型
)
#2、获取游标 即mysql >
cursor = conn.cursor()
#3、执行sql语句
sql='select * from user1 where id = %s;'
rows = cursor.execute(sql,1) #返回受影响行数rows
#4、关闭
cursor.close()
conn.close()
可以通过Navicat软件或cmd命令行创建数据库表,也可以通过python代码创建表结构
c_sql = '''create table test1(
id int(3) zerofill primary key auto_increment,
name varchar(15) not null
)engine=InnoDB,charset=utf8;
'''
cur.execute(c_sql)
2.2 插入数据:
import pymysql
db = pymysql.connect(
host="127.0.0.1",
user='root',
password='root',
database='pymysql_test',
port=3306
)
cursor = db.cursor()
sql = """
insert into user(
id,username,gender,age,password
)
values(null,'abc',1,18,'111111');
"""
cursor.execute(sql)
db.commit()
db.close()
补充:""" """
三引号之间可以写入多行数据。
如果在数据还不能保证的情况下,可以使用以下方式来插入数据:
sql = """
insert into user(
id,username,gender,age,password
)
values(null,%s,%s,%s,%s);
"""
cursor.execute(sql,('spider',1,20,'222222')) #参数可以是元组、列表、字典
db.commit()
db.close()
注意:execute() 插入的是一条数据
def execute(self, query, args=None):
"""Execute a query
:param str query: Query to execute.
:param args: parameters used with query. (optional)
:type args: tuple, list or dict(元组 列表 字典)
:return: Number of affected rows 返回受影响的行数
:rtype: int
如果参数是列表或元组,%s 在query字符串中可以被用作占位符
If args is a list or tuple, %s can be used as a placeholder in the query.
如果参数是字典,%(name)s 在query字符串中可以被用作占位符
If args is a dict, %(name)s can be used as a placeholder in the query.
"""
注意:其中name是传入的字典的key
executemany插入多条数据:
sql = """
insert into user (username,password,age) values (%s,%s,%s)
"""
params = [('zhao','111111',22),('sun','111111',45)]
cursor.executemany(sql,params)
conn.commit() #提交到数据库
cursor.close()
conn.close()
2.3 查找数据:
使用pymysql
查询数据。可以使用fetch*
方法。
fetchone()
:这个方法每次之获取一条数据。fetchall()
:这个方法接收全部的返回结果。fetchmany(size)
:可以获取指定条数的数据。
示例代码如下:
或者是直接使用cursor = db.cursor() sql = """ select * from user """ cursor.execute(sql) while True: result = cursor.fetchone() if not result: break print(result) db.close()
fetchall
,一次性可以把所有满足条件的数据都取出来:
或者是使用cursor = db.cursor() sql = """ select * from user """ cursor.execute(sql) results = cursor.fetchall() for result in results: print(result) db.close()
fetchmany
,指定获取多少条数据:cursor = db.cursor() sql = """ select * from user """ cursor.execute(sql) results = cursor.fetchmany(1) for result in results: print(result) db.close()
2.4 删除数据:
cursor = db.cursor() sql = """ delete from user where id=1 """ cursor.execute(sql) db.commit() db.close()
2.5 更新数据:
sql = """ update user set username='aaa' where id=1 """ cursor.execute(sql) conn.commit() conn.close()
2.6 关闭数据库连接
需要分别的关闭指针对象和连接对象,他们有名字相同的方法cursor.close() conn.close()
3、pymysql操作MySQL占位符问题
使用占位符可以解决SQL注入
# 原来是我们对sql进行字符串拼接 # sql="select * from userinfo where name='%s' and password='%s'" %(user,pwd) # rows=cursor.execute(sql) #改写为(execute帮我们做字符串拼接,我们无需且一定不能再为%s加引号了) #注意%s需要去掉引号,因为pymysql会自动为我们加上 sql="select * from userinfo where name=%s and password=%s" rows=cursor.execute(sql,[user,pwd]) #pymysql模块自动帮我们解决sql注入的问题,只要我们按照pymysql的规矩来。
SQL语句编写(占位符的应用)
pymysql执行的关键还是在SQL语句的编写,有几种方式:
1、完整的SQL语句,直接调用
2、利用占位符传递参数。这里要注意,无论整数、字符串,占位符都为 %s,且不需加引号 ,在sql语句中借助占位符组成完整SQLsql_select = "select * from tablename" cursor.execute(sql_select)
3、参数替代tabel = 'persons' sql = "select * from %s" % table cursor.execute(sql)
4、字典类型传递变量,这里要保证占位符的keys要包含在传递的字典keys中tabel = 'persons' sql = "select * from %s" cursor.execute(sql, table) # 参数多于1个时,execute()传入参数应为list或者tuple类型 sql_update = "update persons set birthday=%s where ID=%s" cursor.execute(sql_update, ('2001/7/5', 3))
# 这里的占位符%s修改为%(字典keyname)s sql_insert = "insert into persons(ID, LastName, FirstName) values (%(ID)s, %(LastName)s, %(FirstName)s)" message = { "ID": 7, "LastName": "Jone", "FirstName": "Bob", } cursor.execute(sql_insert, message)
4、通过示意图理解pymysql
参考:https://www.cnblogs.com/fanks99/p/9713873.html
https://blog.csdn.net/guofeng93/article/details/53994112概念理解
pymysql操作数据库流程图解
理解Connection、Cursor
Connection() 的参数列表
加粗参数是必须的
- host,连接的数据库服务器主机名,默认为本地主机(localhost)。
- user,连接数据库的用户名,默认为当前用户。
- password,连接密码,没有默认值。
- db,连接的数据库名,没有默认值。
- port,指定数据库服务器的连接端口,默认是3306。
- conv,将文字映射到Python类型的字典。
- MySQLdb.converters.conversions
- cursorclass,cursor()使用的种类,默认值为MySQLdb.cursors.Cursor,可以设置为DictCursor
from
- compress,启用协议压缩功能。
- named_pipe,在windows中,与一个命名管道相连接。
- init_command,一旦连接建立,就为数据库服务器指定一条语句来运行。
- read_default_file,使用指定的MySQL配置文件。
- read_default_group,读取的默认组。
- unix_socket,在unix中,连接使用的套接字,默认使用TCP。
- charset,编码方式
连接对象的db.close()方法可关闭数据库连接,并释放相关资源。
连接对象的db.cursor([cursorClass])方法返回一个指针对象,用于访问和操作数据库中的数据。
连接对象的db.begin()方法用于开始一个事务,如果数据库的AUTOCOMMIT已经开启就关闭它,直到事务调用commit()和rollback()结束。
连接对象的db.commit()和db.rollback()方法分别表示事务提交和回退。
指针对象的cursor.close()方法关闭指针并释放相关资源。
指针对象的cursor.execute(query[,parameters])方法执行数据库查询。
指针对象的cursor.fetchall()可取出指针结果集中的所有行,返回的结果集一个元组(tuples)。
指针对象的cursor.fetchmany([size=cursor.arraysize])从查询结果集中取出多行,我们可利用可选的参数指定取出的行数。
指针对象的cursor.fetchone()从查询结果集中返回下一行。
指针对象的cursor.arraysize属性指定由cursor.fetchmany()方法返回行的数目,影响fetchall()的性能,默认值为1。
指针对象的cursor.rowcount属性指出上次查询或更新所发生行数。-1表示还没开始查询或没有查询到数据。
Cursor对象常用方法
- close() :关闭此游标对象
- fetchone() :得到结果集的下一行
- fetchmany([size = cursor.arraysize]) :得到结果集的下几行
- fetchall() :得到结果集中剩下的所有行
- excute(sql[, args]) :执行一个数据库查询或命令
- excutemany(sql, args) :执行多个数据库查询或命令
使用步骤
1、建立数据库连接
import pymysql
conn = pymysql.connect(
host='127.0.0.1',
user='root',
password="root",
database='spider_mysql',
port=3306, #必须是int
charset='utf8'
)
cursor=conn.cursor()
2、执行数据库操作rows=cursor.execute(sql,param)
我们要使用连接对象获得一个cursor对象,接下来,我们会使用cursor提供的方法来进行工作.
这些方法包括两大类:1.执行命令,2.接收返回值
3、cursor用来执行命令的方法:
- callproc(self, procname, args):用来执行存储过程,接收的参数为存储过程名和参数列表,返回值为受影响的行数
- execute(self, query, args):执行单条sql语句,接收的参数为sql语句本身和使用的参数列表,返回值为受影响的行数
- executemany(self, query, args):执行单挑sql语句,但是重复执行参数列表里的参数,返回值为受影响的行数
- nextset(self):移动到下一个结果集
4、cursor用来接收返回值的方法:
- fetchall(self):接收全部的返回结果行.
- fetchmany(self, size=None):接收size条返回结果行.如果size的值大于返回的结果行的数量,则会返回cursor.arraysize条数据.
- fetchone(self):返回一条结果行.
- scroll(self, value, mode=’relative’):移动指针到某一行.如果mode=’relative’,则表示从当前所在行移动value条,如果mode=’absolute’,则表示从结果集的第一 行移动value条.
5、下面的代码是一个完整的例子.
使用sql语句,这里要接收的参数都用%s占位符,要注意的是,无论你要插入的数据是什么类型,占位符永远都要用%s
sql="insert into cdinfo values(%s,%s,%s,%s,%s)"
#param应该为tuple或者list
param=(title,singer,imgurl,url,alpha)
#执行,如果成功,n的值为1
n=cursor.execute(sql,param)
#再来执行一个查询的操作
cursor.execute("select * from cdinfo")
#我们使用了fetchall这个方法.这样,cds里保存的将会是查询返回的全部结果.每条结果都是一个tuple类型的数据,这些tuple组成了一个tuple
cds=cursor.fetchall()
#因为是tuple,所以可以这样使用结果集
print(cds[0][3])
#或者直接显示出来,看看结果集的真实样子
print(cds)
#如果需要批量的插入数据,就这样做
sql="insert into cdinfo values(0,%s,%s,%s,%s,%s)"
#每个值的集合为一个tuple,整个参数集组成一个tuple,或者list
param=((title,singer,imgurl,url,alpha),(title2,singer2,imgurl2,url2,alpha2))
#使用executemany方法来批量的插入数据.这真是一个很酷的方法!
n=cursor.executemany(sql,param)
需要注意的是(或者说是我感到奇怪的是),在执行完插入或删除或修改操作后,需要调用一下conn.commit()方法进行提交.这样,数据才会真正保 存在数据库中.我不清楚是否是我的mysql设置问题,总之,今天我在一开始使用的时候,如果不用commit,那数据就不会保留在数据库中,但是,数据 确实在数据库呆过.因为自动编号进行了累积,而且返回的受影响的行数并不为0.
6、关闭数据库连接
需要分别的关闭指针对象和连接对象.他们有名字相同的方法cursor.close()
conn.close()
Django操作数据库
django是一个出色的用于python的web框架。django连接有操作数据库的api,使用起来十分简洁。我们在settings.py中配置好所要连接的数据库,然后在modules、view、urls中分别写好业务逻辑。
四、MongoDB数据库操作
菜鸟教程:https://www.runoob.com/mongodb/mongodb-tutorial.html
1.准备工作
MongoDB是一个基于分布式文件存储的NoSQL数据库,在处理海量数据的时候会比MySQL更有优势,爬虫如果数据量十分庞大,推荐使用MongoDB,当然没有达到海量的数据完全也可以使用MongoDB来存储数据。因此学会MongoDB也是爬虫工程师必须要掌握的一个技能。
Windows下安装MongoDB数据库:
注意:安装路径中不要出现中文 空格
运行MongoDB:
1.创建数据目录:
启动MongoDB之前,首先要给它指定一个数据存储路径,比如在MongoDB的安装路径下新建一个data文件夹,专门用来存储数据的。
2.把MongoDB的bin目录加入到环境变量中
3.执行命令mongod --dbpath C:\Program Files\MongoDB\Server\3.4\data
启动
连接MongoDB:
在环境变量设置好的前提下,执行mongo
即可进入到mongo的操作终端了。
使用Compass软件连接MongoDB:
compass是一个GUI操作MongoDB的客户端,类似与Navicat
将MongoDB制作成Windows服务:
启动MongoDB后如果想要让MongoDB在后台一直运行,而不是一直开着一个cmd终端运行着mongod.exe服务端,我们可以将MongoDB制作成一个类似于Windows后台服务,以后通过一行命令即可运行MongoDB服务端,下面是制作步骤:
1.创建配置文件:在MongoDB安装的路径下创建配置文件/log/mongod.cfg
(路径和名字不是必须和我保持一致,但是后缀名必须是cfg),然后再配置文件中添加如下代码:
logpath=C:\programApps\mongodb\log\mongod.log
dbpath=C:\programApps\mongodb\data
logpath是日志的路径,dbpath的MongoDB数据库的存储路径。
2.安装MongoDB服务:
使用下面命令即可将MongoDB安装成一个服务:
mongod --config 'cfg配置文件所在的路径' --install
例如:
mongod --config 'C:\programApps\mongodb\mongod.cfg' --install
3.启动MongoDB:net start mongodb
4.关闭MongoDB:net stop mongodb
5.移除MongoDB:"" --remove
2.MongoDB基本使用:
2.1 MongoDB概念介绍
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
---|---|---|
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
joins | ××× | 表连接/MongoDB不支持表连接 |
primary key | primary key | 主键/MongoDB自动将_id设置为主键 |
2.2 MongoDB三元素:
三元素:数据库、集合、文档
1.文档(document):就是关系型数据库中的一行row。文档是一个对象由键值对构成,是json的扩展形式:
{'name':'xiong','age':18}
2.集合(collection):就是关系型数据库中的表。可以存储多个文档,结构可以不固定,比如可以存储如下文档在一个集合中:
{'name':'xiong','age':18}
{'name':'xiong','gender':1}
{'title':'美食','price':128}
2.3 MongoDB基本操作命令
1.db
:查看当前数据库
2.show dbs
:查看所有数据库
3.use 数据库
:切换数据库,如果不存在则创建一个(只是在内存中创建需要插入一条数据才算真正写入到磁盘)
4.db.dropDatabase()
:删除当前使用的数据库
5.db.集合名.insert(value)
:添加数据到指定的集合中
db.collection.insertOne()
插入一条数据db.collection.insertMany()
插入多条数据
6.db.集合名.find()
:从指定的集合中查找数据
7.db.createCollection(name, options)
:创建集合,name: 要创建的集合名称,options: 可选参数, 指定有关内存大小及索引的选项,db.createCollection("runoob")
8.show collections
:查看所有集合
9.db.集合名.drop()
:删除集合
更多命令操作见:https://www.runoob.com/mongodb/mongodb-create-database.html
2.4 Python操作MongoDB
https://www.runoob.com/python3/python-mongodb.html
安装pip install pymongo
连接mongodb:
import pymongo
#获取连接的对象
client = pymongo.MongoClient(
host='127.0.0.1',
port=27017,
)
#获取数据库
db = client.zhihu
#获取集合
collection = db.qa
#插入一条数据到集合中
collection.insert_one({
'username':'xiong',
'age':18
})
数据类型:
类型 | 数字 | 备注 |
---|---|---|
Double | 1 | 浮点型 |
String | 2 | 字符串,最常用,必须是有效的utf8 |
Object | 3 | 用于嵌入式的文档,即一个值为一个文档 |
Array | 4 | 数组/列表 |
Binary data | 5 | |
Undefined | 6 | 已废弃。 |
Object id | 7 | 文档ID |
Boolean | 8 | true/false |
Date | 9 | 日期或时间的UNIX时间格式 |
Null | 10 | Null值 |
Regular Expression | 11 | |
JavaScript | 13 | |
Symbol | 14 | |
JavaScript (with scope) | 15 | |
integer | 16 | 可以是32/64位,取决于服务器 |
Timestamp | 17 | 时间戳,从1970-1-1到现在的秒数 |
Min key | 255 | Query with -1 |
. | ||
Max key | 127 |
操作MongoDB的主要方法:
1.insert_one
:插入一条文档到集合中
collection.insert_one({
'username':'xiong',
'age':18
})
2.insert_many
:插入多条文档数据到集合中:
collection.insert_one({
'username':'xiong',
'age':18
},
{
'goods':'苹果',
'price':5.88
},
)
3.find_one
:查找一条文档对象:
result = collection.find_one()
result = collection.find_one({'username':'xiong'}) #按条件查找的
4.更新一条数据
collection.update_one({"username":'xiong'},{"$set":{"username":"xiaoxiong"}})
5.更新多条数据
import pymongo
myclient = pymongo.MongoClient("mongodb://localhost:27017/")
mydb = myclient["runoobdb"] #或者 myclient.runoobdb
mycol = mydb["sites"] #或者 mydb.sites
myquery = { "name": { "$regex": "^xiong" } } #所有名字以xiong开头的
newvalues = { "$set": { "xiaoxiong": "123" } }
x = mycol.update_many(myquery, newvalues)
print(x.modified_count, "文档已修改")
6.delete_one
删除一条文档对象
myquery = { "name": "Taobao" }
mycol.delete_one(myquery)
7.delete_many
删除多条文档对象
myquery = { "name": {"$regex": "^F"} }
x = mycol.delete_many(myquery)
print(x.deleted_count, "个文档已删除") #5个文档已删除
delete_many() 方法如果传入的是一个空的查询对象,则会删除集合中的所有文档:x = mycol.delete_many({})
删除集合mycol中的所有文档
使用 drop() 方法来删除一个集合:mycol.drop()