一句話歸納本文: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。