<p>相隔兩個(gè)月句葵,爬蟲(chóng)任務(wù)完成了。上次說(shuō)道(利用Python對(duì)天貓店鋪銷(xiāo)售進(jìn)行分析.上)兢仰,后續(xù)要完成四個(gè)功能乍丈,包括:</p>
- 每天晚上對(duì)一天采集的數(shù)據(jù)進(jìn)行分析,分析出今天的最佳銷(xiāo)量把将;
- 通過(guò)銷(xiāo)量和單價(jià)計(jì)算每日的銷(xiāo)售額轻专;
- 將上面的內(nèi)容統(tǒng)一生成pdf報(bào)表;
- 將報(bào)表發(fā)到郵箱中察蹲;
<p>在上一個(gè)任務(wù)完成之后请垛,任務(wù)的最后是通過(guò)crontab設(shè)置每天8點(diǎn),13點(diǎn),18點(diǎn),23點(diǎn),定時(shí)采集任務(wù)洽议,而該篇內(nèi)容的目的就是在每天23點(diǎn)最后一次任務(wù)完成之后宗收,對(duì)該天采集的數(shù)據(jù)進(jìn)行處理,時(shí)間設(shè)定在23點(diǎn)30分亚兄,也是采用crontab來(lái)定時(shí)開(kāi)啟混稽。</p>
計(jì)算最佳銷(xiāo)量以及計(jì)算銷(xiāo)售額
<p>這個(gè)只要通過(guò)SQLite將每天收集的數(shù)據(jù)重新提取出來(lái),由于我們的當(dāng)天的銷(xiāo)售數(shù)據(jù)是收集在SCOUNT表格中审胚,而數(shù)據(jù)的列名稱(chēng)是依據(jù)時(shí)間來(lái)命名匈勋,為了獲得當(dāng)天四個(gè)時(shí)間點(diǎn)采集的銷(xiāo)售數(shù)據(jù),需要先獲得列名稱(chēng)菲盾。</p>
<p>在SQLite里面颓影,可以通過(guò)Pragma獲得所有的列名稱(chēng)信息,Pragma有兩個(gè)功能懒鉴,包括更改內(nèi)部操作以及獲得表格固有數(shù)據(jù)诡挂,通過(guò)其中的table_info碎浇,既可以獲得列名稱(chēng)信息,所有列名稱(chēng)信息獲得后璃俗,通過(guò)list comprehensions(這個(gè)實(shí)在不知道怎么翻譯)奴璃,可以獲得今天的新生成的4個(gè)銷(xiāo)售數(shù)據(jù)列:</p>
def get_today_columns(c, today):
c.execute("PRAGMA table_info(SCOUNT);")
column_list = c.fetchall()
return ["[" + column[1] + "]" for column in column_list if today in column[1]]
<p>然后就是獲得進(jìn)行的銷(xiāo)售數(shù)據(jù),由于每個(gè)SKU一天將采集四次數(shù)據(jù)城豁,并且收集的SKU有下架的可能苟穆,SKU列表中的不是每個(gè)SKU都有可能被采集,所以對(duì)采集出來(lái)需要的數(shù)據(jù)需要dropna唱星,并且需要將SKU信息表格和銷(xiāo)售數(shù)據(jù)表格通過(guò)merge函數(shù)合并雳旅,形成我們需要的data。每個(gè)SKU在每個(gè)時(shí)刻采集的數(shù)據(jù)會(huì)出現(xiàn)波動(dòng)间聊,銷(xiāo)量數(shù)據(jù)并不是一個(gè)連續(xù)增長(zhǎng)的過(guò)程攒盈,因此為了求得當(dāng)天的銷(xiāo)量,可取一天中最大數(shù)和最小數(shù)差值哎榴。</p>
def today_sells(today_columns, conn):
query_data = "SELECT scountskuid,%s, %s, %s, %s FROM SCOUNT;" % (today_columns[0],today_columns[1],today_columns[2],today_columns[3])
data = pd.read_sql(query_data, conn, index_col="scountskuid")
data.dropna(axis= 0 , how='all', inplace=True)
query_name = "SELECT skuid, name FROM UB"
name = pd.read_sql(query_name, conn, index_col="skuid")
data = pd.merge(name, data, how = 'inner', left_index=True, right_index=True)
data['sells'] = data.max(axis=1, numeric_only=True)-data.min(axis=1, numeric_only=True)
return data[['name', 'sells']]
<p>生成銷(xiāo)售額的方法類(lèi)似型豁,就不在這里列出。</p>
生成PDF報(bào)表
<p>生成PDF尚蝌,這是當(dāng)時(shí)的一個(gè)設(shè)想迎变,后來(lái)參考這篇教程做出來(lái)了(Practical Business Python 是個(gè)好網(wǎng)站,推薦)飘言,原理是通過(guò)DataFrame轉(zhuǎn)化為HTML衣形,再將HTML轉(zhuǎn)化為PDF。但是寫(xiě)郵件模塊的時(shí)候热凹,發(fā)現(xiàn)郵件可以?xún)?nèi)嵌HTML泵喘,因此就沒(méi)有必要專(zhuān)門(mén)生成PDF,再通過(guò)郵件以附件的形式發(fā)送了般妙。但在這里,還是先梳理下整個(gè)流程:</p>
<p>采用Jinja2生成PDF相速,首先需要生成一個(gè)模板碟渺,模板里面需設(shè)定好HTML的樣式,這是參考教程寫(xiě)出的一個(gè)HTML的樣式:</p>
<!DOCTYPE html>
<html>
<head lang="zh">
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
<h2>{{ table_title }}</h2>
{{ data_table }}
</body>
</html>
<p>完成后突诬,再將DataFrame通過(guò)to_html函數(shù)轉(zhuǎn)化為HTML并填入到樣式中苫拍。</p>
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('myreport.html')
template_vars = {'title': today+'天貓銷(xiāo)售',
'table_title': today,
'data_table': data.to_html()}
html_out = template.render(template_vars)
<p>最后生成PDF,只加入一個(gè)模塊喝一句話(huà)就可以了旺隙。weasyprint這個(gè)模塊是專(zhuān)門(mén)用于將HTML或者CSS轉(zhuǎn)化為PDF:</p>
from weasyprint import HTML
HTML(string = html_out).write_pdf("my_report.pdf")
發(fā)送郵件
<p>python里面有專(zhuān)門(mén)的發(fā)送郵件模塊绒极,email模塊。郵件的模塊包括兩部分蔬捷,一部分是郵件正文模塊垄提,一部分郵件發(fā)送模塊:</p>
<p>郵件正文模塊榔袋,通過(guò)MIMEText完成。在email模塊里面有專(zhuān)門(mén)的(MIME, Multipurpose Internet Mail Extensions铡俐,多用途互聯(lián)網(wǎng)郵件擴(kuò)展)模塊凰兑,用來(lái)生成對(duì)應(yīng)的郵件正文類(lèi)型。在這里先采用文本模塊MIMEText做個(gè)示范:</p>
from email.mime.text import MIMEText
# me == 發(fā)送地址
# you == 接受地址
msg = MIMEText(html_out, 'html')
msg['Subject'] = " %s 銷(xiāo)售日?qǐng)?bào)" % today
msg['From'] = me
msg['To'] = you
<p>然后就是發(fā)送郵件了审丘,需要經(jīng)過(guò)stmplib模塊吏够,下面詳細(xì)講講。發(fā)送郵件首先需要設(shè)置smtp(Simple Mail Transfer Protocol,簡(jiǎn)單郵件傳輸協(xié)議)的地址和端口滩报,然后部分郵箱需要采用TTS加密協(xié)議的時(shí)候锅知,則需要使用starttts()函數(shù)。然后對(duì)應(yīng)的是登陸的用戶(hù)名的密碼脓钾,再將上面編寫(xiě)的msg發(fā)出去类嗤,最后quit即可。</p>
#smtp_address:發(fā)送收件的smtp地址讨永;
#smtp_port:發(fā)送收件的smtp地址對(duì)應(yīng)的端口瞪浸,如果采用TTS加密的話(huà),一定要注意端口的設(shè)置沉噩;
#login_username:郵箱登陸的用戶(hù)名捺宗;
#login_password:郵箱登陸的密碼;
import smtplib
try:
s = smtplib.SMTP(smtp_address, smtp_port)
s.starttls()
s.login(login_username, login_password)
s.send_message(msg)
s.quit()
print(today + "發(fā)送成功川蒙!")
except smtplib.SMTPException:
print("Error: 無(wú)法發(fā)送郵件")
結(jié)語(yǔ)
<p>總結(jié)下蚜厉,之前設(shè)定的任務(wù)大體完成了。但是還是有很多可以深化的內(nèi)容畜眨,例如前面采用DataFrame的時(shí)候昼牛,沒(méi)有對(duì)數(shù)據(jù)進(jìn)行可視化,HTML的模板還可以再美化下康聂,另外假如引入了數(shù)據(jù)可視化贰健,要怎么將可視化的圖片嵌入到郵件中。郵件登陸那部分恬汁,部分郵箱沒(méi)有辦法采用這個(gè)方法發(fā)出(需要再考慮smtp設(shè)置)伶椿。</p>
<p>上面這些問(wèn)題,后續(xù)會(huì)繼續(xù)以小項(xiàng)目的形式進(jìn)行研究氓侧。后面還可以進(jìn)行平臺(tái)之間的銷(xiāo)售情況對(duì)比等等脊另,總而言之,該項(xiàng)目還是有很大的擴(kuò)張空間的约巷。嘛偎痛,這一次就先這樣結(jié)束吧。</p>