业务场景:
1.写一个接口,用于接收爬虫提交的数据。
2.将数据保存到mysql数据库已经创建好的用户表
3.如果某个用户的数据已经存在,则更新数据(注意不是覆盖,数据库有多个字段,并不是每一次接收的数据都包含所有字段,所以需要仅更新有数据的字段)
分析:
接口可以使用flask的注解完成,非常简单
需要操作数据库,那么首先就应该建立数据库连接
然后通过链接映射表的模型,并且将这个模型实例化为一个对象
最后使用这个对象的方法进行数据库操作
使用sqlalchemy可以完美实现,没有安装的可以使用
pip install sqlalchemy 下载
ok,思路捋清楚了。直接开干!
先提供一个接口用于接收爬虫数据
from flask import Flask, request
web = Flask(__name__)
@web.route('/api/user/save', methods=['post'])
def get_user():
return_dict = {'return_code': '200', 'return_info': '处理成功', 'result': False}
if request.args is None:
return_dict['return_code'] = '5004'
return_dict['return_info'] = '请求参数为空'
json_data = request.get_json()
# 此处调用数据库的操作方法(增删改查)
return return_dict
一、建立与mysql数据库的链接
创建数据库链接,写法固定。
依次填入数据库的账号密码ip地址以及使用的库名即可,默认端口号3306,如果修改过,则需要填写端口号
# 导入需要引用的包
from sqlalchemy import create_engine, Table
engine = create_engine('mysql+pymysql://数据库账号:数据库密码@localhost/使用的库')
二、数据连接会话,定义模型类继承父类
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session
session = sessionmaker(bind=engine) # 类似于游标
dbsession = scoped_session(session)
Base = declarative_base() # 定义一个给其他类继承的父类
md = MetaData(bind=engine) # 元数据: 主要是指数据库表结构、关联等信息
# 定义模型类
class User(Base):
__table__ = Table('users', md, autoload=True) # users即为表名
三、使用实例化模型对象的方法操作数据库
if __name__ == '__main__':
result = dbsession.query(User).filter(User.id == 1).all()
print(result)
print(result[0].user_name)
for row in result:
print(row.user_name, row.email)
运行结果,表中的数据被成功返回
但是我们需要动态的接收数据以及自动更新的操作,ok,先执行查询操作
result_detail = dbsession.query(User).filter_by(id=json_data.get('id'))
根据查询结果判断进行哪种操作
if not result_detail or not result_detail.first():
# 无则插入
save_date = User(**dict(json_data)) # 动态传参
dbsession.add(save_date)
dbsession.commit() # 修改类操作需要手动提交
else:
# 有则更新
result_detail.update(json_data) # 动态更新
dbsession.commit()
然后开启flask的服务
if __name__ == '__main__':
web.run(port=10000, debug=True, host='0.0.0.0', threaded=True)
运行代码
ok,爬虫只需要使用post请求127.0.0.1:10000/api/user/save,传递json格式的数据,就可以完成对数据库的新增和更新,而且完全不需要写sql语句,非常的nice~
这里仅提供思路,还有很多不足的地方,比如可以把一些方法封装成公共方法。
先贴上整体代码,代码原创,可以直接使用。
不过这并不是一个好的写法。
仅供参考,希望对大家能有一些帮助吧
from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session
from flask import Flask, request
web = Flask(__name__)
# 建立与mysql数据库的链接
engine = create_engine('mysql+pymysql://root:123456@localhost/pythontest')
# 定义模型类继承父类及数据连接会话
DBsession = sessionmaker(bind=engine) # 类似于游标
dbsession = scoped_session(DBsession)
Base = declarative_base() # 定义一个给其他类继承的父类
md = MetaData(bind=engine) # 元数据: 主要是指数据库表结构、关联等信息
# 定义模型类
class User(Base): # 自动加载表结构
__table__ = Table('users', md, autoload=True)
@web.route('/api/user/save', methods=['post'])
def get_user():
return_dict = {'return_code': '200', 'return_info': '处理成功', 'result': False}
if request.args is None:
return_dict['return_code'] = '5004'
return_dict['return_info'] = '请求参数为空'
json_data = request.get_json()
result_detail = dbsession.query(User).filter_by(id=json_data.get('id'))
# 此处调用数据库的操作方法(增删改查)
if not result_detail or not result_detail.first():
# 无则插入
save_date = User(**dict(json_data)) # 动态传参
dbsession.add(save_date)
dbsession.commit() # 修改类操作需要手动提交
else:
# 有则更新
result_detail.update(json_data) # 动态更新
dbsession.commit()
return return_dict
if __name__ == '__main__':
web.run(port=10000, debug=True, host='0.0.0.0', threaded=True)