一句话归纳本文:html
内容较多,建议先mark后看,讲解了一波MySQL安装,基本操做,语法速成,DataGrip使用, 连接远程数据库问题,爬取Gank.io API接口,存储到数据,还有遇到的三个问题。前端
引言:python
失踪人口回归,工种从开发变成了打杂后,供本身学习和写文章的时间也没之前充裕了, 大部分时间都在处理一些杂事,唉...在学习Python之后,要处理什么问题,我第一个想起 的都是它。好比前段时间在玩的微信小游戏 "萌犬变变变",前身是网页版的,只是最近迁移 到了小程序上。mysql
游戏大概玩法以下:android
游戏的卖点:经过合成解锁各类各样有趣的狗子。ios
这样的小游戏看上去并不复杂,可是吸金数毫不可小觑,像我这种贫民玩家也 氪了30买月卡,而后排名5W开外:git
站在我的视角分析下这个游戏火的缘由:github
以上就是我的的一些愚见,都差点忘记这个是个开发仔了,说回程序把,关于这个程序, 以前想到用Python作的两件事:sql
自动点箱子:数据库
裁剪快递箱的顶部小角,经过adb命令每隔一秒截屏,利用opencv进行模板匹配,获取图片 中顶部小角的坐标数组,adb命令模拟点击;
轮盘自动点击:
先把轮盘的每种结果的执行流程都捋下,点哪里,跳那里,是否设置延时等,接着利用 adb截图,利用ocr图片识别关键字,好比'分享'自动关掉,'偷窃'点肯定等。
由于以为没什么意思,都不玩了,就没去整程序了,大概思路就是上面这样。 说这么多,只是想说明Python,真香。 嗯,扯得有点远了,前面的章节学爬虫,抓取到的数据存过txt,Excel和csv, 这三种对于非开发者来讲挺友好的,对于开发仔来讲,不存下数据库就说不过了。
数据库又分为两种:关系型数据库 和 非关系型数据库, 前者是基于关系模型的数据库,多个二维表经过表与表间的关联关系来组成一个数据库; 后者NoSQL是基于键值对的,数据间没有耦合性,很是高效;
本节使用的就是关系型数据库里的MySQL,相信不少童鞋都知道这个东东了, 编写一波gank.io的爬虫,爬取全部数据存起来,后续用Flask本身写接口玩玩~
环境:阿里云服务器 Ubuntu 16.04
依次键入下述命令安装MySQL:
# 安装MySQL服务,输入Y后,如图会让你输入密码,重复输入确认
sudo apt-get install mysql-server
# 安装MySQL客户端
sudo apt-get install mysql-client
# 安装libmysqlclient,输入Y
sudo apt-get install libmysqlclient-dev
复制代码
安装完后键入下述命令验证是否安装成功
sudo netstat -tap | grep mysql
复制代码
# 回车后,须要输入在安装那里设置的密码
mysql -u root -p
复制代码
show databases;
复制代码
use 数据库名
复制代码
show tables;
复制代码
# 开始服务
/etc/init.d/mysql stop
# 中止服务
/etc/init.d/mysql start
# 重启服务
/etc/init.d/mysql restart
复制代码
基本的操做就这些,对于数据库的相关操做,再进入数据库 后就能够经过数据库语句完成相关操做了。
# 整型(取值范围若是加了unsigned,则最大值翻倍)
TINYINT(m) 1个字节 范围(-128~127);
SMALLINT(m) 2个字节 范围(-32768~32767);
MEDIUMINT(m) 3个字节 范围(-8388608~8388607);
INT(m) 4个字节 范围(-2147483648~2147483647);
BIGINT(m) 8个字节 范围(+-9.22*10的18次方);
# 浮点型
FLOAT(m,d) 单精度浮点型 8位精度(4字节) m总个数,d小数位;
DOUBLE(m,d) 双精度浮点型 16位精度(8字节) m总个数,d小数位;
# 字符串
# 1.char(n)若存入字符小于n,以空格补齐后面,查询时再将空格去掉,因此char类型存储
# 的字符串末尾不能有空格。
# 2.char(n)固定长度,无论存几个字符,都占用n个字节
# 3.varchar(n)可变长度,存入的实际字符数+1个字节(n<=255)或2个字节(n>255)
# 4.char类型的字符串检索速度要比varchar类型的快
# 5.text类型不能有默认值,varchar查询速度快于text
CHAR(n) 固定长度,最多255个字符;
VARCHAR(n) 可变长度,最多65535个字符;
TINYTEXT 可变长度,最多255个字符;
TEXT 可变长度,最多65535个字符;
MEDIUMTEXT 可变长度,最多2的24次方-1个字符;
LONGTEXT 可变长度,最多2的32次方-1个字符;
# 二进制数据
_BLOB 以二进制方式存储,不分大小写,不用指定字符集,只能总体读出;
_TEXT 以文本方式存储,英文存储区分大小写,能够指定字符集;
# 日期时间类型
DATE 日期
TIME 时间
DATETIME 日期时间
TIMESTAMP 自动存储记录修改时间
复制代码
NULL 数据列可包含NULL值
NOT NULL 数据列不容许包含NULL值
DEFAULT 默认值
PRIMARY KEY 主键
AUTO_INCREMENT 自动递增,适用于整数类型
UNSIGNED 无符号
CHARACTER SET name 指定一个字符集
复制代码
# 建库
CREATE DATABASE 数据库名;
# 删库(删除数据库没法恢复!!!),删除不存在的库会报
# database doesn't exist的错误,故先用IF EXISTS判断下。
DROP DATABASE IF EXISTS 数据库名;
复制代码
# 建表,好比
CREATE TABLE test
(
_id VARCHAR(50) NOT NULL PRIMARY KEY,
dsec TEXT NULL,
images TEXT NULL,
url TEXT NULL,
type VARCHAR(50) DEFAULT '' NULL
);
# 清空表数据,总体删除,速度较快,会重置Identity(标识列、自增字段)
TRUNCATE 表名
# 删除表中数据,逐条删除,速度较慢,不会重置Identity,配合WHERE关键字能够删除部分
DELETE FROM 表名
# 删表
DROP TABLE 表名
# 重命名表
ALTER TABLE 原表名 RENAME 新表名;
RENAME TABLE 原表名 TO 新表名;
# 增长列
ALTER TABLE 表名 Add column 新字段 数据类型 AFTER 在哪一个字段后添加
# 删除列
ALTER TABLE 表名 DROP 字段名;
# 重命名列/数据类型
ALTER TABLE 表名 CHANGE 原列名 新列名 数据类型;
# 增长主键
ALTER TABLE 表名 ADD PRIMARY KEY (主键名);
# 删除主键
ALTER TABLE 表名 DROP PRIMARY KEY;
# 添加惟一索引
ALTER TABLE 表名 ADD UNIQUE 索引名 (列名);
# 添加普通索引
ALTER TABLE 表名 ADD INDEX 索引名 (列名);
# 删除索引
ALTER TABLE 表名 DROP INDEX 索引名;
# 把表默认的字符集和全部字符列(CHAR, VARCHAR, TEXT)改成新的字符集:
ALTER TABLE 表名 CONVERT TO CHARACTER SET utf8;
# 修改表某一列的编码
ALTER TABLE 表名 CHANGE 列名 varchar(255) CHARACTER SET utf8;
# 仅仅改变一个表的默认字符集
ALTER TABLE 表名 DEFAULT CHARACTER SET utf8;
复制代码
关键词就上面几个,经过一个完整示例来快速上手MySQL
# 建新数据库
CREATE DATABASE test
# 新建一个表person,字段有(自增id,名字,年龄,性别)
CREATE TABLE person(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(30) NOT NULL DEFAULT '',
age INT,
sex CHAR(2)
);
# 往表中插入5条数据
INSERT INTO person (name, age, sex) VALUES ('小明', 8, '男');
INSERT INTO person (name, age, sex) VALUES ('小红', 14, '女');
INSERT INTO person (name, age, sex) VALUES ('小白', 4, '男');
INSERT INTO person (name, age, sex) VALUES ('小宝', 6, '男');
INSERT INTO person (name, age, sex) VALUES ('小莉', 16, '女');
# 更新表中数据(不添加WHERE子句筛选,更新的会是整个表的某列)
UPDATE person SET age = 10, sex = '女' WHERE name = '小明';
# 往表里插入数据,若是某自动已存在则更新数据
INSERT INTO person (id,name, age, sex) VALUES (1,'小明', 20, '男') ON DUPLICATE KEY UPDATE age = '20';
# 删除特定记录
DELETE FROM person WHERE age < 10;
# 查询数据
SELECT * FROM person; #查询全部数据
SELECT name,age FROM person; #查询特定列
SELECT name AS '姓名',age AS '年龄'FROM person; #为检索出来的列设置别名
SELECT name FROM person WHERE age > 15 AND age <=20; # 条件查询
SELECT name FROM person WHERE age BETWEEN 15 AND 20; # 范围查询
# 数据求总和,平均值,最大,最小值,记录数
SELECT SUM(age),AVG(age), MAX(age),MIN(age), COUNT(age) FROM person;
# 查询的时候排序:升序(ASC),降序(DESC)
SELECT * FROM person ORDER BY age ASC;
复制代码
BEGIN # 开始一个事务
COMMIT # 事务确认
ROLLBACK # 事务回滚
复制代码
关于MySQL的基本语法就到这里,本节够用了,其余的后续用到再讲~
通常来说数据库操做不多写命令,基本都会依赖一些图形化工具来提升效率, 关于MySQL的图形化工具,网上貌似挺多的,大部分用的貌似是Navicat for mysql (我司后台用的就是这个),不过我仍是选择了idea全家桶里的DataGrip,没有为何...
依次点击 New -> DataSource -> MySQL 如图依次配置下Host,Database,User,Password,而后Test Connection测试是否 链接成功,成功的话点击Ok粗体文本。
本地是这样,若是你的数据库不在本机而是在云服务器上,就要另外折腾了。
mysql默认是不容许远程访问的,笔者用的是阿里云的服务器,在链接远程仓库 的时候也遇到一些问题,顺带记录下,方便后来者。(下述操做发生在服务器上已经安装了mysql环境后!)
Step 1:云服务器开启安全组里的3306端口
Step 2:中止mysql服务
/etc/init.d/mysql stop
复制代码
Step 3:修改my.cnf文件,注释掉bind-address = 127.0.0.1,键入sq保存退出;
vim /etc/mysql/my.cnf
复制代码
Step 4:启动mysql服务
/etc/init.d/mysql start
复制代码
Step 5:输入下述命令查看当前3306端口的状态
netstat -an|grep 3306
复制代码
Step 6:修改访问权限
mysql -u root -p # 用户登陆
use mysql; # 选中mysql数据库
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '密码' WITH GRANT OPTION; # 受权
FLUSH PRIVILEGES; # 更新权限
EXIT # 退出mysql
复制代码
PS:上面设置的结果是全部ip都能访问数据库,如需指定特定ip才能访问的话, 能够把**'@'%
**改为特定ip。还有这里用的是root帐户,你能够经过下述命令 建立一个新的用户,而后用这个用户进行访问,能够由此作一些权限控制操做。
CREATE USER 新用户 IDENTIFIED BY '密码';
GRANT ALL PRIVILEGES ON *.* TO '新用户'@'%' IDENTIFIED BY '密码' WITH GRANT OPTION; # 受权
FLUSH PRIVILEGES;
复制代码
Step 7:链接远程mysql
这里用的是DataGrip进行链接,右键,new -> Data Source -> MySQL 这里要先配置SSH或者SSL,端口默认是22
再接着配置远程数据库相关,端口3306
配置完后点击Test Connection成功后,点击OK便可。
中途若是出现了异常,好比SSH Auth ERROR可能就是SSH密码错误; 除此以外的MySQL异常或问题可自行查阅:
云服务器 ECS Linux MySQL 没法远程链接问题常见错误及解决办法
准备得差很少了,接着来编写爬虫程序了,由于代码家已经提供了 API接口,这里就不一个个网页爬取了,直接抓接口。
分析下接口: 有六种不一样类型的数据:Android, iOS, 休息视频, 福利, 拓展资源, 前端, 瞎推荐, App 而后每一个接口取五个须要的字段:_id, dsec, images, url, type
因此要作的第一件事:循环建表
接着定义一个Gank类
再接着定义一个网数据库里插入数据的函数(参数是一个gank对象列表):
再定义一个爬取接口数据的方法
接着main函数调用下,
运行等待程序抓取完成,完成后能够直接代码查询:
或者直接经过DataGrip查看:
接口返回的数据里有些字段好比标题和URL巨长,一开始用了varchar(250)的, 报错提示某列什么错误,后来就全改为TEXT了。
由于有些标题里包含特殊符号和表情,在插入数据的时候报错,大概是这样的: Incorrect string value: '\xF0\x9F...' for column 'XXX' at row 1
缘由是:UTF-8编码有多是两个、三个、四个字节。Emoji表情或者某些特殊字符是4个字节, 而Mysql的utf8编码最多3个字节,因此数据插不进去。MySQL在5.5.3版本以后增长了 utf8mb4的编码,专门用来兼容四字节的unicode。理论上将字符集修改成utf8mb4 不会对已有的utf8编码读取产生任何问题。官方解释:
10.9.1 The utf8mb4 Character Set (4-Byte UTF-8 Unicode Encoding)
解决过程:
Step 1:打开终端,键入:locale my.cnf 定位到文件位置(window下是my.ini):
Step 2:vim etc/mysql/my.cnf 追加下述内容,wq保存:
[mysqld]
character-set-server=utf8mb4
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
复制代码
Step 3:重启MySQL服务器
Step 4:进入mysql,而后键入**show variables like '%character%';**确认设置是否生效
Step 5:更改数据库,表,列编码
ALTER DATABASE 数据库名 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
ALTER TABLE 表名 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
ALTER TABLE 表名 CHANGE 列名 VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
复制代码
到此问题就解决了,此时打开数据库表能够看到对应记录已存入,不过是显示成问号 的形式,读取到数据显示到支持emoji表情的页面上就能够了,好比手机。
打开一个表看到里面的数据只有500条,试了几回仍是这样,觉得DataGrip只能存储500条数据, 后来发现这里有个501+,分页,so,点击右面那个相似于播放的按钮就能够切换区间了!
开头扯了一下犊子,接着详细讲解了一波MySQL相关的东西,接着写了一波简单爬虫 爬取gank.io,存储数据的方式又新增了数据库一种~
参考文献:
附:最终代码(均可以在:github.com/coder-pig/R… 找到):
# 抓取Gank.io全部文章的爬虫
import pymysql
import requests as rq
import urllib
import coderpig_n as cn
gank_api = "http://gank.io/api/data/"
# 各类分类的表名:Android,iOS,休息视频,福利,拓展资源,前端,瞎推荐,App
category_list = ["android", "ios", "video", "meizi", "other", "fed", "random", "app"]
type_list = ["Android", "iOS", "休息视频", "福利", "拓展资源", "前端", "瞎推荐", "App"]
column_list = ('_id', 'dsec', 'images', 'url', 'type')
def init_db():
db = pymysql.connect(host='localhost', user='root', password='zpj12345', port=3306, db='gank', charset="utf8")
cursor = db.cursor()
try:
for category in category_list:
sql = "CREATE TABLE IF NOT EXISTS %s (" \
"_id VARCHAR(50) NOT NULL," \
"dsec TEXT," \
"images TEXT," \
"url TEXT," \
"type VARCHAR(50) DEFAULT ''," \
"PRIMARY KEY (_id))" % category
cursor.execute(sql)
db.close()
except:
pass
class Gank:
_id = dsec = images = url = type = ''
def __init__(self, _id, dsec, images, url, type):
self._id = _id
self.dsec = dsec
self.images = images
self.url = url
self.type = type
# 以元组的方式返回值
def to_value_tuple(self):
return self._id, self.dsec, self.images, self.url, self.type
def insert_db(gank_list):
db = pymysql.connect(host='localhost', user='root', password='zpj12345', port=3306, db='gank', charset="utf8")
cursor = db.cursor()
try:
for data in gank_list:
if data.type in type_list:
category = category_list[type_list.index(data.type)]
data_tuple = data.to_value_tuple()
sql = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=category,
keys=','.join(column_list),
values=','.join(['%s'] * len(data_tuple)))
cursor.execute(sql, data_tuple)
print(data_tuple)
db.commit()
except Exception as e:
print(str(e))
db.rollback()
db.close()
def spider_data(pos):
count = 1
while True:
resp = rq.get(gank_api + urllib.parse.quote(type_list[pos]) + "/50/" + str(count), proxies=cn.get_proxy_ip())
resp_json = resp.json()
print(resp.url)
if resp.status_code == 200 and len(resp_json['results']) != 0:
json_list = []
for result in resp_json['results']:
images = result.get('images')
if images is None:
images = ''
else:
images = images[0]
gank = Gank(result['_id'], result['desc'], images, result.get('url', ''),
result['type'])
json_list.append(gank)
insert_db(json_list)
else:
break
count += 1
if __name__ == '__main__':
init_db()
for i in range(0, len(type_list)):
spider_data(i)
db = pymysql.connect(host='localhost', user='root', password='zpj12345', port=3306, db='gank', charset="utf8")
cursor = db.cursor()
cursor.execute('SELECT * FROM android')
print(cursor.rowcount)
results = cursor.fetchall()
for result in results:
print(result)
cursor.close()
复制代码
来啊,Py交易啊
想加群一块儿学习Py的能够加下,智障机器人小Pig,验证信息里包含: Python,python,py,Py,加群,交易,屁眼 中的一个关键词便可经过;
验证经过后回复 加群 便可得到加群连接(不要把机器人玩坏了!!!)~~~ 欢迎各类像我同样的Py初学者,Py大神加入,一块儿愉快地交流学♂习,van♂转py。