20191113 2019-2020-2 《Python程序设计》实验四报告

课程:《Python程序设计》
班级: 1911
姓名: 林紫欣
学号:20191113
实验教师:王志强
实验日期:2020年6月1日
必修/选修: 公选课

1.实验内容

  • 利用爬虫爬取世界及中国疫情数据并利用pyecharts实现疫情数据可视化

2.实验设计

简单的三步走战略

  • 爬取数据
  • 数据处理
  • 数据可视化
    • 地图
    • 柱状图
    • 词云图
    • 折线图

3. 实验过程及结果

爬取世界疫情数据及其地图可视化

1.爬取数据

  • 选择爬取的网页

经过多方的数据比较最终选择了新浪新闻|新型冠状病毒肺炎疫情

  • 查看网页源代码

  • 寻找所要爬虫的信息

根据所爬取的网页链接观察得出规律,可知所要爬取的最新数据的网址可设置为

new_time = int(time.time() * 1000)
url = 'https://gwpre.sina.cn/ncp/foreign?_={}'.format(new_time)
  • 进行数据爬取
new_time = int(time.time() * 1000)
url = 'https://gwpre.sina.cn/ncp/foreign?_={}'.format(new_time)
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36'}
res = requests.get(url,headers=headers)

2.数据的处理

  • 类型转换,json-->dict
data = json.loads(res.text)
  • 提取所需数据
name = jsonpath.jsonpath(data,'$..name')
confirm = jsonpath.jsonpath(data,'$..value')
  • 数据处理与存储
data_zip = zip(name,confirm)
data_list = [[a,b] for a,b in data_zip]
pd_data = pd.DataFrame(columns=['国家','累计确诊人数'],data = data_list)
pd_data.to_csv("Word.csv", encoding='utf-8-sig')

3.可视化地图

  • 第一次可视化的时候发现地图上没有数据显示

经检查发现是所爬虫下来的数据国家是中文,而pyecharts的地图库中是英文,没有办法正常匹配。
故而百度获得了世界地图nameMap

  • 第二次可视化的时候有部分数据并没有在地图上显示,并且地图没有层级分别

讲过层层检查发现是百度得到的nameMap和新浪新闻所用的并不是同一个,有部分国家名字有略微不同。
修改过后开始设置地图层级。

  • 第三次可视化发现数据除了中国其他国家皆数据翻倍

在代码中进行打印检查

所获数据一一对应,同时没有差错。
利用腾讯新闻网所爬取的数据并不会出现类似问题。但是腾讯新闻网的数据并不全面。
那是为什么呢?目前并未解决。

  • 目前可视化代码
LEVEL_CLASSIFICATION = [
    {'min': 0, 'max': 0, 'label': '0', 'color': '#FFFFFF'},
    {'min': 1, 'max': 99, 'label': '1-99', 'color': '#FECFC6'},
    {'min': 100, 'max': 999, 'label': '100-999', 'color': '#FD836B'},
    {'min': 1000, 'max': 9999, 'label': '1000-9999', 'color': '#FC4824'},
    {'min': 10000, 'max': 99999, 'label': '10000-99999', 'color': '#B62002'},
    {'min': 100000, 'max': 999999, 'label': '100000-999999', 'color': '#731401'},
    {'min': 1000000, 'max': 99999999, 'label': '1000000人以上', 'color': '#310901'}]
InitOpts = options.InitOpts(width='1200px',height='600px',page_title='世界疫情分布图',bg_color='white')
map = Map(InitOpts)
map.add(series_name='累计确诊人数',data_pair=data_zip,maptype='world',name_map=NAME_MAP,is_map_symbol_show=False)
map.set_series_opts(label_opts=options.LabelOpts(is_show=False))    # 设置系列配置项
map.set_global_opts(title_opts=options.TitleOpts(title='世界疫情分布情况'),
visualmap_opts = options.VisualMapOpts(max_=800, is_piecewise=True, pieces=LEVEL_CLASSIFICATION))   # 设置全局变量
map.render('世界疫情分布情况PLUS.html')

4.码云链接

世界疫情分布地图

爬取中国疫情数据及其可视化

