一、背景:
虽然穷还菜鸟,但投钱进了股市,也维持着一个涨停数据项目。当前最重大时事就是新型肺炎。各大网站都有数据统计,可视化做很漂亮。但都是国内的,没做国际的。而新型肺炎已经上升为国际事件,国内与国际资本市场也相互影响。这种情况下,其他国家新型肺炎数据也值得关注.没有现成的就得自己做。
编程菜鸟初学不精,能实现目标就好。
二、过程:
1、爬取数据:
最终选择了网易。能力有限,其他的爬不下来。
import re
import time
import requests
from bs4 import BeautifulSoup
url = "http://news.163.com/special/epidemic/"
def get_htmltext(url):
""
直接黏贴的,找了个最简单的。不懂原理,能得到想要的数据。
""
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.content.decode('gbk').encode('utf-8')
return r.text
except:
raise
text = get_htmltext(url)
soup = BeautifulSoup(text, 'html.parser')
data = soup.find_all('p')
[
中国(含港澳台):确诊 11891 例,死亡 259 例,治愈 270 例
,海外:确诊 137 例
,海外确诊病例:日本20例,泰国19例
,新加坡18例,韩国12例,澳大利亚12例
,马来西亚8例,德国7例,美国7例,法国6例
,越南6例,阿联酋4例,加拿大4例,英国2例
,意大利2例,俄罗斯2例,印度1例,瑞典1例
,芬兰1例,尼泊尔1例,西班牙1例
,斯里兰卡1例,柬埔寨1例,菲律宾1例
,单击省份可查看病例数
,以上数据均来自官方通报
,全国确诊
,治愈人数
,死亡人数
,已开启实时追踪
]
2、整理数据:
result = str(data).replace('<p>','').replace('</p>','')
result = str(result).split(',')
l0 = [i for i in result if not i.startswith(' <p')][:-3] # 通过for遍历,用<p来判断是否为有用数据,然后切片得到如下:
[’[中国(含港澳台):确诊 11891 例,死亡 259 例,治愈 270 例’, ’ 海外:确诊 137 例’, ’
海外确诊病例:日本20例,泰国19例’, ’ 新加坡18例,韩国12例,澳大利亚12例’, ’
马来西亚8例,德国7例,美国7例,法国6例’, ’ 越南6例,阿联酋4例,加拿大4例,英国2例’, ’
意大利2例,俄罗斯2例,印度1例,瑞典1例’, ’ 芬兰1例,尼泊尔1例,西班牙1例’, ’ 斯里兰卡1例,柬埔寨1例,菲律宾1例’]
l1 = [i.split(',') for i in l0]
l2 = [g.strip() for i in l1 for g in i] # 嵌套for循环分割,得到最终数据列表
['[中国(含港澳台):确诊 11891 例',
'死亡 259 例',
'治愈 270 例',
'海外:确诊 137 例',
'海外确诊病例:日本20例',
'泰国19例',
'新加坡18例',
'韩国12例',
'澳大利亚12例',
'马来西亚8例',
'德国7例',
'美国7例',
'法国6例',
'越南6例',
'阿联酋4例',
'加拿大4例',
'英国2例',
'意大利2例',
'俄罗斯2例',
'印度1例',
'瑞典1例',
'芬兰1例',
'尼泊尔1例',
'西班牙1例',
'斯里兰卡1例',
'柬埔寨1例',
'菲律宾1例']
#使用正则表达式将总体和明细数据拆分,取出数字转为int,并去除多余字符,用字典推导式生成字典。
total = {re.sub(r'[\d]+ 例','',i).replace(':',''):int(re.search(r'[\d]+', i).group()) for i in l2[:4]}
overseas_detail = {re.sub(r'[\d]+例','',i).replace('海外确诊病例:',''):int(re.search(r'[\d]+', i).group()) for i in l2[4:]}
#添加海外国家数量和日期,最终结果为一个字典。
total['海外感染国家总数'] = len(overseas_detail)
total['日期'] = time.strftime('%Y%m%d')
'''
{'[中国(含港澳台)确诊 ': 11891,
'死亡 ': 259,
'治愈 ': 270,
'海外确诊 ': 137,
'海外感染国家总数': 23,
'日期': '20200201'}
'''
3、做可视化:
import pandas
from pyecharts import options as opts
from pyecharts.charts import Line, Grid
df_ncov = pd.DataFrame(total.values(), index=total.keys()).T # 转为DataFrame,重设索引
df_ncov = df_ncov.set_index('日期')
def get_line(tb):
line0 = Line(init_opts=opts.InitOpts(width='500px', bg_color='#F5F5F7'))
line0.add_xaxis(xaxis_data = tb.index.tolist())
for col in tb.columns[1:]:
line0.add_yaxis(
series_name=col,
y_axis=tb[col].values,
is_smooth=True,
is_hover_animation=False,
linestyle_opts=opts.LineStyleOpts(width=3, opacity=0.5),
label_opts=opts.LabelOpts(is_show=True),
# itemstyle_opts=opts.ItemStyleOpts(color='#099e79'),
is_symbol_show=True)
# markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(type_="average")]))
line0.set_global_opts(
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45),is_scale=True),
yaxis_opts=opts.AxisOpts(is_scale=True),
title_opts=opts.TitleOpts(title="",subtitle=''),
legend_opts=opts.LegendOpts(pos_left='right'),
toolbox_opts=opts.ToolboxOpts(orient='vertical',pos_left=None,pos_top='top'),
# datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")]
)
line1 = Line(init_opts=opts.InitOpts(width='500px', bg_color='#F5F5F7'))
line1.add_xaxis(xaxis_data = tb.index.tolist())
for col in tb.columns[:1]:
line1.add_yaxis(
series_name=col,
y_axis=tb[col].values,
is_smooth=True,
is_hover_animation=False,
linestyle_opts=opts.LineStyleOpts(width=3, opacity=0.5),
label_opts=opts.LabelOpts(is_show=True),
# itemstyle_opts=opts.ItemStyleOpts(color='#099e79'),
is_symbol_show=True)
# markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(type_="average")]))
line1.set_global_opts(
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45),is_scale=True),
yaxis_opts=opts.AxisOpts(is_scale=True),
title_opts=opts.TitleOpts(title="新型肺炎人数",subtitle='',pos_left='center'),
legend_opts=opts.LegendOpts(pos_left='left'),
toolbox_opts=opts.ToolboxOpts(orient='vertical',pos_left=None,pos_top='top'),
# datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")]
)
grid = (
Grid()
.add(line0, grid_opts=opts.GridOpts(pos_left="50%"))
.add(line1, grid_opts=opts.GridOpts(pos_right="50%"))
)
return grid
ln = get_line(df_ncov)
ln.render_notebook()
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200202002532208.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2hvdG9vdG9w,size_16,color_FFFFFF,t_70)
把数据导入了自己搭建的数据库,以后每日更新,作为参考。
三、总结:
1、不满意的地方:
本想加上疑似人数,可是能力太差。都是script的json格式,不知道怎么弄下来,最终放弃。
吐槽下pycharts。去年做涨停项目的时候,pyecharts的主页例子都有展示图片,现在反倒没有了。很不友好,不知道具体效果,都是代码,没有图片很不方便。没有基础的,估计会被劝退。
另外因为数据跨度大,放在一起效果不佳。想了几个方案解决,调整坐标(指数坐标或双坐标),上下图,左右图。第一个,没有指数坐标的选项,双坐标提示line没有overlab。示例中是bar和line做双坐标。上下不好看。最终选择左右图,其实也不好看。不满意。
2、学到的东西:
推导式、正则表达式、一些爬虫知识、重温了pyecharts等。
3、感悟:
想做成点事情真不容易,自己水平太低。这段时间看软件工程,想提高代码复用性,结果很难实现,还得努力啊。另外变懒了,懒得敲代码,有些生疏,学了很多知识和技巧,得用起来。