1. 程式人生 > >如何利用mysql+pyecharts儲存資料並可視化

如何利用mysql+pyecharts儲存資料並可視化

目標

爬取紅嶺創投(https://www.my089.com/)日投資發標記錄,儲存在mysql資料庫中,
並將資料視覺化以便分析.

行動

爬取資料

通過selenium+FIrefox的無頭模式將需要的資料爬取出來,程式碼實現不在贅述,詳細步驟可檢視我的上一篇圖文(如何利用Python爬取網易新聞),selenium3.11.0版本已經停止對phantomjs的支援,現在可以使用chrome和firefox的無頭模式實現該功能.
開啟無頭模式:

from selenium.webdriver.firefox.options import Options
firefox_options=webdriver.FirefoxOptions()
firefox_options.add_argument("--headless")
firefox_options.add_argument("--disable-gpu")

一個疑問:

使用ubuntu的crontab定時任務執行此爬蟲指令碼時,如果不開啟無頭模式,報錯如下:

selenium.comm.exception.WebDriverException:message:invalid argument :can't
kill an exited process

沒能理解這個報錯的原因,希望與大家一起討論.

儲存資料

資料庫這次選擇了mysql, 首先需要建立自己的資料庫,建立相應表格,這裡推薦使用 Navicat,能夠將資料庫操作圖形化.navicat需要做一些配置,網上有大量教程,建表時需要注意型別,選擇正確的型別在後續使用時會減少很多麻煩,例如:

VARCHAR和CHAR型別

varchar適用場景:

  • 字串列的最大長度比平均長度大很多
  • 字串列很少被更新
  • 使用了多位元組字符集儲存字串(如utf8中的中文和英文)

char適用場景:

  • 儲存長度近似的值(md5值,如密碼)
  • 儲存短字串
  • 儲存經常被更新的字串列

日期型別

TIMESTAMP型別:

  • 以yyyy-MM-dd HH:mm:ss格式顯示,佔用4個位元組
  • 時間範圍:1970-1-1 到 2038-01-19
    DATATIME型別:
  • 以yyyy-MM-dd HH:mm:ss格式顯示,佔用8個位元組
  • 時間範圍:1000-1-1 00:00:00至9999-12-31 23:59:59

插入資料

	db=pymysql.connect(host='localhost',user='root',password=
    'xxxx',db='hlct',charset='utf8')
    sql="INSERT INTO data_1 VALUES('" + dic['借款人'] + "','" +dic['時間']\
        + "','" + dic['借款金額'].replace(',', '')+ "','" + dic['利率'] +\
        "','" + dic['期限'] + "','" + dic['還款方式'] + "');"
	cursor =db.cursor()  #獲取操作遊標
    cursor.execute(sql)  #執行sql語句
    db.commit()          #提交到資料庫執行
    db.close()

此時,資料已經靜悄悄的待在資料庫中了 xd
在這裡插入圖片描述

利用echarts將資料視覺化作圖

最初我是在這學習的echarts基本操作 ------渲染圖表
針對這次的目標,折線圖是最好的展現資料方式.資料庫原始資料需要做出一定處理,根據具體用途處理就好.

import pyecharts_snapshot
from datetime import datetime ,date, timedelta
from pyecharts import Line
def rLine(y_rate):
    x_axis =["00", "01", "02", "03", "04", "05", "06", "07",
             "08", "09", "10" ,"11","12", "13", "14", "15", "16", "17", "18", "19",
             "20", "21","22","23"]
    aver=[];max=[];min=[]
    for y in y_rate:
        aver.append(y[0])
        max.append(y[1])
        min.append(y[2])
    line = Line("紅嶺創投利率曲線"'('+Date+')')
    line.use_theme("dark")
    line.add("最高利率", x_axis=x_axis,y_axis=max,yaxis_max=9,
             yaxis_min=8,yaxis_force_interval=0.1,
             yaxis_formatter='%')
    line.render(path='/home/lsgo18/PycharmProjects/honglingchuangtou/rate.png')
  • x_axis--------------------------------------橫軸資料
  • y_axis--------------------------------------縱軸資料
  • line.add()----------------------------新增資料作圖
  • yaxis_max--------------------設定縱軸刻度範圍
  • yaxis_force_interval--------------設定刻度精度
  • line.use_theme--------------------------主題顏色
  • line.render()------------------------------生成檔案
    在這裡插入圖片描述
    在這裡插入圖片描述

crontab定時任務

觀察了紅嶺創投往網站一段時間後,發現只能顯示近十分鐘左右的即時資料,不可能每過幾分鐘手動點選程式執行,夥伴們向我推薦了一個非常好用的指令-----crontab,crontab 是用來讓使用者在固定時間或固定間隔執行程式之用,換句話說,也就是類似使用者的時程表,並且在後臺執行,不會打擾到我們的學習和工作.

  • 開啟crontab:
sudo vim /etc/cronta
  • 介面如下(通過vim開啟)

在這裡插入圖片描述

基本格式

*   *   *   *   *  command 

分  時  日  月  周  命令
第1列表示分鐘1~59 每分鐘用*或者 */1表示
第2列表示小時1~23(0表示0點)
第3列表示日期1~31
第4列表示月份1~12
第5列標識號星期0~6(0表示星期天)
第6列要執行的命令
通常需要將python環境絕對路徑,程式絕對路徑寫入命令,保證能正常執行,如果crontab沒有執行,大概率的原因就在此,圖中倒數第四行黃色部分就是執行爬蟲的指令,最後/auto.log部分是輸出日誌,將每一次執行的結果寫進日誌檔案,以便檢查執行情況.

smtplib傳送郵件

每天處理資料做出折線圖後,將圖片傳送給團隊老大,smtplib是不錯的選擇,結合crontab就能每天自動執行,成就感超強.

import smtplib
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.utils import parseaddr, formataddr
    def send(self):
        from_addr = "[email protected]"  # 發件人 Email 地址和口令
        password = "xxxxxxx"
        smtp_server = "smtp.qq.com"  # SMTP 伺服器地址
        to_addr = "[email protected]"  # 收件人地址

        # 郵件頭
        msg = MIMEMultipart()#代表郵件本身
        msg['From'] = self._format_addr('lsgo <%s>' % from_addr)
        msg['To'] = self._format_addr('lsgo <%s>' % to_addr)
        msg['Subject'] = Header('紅嶺創投', 'utf-8').encode()  # 標題

        # 郵件正文
        # msg.attach(MIMEText('……', 'plain', 'utf-8'))

        # 新增附件
        self.addfile(msg)

        try:
            server = smtplib.SMTP(smtp_server, 25)
            server.set_debuglevel(1)
            server.starttls()
            server.login(from_addr, password)
            server.sendmail(from_addr, [to_addr], msg.as_string())
            server.quit()
            print("郵件傳送成功")
        except smtplib.SMTPException:
            self.send()
            print("Error: 傳送郵件失敗,正在重試!")

在郵件中新增附件:

    def _format_addr(self,s):
        name, addr=parseaddr(s)
        return formataddr((Header(name,'utf-8').encode(),addr))
    def _getfile(self):
        file='/home/lsgo18/PycharmProjects/honglingchuangtou/'
        return [file+'money.png',file+'rate.png']
    def addfile(self,msg):
        files=self._getfile()
        #設定附件的MIME和檔名
        attr1 = MIMEBase('image', 'png', filename='file.png')
        #必要的頭資訊
        attr1.add_header('Content-Disposition', 'attachment',
                         filename=files[0][-9:])
        attr1.add_header('Content-ID', '<0>')
        attr1.add_header('X-Attachment-Id', '0')
        #讀取附件內容
        attr1.set_payload(open(files[0], 'rb+').read())
        #用Base64編碼
        encoders.encode_base64(attr1)
        #新增到MIMEMuptipart
        msg.attach(attr1)

        # 附件2
        attr2 = MIMEBase('image', 'png', filename='file.png')
        attr2.add_header('Content-Disposition', 'attachment',
                         filename=files[1][-8:])
        attr2.add_header('Content-ID', '<0>')
        attr2.add_header('X-Attachment-Id', '0')
        attr2.set_payload(open(files[1], 'rb').read())
        encoders.encode_base64(attr2)
        msg.attach(attr2)