1.爬取并处理数据

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36',
    'Referer': 'https://news.sina.cn/zt_d/yiqing0121'
}
if __name__ == '__main__':
    new_time = int(time.time() * 1000)
    url = 'https://gwpre.sina.cn/interface/fymap2020_data.json?_={}&callback=dataAPIData'.format(new_time)
    get_html(url)

def get_html(url):
    html = requests.get(url, headers=headers)
    take_json = re.compile('{"data_title":"fymap","data":(.*?)}}')  # 用正则表达式取中间

    new_json = take_json.findall(html.text)
    new_json = json.loads(new_json[0] + '}}')

    province_dict = {
        '省份名字': [],
        '省份英文名字': [],
        '目前确诊人数': [],
        '累计确诊人数': [],
        '治愈人数': [],
        '目前死亡人数': [],
        '现存无症状人数': [],
        '目前怀疑感染人数': [],
        '目前境外输入人数': [],
        '较昨日增加人数': [],
        '连续无感染天数': [],
    }

    city_dict = {
        '城市名字': [],
        '目前确诊人数': [],
        '累计确诊人数': [],
        '目前治愈人数': [],
        '目前死亡人数': [],
        '现存无症状人数': [],
        '目前怀疑感染人数': [],
        '目前境外输入人数': [],
        '较昨日增加人数': [],
        '连续无感染天数': [],
    }

    for i in new_json['list']:
        province_dict['省份名字'].append(i['name'])  # 城市名字
        province_dict['省份英文名字'].append(i['ename'])  # 城市英文名字
        province_dict['现存无症状人数'].append(i['asymptomNum'])  # 现存无症状人数
        province_dict['治愈人数'].append(i['cureNum'])  # 治愈人数
        province_dict['目前死亡人数'].append(i['deathNum'])  # 目前死亡人数
        province_dict['目前确诊人数'].append(i['econNum'])  # 目前确诊人数
        province_dict['累计确诊人数'].append(i['value'])  # 累计确诊人数
        province_dict['目前怀疑感染人数'].append(i['susNum'])  # 目前怀疑感染人数
        province_dict['目前境外输入人数'].append(i['jwsrNum'])  # 目前境外输入人数
        province_dict['较昨日增加人数'].append(i['conadd'])  # 较昨日增加人数
        province_dict['连续无感染天数'].append(i['zerodays'])  # 连续无感染天数

        for t in i['city']:
            city_dict['城市名字'].append(t['mapName'])  # 城市名字
            city_dict['累计确诊人数'].append(t['conNum'])  # 城市累计确诊人数
            city_dict['目前治愈人数'].append(t['cureNum'])  # 城市治愈人数
            city_dict['目前死亡人数'].append(t['deathNum'])  # 城市治愈人数
            city_dict['目前确诊人数'].append(t['econNum'])  # 目前确诊人数
            city_dict['较昨日增加人数'].append(t['conadd'])  # 较昨日增加人数
            city_dict['连续无感染天数'].append(t['zerodays'])  # 城连续无感染天数
            city_dict['目前境外输入人数'].append(t['jwsr'])  # 目前境外输入人数
            city_dict['现存无症状人数'].append(t['asymptomNum'])  # 现存无症状人数
            city_dict['目前怀疑感染人数'].append(t['susNum'])  # 目前怀疑感染人数

    province_data = pd.DataFrame(province_dict)
    city_data = pd.DataFrame(city_dict)

    for i in province_dict:  # 迭代数据  如果出现空数据则补0
        province_data[i] = province_data[i].apply(lambda x: '0' if x == '' else x)

    for i in city_dict:  # 迭代数据  如果出现空数据则补0
        city_data[i] = city_data[i].apply(lambda x: '0' if x == '' else x)

    city_data = city_data[~city_data['城市名字'].isin(['境外', '外来', '0'])]  # 取反 筛选掉没用数据

    province_id = province_data['省份名字'].values.tolist()  # .values.tolist()为转换为列表形式
    province_set = province_data['累计确诊人数'].values.tolist()

