<p>相隔两个月,爬虫任务完成了。上次说道(利用Python对天猫店铺销售进行分析.上),后续要完成四个功能,包括:</p>
- 每天晚上对一天采集的数据进行分析,分析出今天的最佳销量;
- 通过销量和单价计算每日的销售额;
- 将上面的内容统一生成pdf报表;
- 将报表发到邮箱中;
<p>在上一个任务完成之后,任务的最后是通过crontab设置每天8点,13点,18点,23点,定时采集任务,而该篇内容的目的就是在每天23点最后一次任务完成之后,对该天采集的数据进行处理,时间设定在23点30分,也是采用crontab来定时开启。</p>
计算最佳销量以及计算销售额
<p>这个只要通过SQLite将每天收集的数据重新提取出来,由于我们的当天的销售数据是收集在SCOUNT表格中,而数据的列名称是依据时间来命名,为了获得当天四个时间点采集的销售数据,需要先获得列名称。</p>
<p>在SQLite里面,可以通过Pragma获得所有的列名称信息,Pragma有两个功能,包括更改内部操作以及获得表格固有数据,通过其中的table_info,既可以获得列名称信息,所有列名称信息获得后,通过list comprehensions(这个实在不知道怎么翻译),可以获得今天的新生成的4个销售数据列:</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>然后就是获得进行的销售数据,由于每个SKU一天将采集四次数据,并且收集的SKU有下架的可能,SKU列表中的不是每个SKU都有可能被采集,所以对采集出来需要的数据需要dropna,并且需要将SKU信息表格和销售数据表格通过merge函数合并,形成我们需要的data。每个SKU在每个时刻采集的数据会出现波动,销量数据并不是一个连续增长的过程,因此为了求得当天的销量,可取一天中最大数和最小数差值。</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>生成销售额的方法类似,就不在这里列出。</p>
生成PDF报表
<p>生成PDF,这是当时的一个设想,后来参考这篇教程做出来了(Practical Business Python 是个好网站,推荐),原理是通过DataFrame转化为HTML,再将HTML转化为PDF。但是写邮件模块的时候,发现邮件可以内嵌HTML,因此就没有必要专门生成PDF,再通过邮件以附件的形式发送了。但在这里,还是先梳理下整个流程:</p>
<p>采用Jinja2生成PDF,首先需要生成一个模板,模板里面需设定好HTML的样式,这是参考教程写出的一个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通过to_html函数转化为HTML并填入到样式中。</p>
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template('myreport.html')
template_vars = {'title': today+'天猫销售',
'table_title': today,
'data_table': data.to_html()}
html_out = template.render(template_vars)
<p>最后生成PDF,只加入一个模块喝一句话就可以了。weasyprint这个模块是专门用于将HTML或者CSS转化为PDF:</p>
from weasyprint import HTML
HTML(string = html_out).write_pdf("my_report.pdf")
发送邮件
<p>python里面有专门的发送邮件模块,email模块。邮件的模块包括两部分,一部分是邮件正文模块,一部分邮件发送模块:</p>
<p>邮件正文模块,通过MIMEText完成。在email模块里面有专门的(MIME, Multipurpose Internet Mail Extensions,多用途互联网邮件扩展)模块,用来生成对应的邮件正文类型。在这里先采用文本模块MIMEText做个示范:</p>
from email.mime.text import MIMEText
# me == 发送地址
# you == 接受地址
msg = MIMEText(html_out, 'html')
msg['Subject'] = " %s 销售日报" % today
msg['From'] = me
msg['To'] = you
<p>然后就是发送邮件了,需要经过stmplib模块,下面详细讲讲。发送邮件首先需要设置smtp(Simple Mail Transfer Protocol,简单邮件传输协议)的地址和端口,然后部分邮箱需要采用TTS加密协议的时候,则需要使用starttts()函数。然后对应的是登陆的用户名的密码,再将上面编写的msg发出去,最后quit即可。</p>
#smtp_address:发送收件的smtp地址;
#smtp_port:发送收件的smtp地址对应的端口,如果采用TTS加密的话,一定要注意端口的设置;
#login_username:邮箱登陆的用户名;
#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 + "发送成功!")
except smtplib.SMTPException:
print("Error: 无法发送邮件")
结语
<p>总结下,之前设定的任务大体完成了。但是还是有很多可以深化的内容,例如前面采用DataFrame的时候,没有对数据进行可视化,HTML的模板还可以再美化下,另外假如引入了数据可视化,要怎么将可视化的图片嵌入到邮件中。邮件登陆那部分,部分邮箱没有办法采用这个方法发出(需要再考虑smtp设置)。</p>
<p>上面这些问题,后续会继续以小项目的形式进行研究。后面还可以进行平台之间的销售情况对比等等,总而言之,该项目还是有很大的扩张空间的。嘛,这一次就先这样结束吧。</p>