2.生成文件夹及其相关可视化html

    filename = 'Visualization in China'
    if not os.path.exists(filename):  # 生成文件夹
        os.makedirs(filename)

    di_tu(province_id, province_set)  # 生成地图
    zhu_zhuang(province_id, province_set)  # 生成柱状图

    city_id = city_data['城市名字'].values.tolist()
    city_set = city_data['累计确诊人数'].values.tolist()

    whole_id = province_id + city_id
    whole_data = province_set + city_set

    ci_yun(whole_id, whole_data)  # 生成词云图

    province_set = province_data['治愈人数'].values.tolist()
    zhe_xian(province_id, province_set)  # 生成折线图

    province_data.to_csv("中国疫情省份分析.csv", encoding='utf-8-sig')
    city_data.to_csv("中国疫情城市分析.csv", encoding='utf-8-sig')

3.可视化地图

def di_tu(your_id, your_data):  # 地图  our_id为名字  your_id为数据
    m = Map(opts.InitOpts(width='1260px',height='600px',page_title="中国新型冠状肺炎疫情分布地图"))
    m.add("确诊人数", [list(z) for z in zip(your_id, your_data)], "china")
    m.set_global_opts(title_opts=opts.TitleOpts(title="中国新型冠状肺炎疫情分布地图"),
                      visualmap_opts=opts.VisualMapOpts(max_=800))
    m.render("./Visualization in China/Map.html")

4.可视化柱状图

def zhu_zhuang(your_id, your_data):  # 柱状图  your_id为名字  your_id为数据

    bar = Bar(
        init_opts=opts.InitOpts(
            theme=ThemeType.PURPLE_PASSION,
            width="1260px",
            height="600px",
        page_title="中国新型冠状肺炎疫情情况柱状图"))
    bar.add_xaxis(your_id)
    bar.add_yaxis('确诊人数', your_data)
    bar.set_global_opts(
        title_opts=opts.TitleOpts(
            title="中国新型冠状肺炎疫情情况柱状图"),
        datazoom_opts=[opts.DataZoomOpts()],  # ------窗口滑块
        xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=10)))  # 旋转标签
    bar.render("./Visualization in China/Histogram.html")

5.可视化词云图

def ci_yun(your_id, your_data):  # 词云图  your_id为名字  your_id为数据

    new = list(zip(your_id, your_data))

    words = new

    wordcloud = WordCloud(init_opts=opts.InitOpts(width="1260px", height='600px', page_title="中国新型冠状肺炎疫情情况词云图"))
    wordcloud.add('', words, word_size_range=[20, 100])
    wordcloud.set_global_opts(title_opts=opts.TitleOpts(title="中国新型冠状肺炎疫情情况词云图"))

    wordcloud.render('./Visualization in China/WordCloud.html')

6.可视化渐变折线图

def zhe_xian(your_id, your_data):  # 折线图  your_id为名字  your_id为数据

    x_data = your_id
    y_data = your_data

    background_color_js = (
        "new echarts.graphic.LinearGradient(0, 0, 0, 1, "
        "[{offset: 0, color: '#c86589'}, {offset: 1, color: '#06a7ff'}], false)"
    )
    area_color_js = (
        "new echarts.graphic.LinearGradient(0, 0, 0, 1, "
        "[{offset: 0, color: '#eb64fb'}, {offset: 1, color: '#3fbbff0d'}], false)"
    )

    c = (
        Line(init_opts=opts.InitOpts(bg_color=JsCode(background_color_js),width='1260px',height='600px',page_title="中国新型冠状肺炎疫情情况折线图"))
            .add_xaxis(xaxis_data=x_data)
            .add_yaxis(
            series_name="治愈人数总量",
            y_axis=y_data,
            is_smooth=True,
            is_symbol_show=True,
            symbol="circle",
            symbol_size=6,
            linestyle_opts=opts.LineStyleOpts(color="#fff"),
            label_opts=opts.LabelOpts(is_show=True, position="top", color="white"),
            itemstyle_opts=opts.ItemStyleOpts(
                color="red", border_color="#fff", border_width=3
            ),
            tooltip_opts=opts.TooltipOpts(is_show=False),
            areastyle_opts=opts.AreaStyleOpts(color=JsCode(area_color_js), opacity=1),
        )
            .set_global_opts(
            title_opts=opts.TitleOpts(
                title="目前治愈人数",
                pos_bottom="5%",
                pos_left="center",
                title_textstyle_opts=opts.TextStyleOpts(color="#fff", font_size=16),
            ),
            xaxis_opts=opts.AxisOpts(
                type_="category",
                boundary_gap=False,
                axislabel_opts=opts.LabelOpts(margin=30, color="#ffffff63",interval=0,rotate=30),
                axisline_opts=opts.AxisLineOpts(is_show=False),
                axistick_opts=opts.AxisTickOpts(
                    is_show=True,
                    length=25,
                    linestyle_opts=opts.LineStyleOpts(color="#ffffff1f"),
                ),
                splitline_opts=opts.SplitLineOpts(
                    is_show=True, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f")
                ),
            ),
            yaxis_opts=opts.AxisOpts(
                type_="value",
                position="right",
                axislabel_opts=opts.LabelOpts(margin=20, color="#ffffff63"),
                axisline_opts=opts.AxisLineOpts(
                    linestyle_opts=opts.LineStyleOpts(width=2, color="#fff")
                ),
                axistick_opts=opts.AxisTickOpts(
                    is_show=True,
                    length=15,
                    linestyle_opts=opts.LineStyleOpts(color="#ffffff1f"),
                ),
                splitline_opts=opts.SplitLineOpts(
                    is_show=True, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f")
                ),
            ),
            legend_opts=opts.LegendOpts(is_show=False),
        )
    )
    c.render('./Visualization in China/LineChart.html')

7.码云链接

Visualization of COVID-19 in China

4.实验结果展示

插入了优酷视频,完全显示的话可能需要过长的时间。
还可以请点击链接20191113林紫欣综合实践报告成果展示

5.实验分析

  • 本次实验结果算是全球战役的一个粗略答卷,是中国疫情战役的一个阶段性总结。全国省市基本控制,6月7日新增确诊仅4例,武汉更是零增长。武汉疫情控制了,中国疫情也就控制了,我们的抗疫歼灭战,已到最后收尾阶段。但于此同时境外输入有5例。中国情况越来越好,世界局势却不容容乐观。
    时至今日全球累计确诊6925171人,新增83438人;美国累计总人数1988544人,高达两百万。
  • 面对全球疫情,我们需要做好应对的三手准备:
  • 一、我们首先要做好自我的防护,巩固我们的抗疫成果
    “内防扩散,外防输入”,这是当前我们的政策。内部扩散的防护我们现在做得很好,未来随着武汉疫情的歼灭,国内疫情基本会呈现可控状态,不会再大规模扩散。但是,随着全球范围内的疫情扩散,外部输入疫情的压力必然大幅增加。在这种情况下,外防输入就成了我们的重点。对我们来说,必须采取措施防输入。而且,在如何识别病人和采取措施方面,我们还需要进一步提升能力。
  • 二、我们要有计划地去帮助我们的朋友,展开抗疫国际合作
    中国的经验和应对疫情的能力,对全球来说就是最宝贵的东西。一方面,作为负责任的大国,我们将我们的经验分享会获得国际上的广泛赞誉,譬如现在世卫组织的专家组对中国的应对措施非常认可,这就使得我们拥有了在应对疫情方面的权威。随着疫情爆发,我们是可以在国际上展开更多合作,为我们的友好国家逐渐提供相应的支持了。譬如,我们支援伊朗就是一个能起到很好作用的示范。接下来,随着我们自身疫情的控制,我们这种能力将会使得我们在世界上获得更大的领导力和影响力,有助于我们对冲国际反华势力对中国的抹黑与攻击。同时,这一系列合作,有助于我们打通更多我们的国际合作关节。
  • 三、我们应研究制定全球疫情爆发背景下的系列应对方案
    全球疫情爆发,如何在疫情爆发的情况下进行人员、经贸往来对世界来说是个重要课题,在这方面我们应该有更加详尽实用的方案。基于这样的实践,我们甚至可以建立一个疫情防控的国际合作组织,将中国的防控经验通过与世卫组织形成机制,这将有助于提升我国与其他国家的合作水平。
  • 这次疫情,如果仅仅在中国爆发,那将成为敌对势力遏制中国的工具;反之,疫情现在全球面临爆发,我们因抗击疫情所做的努力就使得我们获得的更为强大的抗疫能力,此时这种能力就成了我们帮助世界的手段,而帮助世界将提升中国的影响力。现在,国际形势正在由对我们不利向对我们有利转变,亮剑!

5. 实验过程中遇到的问题和解决过程

  • 问题1:世界疫情地图除中国外数据翻倍问题。

  • 问题1解决方案:未解决,目前锁定为数据调用展示问题。
  • 问题2:中国疫情折线图横坐标显示不完全。

  • 问题2解决方案:在axislabel_opts中加入interval=0,rotate=30。加入rotate参数并倾斜30°避免横坐标重叠。
  • 问题三:颜色不符合心中预期

  • 问题解决方案:一开始是使用html颜色代码大全进行对照,后来发现了一个特别棒的网站Fontke,只要选择心仪的颜色然后复制16进制代码就可以了。
    发现了一个更好用的HTML色彩提取利器,颜色不是固定的,就像是WPS里面的调色盘一样,可以自己调。

参考资料




全课总结

  • 一学期的Python程序设计课程让我感触颇深。自感觉这门课程新鲜有趣到苦恼其难度之大,再到体会学习Python的乐趣。这每一步每一时期现在回忆起来都是积为宝贵的成长经历。
  • 《Python程序设计》是实践性很强的课程,其中充满乐趣也极富有挑战性。我们必须亲手去做,才能够体会到该“如何做”,这要比整天在理论中寻找答案更有成就感。
  • 通过学习这门课程,我懂得了许多,有如何从掌握问题,从问题出发做出可以解决问题的程序:
    • 在程序中面临的问题通常用非形式的语言描述,或者直接来自于实际生活。其表述可能会不准确、不完全,甚至有错误。这就需要我们通过深入分析,把问题严格化。
    • 明白了清晰的需求之后,我们需要设计好整个处理过程。
    • 设法落实实现中各主要处理工作的算法,必须要考虑算法的性质与情况。
    • 实现程序,即为编码,通过试验运行确认程序能完成所需的工作。
    • 评价和改进程序。
  • 对Python这种语言的特点及其内容也有了一定的了解。
    Python是一种高级动态、完全面向对象的语言,函数、模块、数字、字符串都是对象,并且完全支持继承、重载、派生、多继承,有益于增强源代码的复用性。Python是一种计算机程序设计语言(解释型语言),具有代码少、简单、运行速度慢的特点。
    • 变量赋值及其命名规则
    • 运算符及其优先级
    • 基本数据类型
    • 循环语句
    • 列表、元组、字典、集合及其常用功能
    • 字符串与正则表达式
    • 函数
    • 面向对象程序设计
    • 文件操作及异常处理
    • Python操作数据库
    • Python网络编程及爬虫开发(Socket)
  • 同时这门课程也让我的自我学习能力有了很大的提升。个人认为,知识海洋浩瀚,“上课”是完全无法解决问题的。学生所需要的正是学习的兴趣与自我探索的能力。这门课程在这两方面有一个比较好的作用。
  • 优点有,缺点同样也有。想让学生自由地飞翔茁壮成长,翅膀的构建需要老师的努力,特别是在一些同学一开始并没有浓厚兴趣的时候,就让同学们自主看视频,会使得一些学习积极性不高的同学落下基础。这样上课的时候便全然不懂,面对课后作业与实验只剩下厌烦,这样又如何使学生真正飞翔起来呢?同时所需要看的视频数量实在是太多了,占用时间过多,作为一门选修课略有些过分。
  • 个人建议:
    • 前期放慢教学速度,或者说是老师提前将自己所做的课件以及总结放给同学,让其课前用较少的时间获取知识,在课堂上进行知识的深入与加工,最好是在课堂上督促同学们动手进行实验。因为本学期是网上授课,有多少同学在听课的时候同时对老师所说进行实践是不清楚的,这无疑需要老师偶尔的提醒与督促,使同学养成良好的学习习惯。
    • 我很喜欢老师布置作业的难度与方式。很大程度上促使我努力学习课堂以外的知识,做完作业之后特别有成就感。这一点我希望可以发扬光大。
    • 希望老师增设作业、实验验收课,对同学们的作业与实验成果进行一个点评。这样有了反馈之后,同学们才知道自己的一些不足和其他同学的闪光点。课程时间原因定然不能逐一进行点评,可以随机抽人进行。这样也可以提升同学们的认真用心程度。
    • 将平时成绩公示化。至少要让每个同学能知道自己的平时成绩,有努力的方向。现在许多成绩并未公示明了。
 posted on 2020-06-07 13:15  20191113林紫欣  阅读(646)  评论(0编辑  收藏