Python高级应用程序设计任务

Posted HiWangLu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python高级应用程序设计任务相关的知识,希望对你有一定的参考价值。

 一、主题式网络爬虫设计方案(15分)

1.主题式网络爬虫名称

《Python爬虫之国家统计局相关数据的爬取及分析》

2.主题式网络爬虫爬取的内容与数据特征分析

本次爬取内容为:国家统计局(http://www.stats.gov.cn/)中,改革开放以来GDP增长率、三大产业对GDP的贡献率以及三大产业对GDP增长的拉动。

数据特征分析:根据网页显示,可以直观地看出这些数据年年在变化,并且第三产业对GDP的贡献率呈上升趋势。三大产业对GDP增长的拉动=三大产业对GDP的贡献率×GDP增长率。

3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)

① 通过数据查询(http://data.stats.gov.cn/)页面,查询所要的数据,并找到数据所在的URL。

②利用Python爬取URL中的所有数据,并保存为xlsx文件(要用到requests、json、os库)。

③进行数据清洗、提取所需数据,整理好并保存为xlsx文件(要用到pandas、numpy、matplotlib库)。

④通过制图,对数据进行可视化分析,并得出结论。

技术难点:网页上的数据是动态的,单纯依靠bs4库没办法解决,要另寻他法。

 

二、主题页面的结构特征分析(15分)
1.主题页面的结构特征
2.Htmls页面解析
3.节点(标签)查找方法与遍历方法
(必要时画出节点树结构)

  查看国家统计局的robots协议,发现是空白,那就可以大胆地进行数据爬取。搜索关键词“GDP”,显示的只有2018年和2017年两年的数据,而在网页的底部有这么一条说明“如果没有输入时间,对于月度指标,系统显示最近1个月的数据;对于季度指标,系统显示最近1个季度的数据;对于年度指标,系统显示最近2年的数据”,这就意味着,1978-2016年的数据要输入时间关键字,才能查询到数据。

  查看网页HTML的源代码,并没有找到我们所要的指标名称和数据,那就说明这个网站的数据都是动态生成的,不能用搜索或遍历标签的方法来找到内容。通过寻求网络帮助,我们学习到两种获取动态数据的方法:第一种是通过Selenium模拟浏览器获取,第二种是从网页响应中找到JS脚本返回的JSON数据。这里我们使用了第二种,对数据进行JSON化。

①找到JS请求的数据接口(360浏览器可直接右击-审查元素,其他浏览器找到工具栏-开发人员工具,或者F12直接打开调试工具)

  点击Network-XHR,里面有一个叫search.htm?s....的链接(如果选项卡里没有链接,刷新页面即可)

  

  点击链接-Preview-展开result,里面有一串JSON数据,经过比对,正是我们所要的数据,接口链接就在Headers-General-Request URL

  打开接口链接,查看内容是否一致。确定内容一致,对数据接口进行请求和获取响应。
  链接内容为字典类型。所要内容在"result"键下,值为列表类型,列表里又包含多个字典,可通过字典的键名进行内容提取。

 

②比较近两年和之前年份的接口链接差异

  搜索“GDP”可以搜索到近两年的相关数据,Request URL:http://data.stats.gov.cn/search.htm?s=GDP&m=searchdata&db=&p=0

  搜索“2017GDP”可以搜索到2017年的相关数据,Request URL:http://data.stats.gov.cn/search.htm?s=2017GDP&m=searchdata&db=&p=0

  “2017GDP”第二页数据,Request URL:http://data.stats.gov.cn/search.htm?s=2017GDP&m=searchdata&db=&p=1

  对比可发现:搜索关键字不同,接口连接改变的是htm?s=后,&m=searchdata前的内容;页数不同,接口连接改变的是&p=后的数字

用requests.get()方法获取信息;用json.loads方法()将数据JSON化;用for循环,对链接进行遍历,以获取所有内容。
通用连接:http://data.stats.gov.cn/search.htm?s={0}{1}&m=searchdata&db=&p={2}

 

三、网络爬虫程序设计(60分)
爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后面提供输出结果的截图。
1.数据爬取与采集

 1 #导入库
 2 import requests
 3 import json
 4 import os
 5 import pandas as pd
 6 import numpy as np
 7 import matplotlib.pyplot as plt
 8 
 9 #对数据接口进行http请求
10 def getHTMLText(url):
11     try:
12         r = requests.get(url, timeout=30)   #获取信息,请求超时时间为30秒
13         r.raise_for_status()   #如果状态不是200,则引发异常
14         r.encoding = r.apparent_encoding   #配置编码
15         return r.text   #返回url对应的页面内容
16     except:
17         return "产生异常"
18 
19 #对数据JSON化,并提取我们想要的内容
20 def filterHTMLText(lst,wbdata):
21     try:
22         data = json.loads(wbdata)   #对HTTP响应的数据JSON化
23         newdata = data[\'result\']    #索引到我们所要的位置
24         for i in newdata:   #对索引出来的JSON数据进行遍历和提取
25             target = i[\'zb\']      #提取“指标”内容
26             data_time = i[\'sj\']   #提取“数据时间”内容
27             value = i[\'data\']     #提取“数值”内容
28             attribute = i[\'db\']   #提取“所属栏目”内容
29             lst.append([target,data_time,value,attribute])   #将数据存放到lst列表里
30         return lst    #返回lst数据列表
31     except:
32         return "产生异常"
33 
34 #保存数据,生成xlsx格式文件
35 def saveHTMLText(lst):
36     try:
37         headers = [\'指标\',\'数据时间\',\'数值\',\'所属栏目\']   #设置columns名称
38         index = [i for i in range(1,len(lst)+1)]         #设置index值
39         df = pd.DataFrame(lst,columns=headers,index=index)   #将数据列表转换为DataFrame对象
40         if not os.path.exists(\'F:\\\\PycharmProject\'):   #判断磁盘里是否存在目标文件夹
41             os.makedirs(\'F:\\\\PycharmProject\')   #不存在,则创建该文件夹并且生成xlsx文件
42             df.to_excel(\'F:\\\\PycharmProject\\\\国家统计局数据.xlsx\')   
43         else:
44             df.to_excel(\'F:\\\\PycharmProject\\\\国家统计局数据.xlsx\')
45         print("保存成功")   #返回“保存成功”的提示
46     except:
47         print("保存失败")   #返回“保存失败”的提示
48 
49 #主程序
50 def main():
51     uList = []   #存储爬取到的数据
52     for YearIndex in range(1978,2017):   #遍历1978-2016年的URL
53         for PageIndex in range(0,6):     #遍历每一年前6页的URL
54             url = "http://data.stats.gov.cn/search.htm?s={0}{1}&m=searchdata&db=&p={2}".format(YearIndex,\'GDP\',PageIndex)  
55             html = getHTMLText(url)      #调用getHTMLText函数
56             filterHTMLText(uList,html)   #调用filterHTMLText函数
57     for PageIndex in range(0,6):   #遍历2017-2018年前6页的数据
58             url = "http://data.stats.gov.cn/search.htm?s=GDP&m=searchdata&db=&p={0}".format(PageIndex)
59             html = getHTMLText(url)
60             filterHTMLText(uList,html) 
61     saveHTMLText(uList)   #调用saveHTMLText函数
62 
63 #程序执行时调用主程序main()
64 if __name__ == \'__main__\':
65     main()

运行结果:

                   

 

2.对数据进行清洗和处理

1 #删除无效列
2 GDP_Data = pd.DataFrame(pd.read_excel(\'F:\\\\PycharmProject\\\\国家统计局数据.xlsx\'))
3 GDP_Data.drop(GDP_Data.columns[0],axis=1,inplace=True)
4 GDP_Data.head(10)

运行结果:

 

1 #查找重复值
2 GDP_Data.duplicated()

运行结果:

1 #删除重复值
2 GDP_Data = GDP_Data.drop_duplicates()
3 GDP_Data.head(10)

运行结果:

1 #统计‘数值’列空值的个数
2 GDP_Data[\'数值\'].isnull().value_counts()

运行结果:

1 #删除‘数值’列中含有空值的行
2 GDP_Data.dropna(axis=0, how=\'any\', inplace=True)
3 GDP_Data[\'数值\'].isnull().value_counts()

运行结果:

1 #查看描述信息
2 GDP_Data.describe()

运行结果:

1 #对数据按照“数据时间”进行升序排序
2 GDP_Data.sort_values(by=["数据时间"],inplace=True,ascending=[True])
3 GDP_Data

运行结果:

 

1 #提取“国内生产总值增长(百分点)”数据
2 GDP_Incr = GDP_Data.loc[(GDP_Data[\'指标\'].str.contains(\'国内生产总值增长\\(百分点\\)\'))&(GDP_Data[\'所属栏目\'] == \'年度数据\')]
3 GDP_Incr

运行结果:

1 #补充“2018年国内生产总值增长(百分点)”的数据
2 New_Data = pd.DataFrame({\'指标\':\'国内生产总值增长(百分点)\',\'数据时间\':\'2018年\',\'数值\':6.6,\'所属栏目\':\'年度数据\'},index=[2443])
3 GDP_Incr=GDP_Incr.append(New_Data,ignore_index=False)   #将2018年的数据添加到最后一行
4 GDP_Incr

运行结果:

1 #提取“第一产业对GDP的贡献率”数据
2 Contribution_Fir=GDP_Data.loc[GDP_Data[\'指标\'].str.contains(\'第一产业对GDP的贡献率\')]
3 Contribution_Fir

运行结果:

1 #提取“第二产业对GDP的贡献率”数据
2 Contribution_Sec=GDP_Data.loc[GDP_Data[\'指标\'].str.contains(\'第二产业对GDP的贡献率\')]
3 Contribution_Sec

运行结果:

1 #提取“第三产业对GDP的贡献率”数据
2 Contribution_Thir=GDP_Data.loc[GDP_Data[\'指标\'].str.contains(\'第三产业对GDP的贡献率\')]
3 Contribution_Thir

运行结果:

1 #提取“第一产业对国内生产总值增长的拉动”数据
2 Promote_Fir=GDP_Data.loc[GDP_Data[\'指标\'].str.contains(\'第一产业对国内生产总值增长的拉动\')]
3 Promote_Fir

运行结果:

1 #提取“第二产业对国内生产总值增长的拉动”数据
2 Promote_Sec=GDP_Data.loc[GDP_Data[\'指标\'].str.contains(\'第二产业对国内生产总值增长的拉动\')]
3 Promote_Sec

运行结果:

1 #提取“第三产业对国内生产总值增长的拉动”数据
2 Promote_Thir=GDP_Data.loc[GDP_Data[\'指标\'].str.contains(\'第三产业对国内生产总值增长的拉动\')]
3 Promote_Thir

运行结果:

1 #合并三大产业贡献率和GDP增长率
2 Contribution = pd.DataFrame({\'第一产业对GDP的贡献率\':Contribution_Fir[\'数值\'].tolist(),\'第二产业对GDP的贡献率\':Contribution_Sec[\'数值\'].tolist(),\'第三产业对GDP的贡献率\':Contribution_Thir[\'数值\'].tolist(),\'国内生产总值增长(百分点)\':GDP_Incr[\'数值\'].tolist()},index=Contribution_Fir[\'数据时间\'])
3 Contribution_All = pd.DataFrame({\'第一产业对GDP的贡献率\':Contribution_Fir[\'数值\'].tolist(),\'第二产业对GDP的贡献率\':Contribution_Sec[\'数值\'].tolist(),\'第三产业对GDP的贡献率\':Contribution_Thir[\'数值\'].tolist()},index=Contribution_Fir[\'数据时间\'])
4 Contribution.to_excel(\'F:\\\\PycharmProject\\\\三大产业对GDP的贡献率及GDP增长率.xlsx\')
5 Contribution

运行结果:

 

1 #合并三大产业对GDP增长的拉动
2 Promote = pd.DataFrame({\'第一产业对国内生产总值增长的拉动(百分点)\':Promote_Fir[\'数值\'].tolist(),\'第二产业对国内生产总值增长的拉动(百分点)\':Promote_Sec[\'数值\'].tolist(),\'第三产业对国内生产总值增长的拉动(百分点)\':Promote_Thir[\'数值\'].tolist()},index=Promote_Fir[\'数据时间\'])
3 Promote.to_excel(\'F:\\\\PycharmProject\\\\三大产业对GDP增长的拉动.xlsx\')
4 Promote

运行结果:

 

 

3.文本分析(可选):jieba分词、wordcloud可视化
4.数据分析与可视化
(例如:数据柱形图、直方图、散点图、盒图、分布图、数据回归分析等)

 1 #绘制1978年-2018年三大产业对GDP的贡献率及GDP增长率的折线图
 2 plt.rcParams[\'font.sans-serif\'] = [\'KaiTi\'] # 指定默认字体
 3 plt.rcParams[\'axes.unicode_minus\'] = False # 解决保存图像是负号\'-\'显示为方块的问题
 4 Contribution.plot(figsize=(20,10),linewidth=2.5,marker=\'o\').set_title(\'1978年-2018年三大产业对GDP的贡献率及GDP增长率的折线图\',size=25)
 5 plt.xticks(fontsize=20)   #横坐标字体大小20像素
 6 plt.yticks(fontsize=20)   #横坐标字体大小20像素
 7 plt.xlabel(\'时间\',fontsize=20)   #横坐标标题为“时间”,字体大小为20像素
 8 plt.ylabel(\'数值(百分点)\',fontsize=20)   #纵坐标标题为“数值(百分点)”,字体大小为20像素
 9 plt.legend(fontsize=20)   #设置图例大小为20像素
10 plt.show()

运行结果:

 

1 #绘制1978年-2018年三大产业对GDP的贡献率及GDP增长率的水平组合柱状图
2 Contribution.plot(kind=\'barh\',figsize=(20,50),linewidth=5).set_title(\'1978年-2018年三大产业对GDP的贡献率及GDP增长率的水平组合柱状图\',size=25)
3 plt.xticks(fontsize=20)
4 plt.yticks(fontsize=20)
5 plt.ylabel(\'时间\',fontsize=20)
6 plt.xlabel(\'数值(百分点)\',fontsize=20)
7 plt.legend(fontsize=20)
8 plt.show()

运行结果:

 

1 #绘制1978年-2018年三大产业对GDP贡献率的盒图
2 plt.figure(figsize=(20,15))
3 plt.xticks(fontsize=20)
4 plt.yticks(fontsize=20)
5 sns.boxplot(data=Contribution_All).set_title("1978年-2018年三大产业对GDP贡献率的盒图",size=25)
6 plt.show()

运行结果:

 

1 #绘制1978年-2018年三大产业对GDP增长拉动的折线图
2 Promote.plot(figsize=(20,10),linewidth=2.5,marker=\'D\',linestyle=\'-.\').set_title(\'1978年-2018年三大产业对GDP增长拉动的折线图\',size=25)
3 plt.xticks(fontsize=20)
4 plt.yticks(fontsize=20)
5 plt.xlabel(\'时间\',fontsize=20)
6 plt.ylabel(\'数值(百分点)\',fontsize=20)
7 plt.legend(fontsize=20)
8 plt.show()

运行结果:

 

1 #绘制1978年-2018年GDP增长百分点的小提琴图
2 plt.figure(figsize=(10,10))
3 plt.xticks(fontsize=20)
4 plt.yticks(fontsize=20)
5 sns.violinplot(data=Contribution[\'国内生产总值增长(百分点)\']).set_title(\'1978年-2018年GDP增长百分点的小提琴图\',size=20)
6 plt.show()

运行结果:

 

5.数据持久化

上述已将相关数据以xlsx格式存入本地磁盘,实现数据持久化。

6.附完整程序代码

  1 #导入库
  2 import requests
  3 import json
  4 import os
  5 import pandas as pd
  6 import numpy as np
  7 import matplotlib.pyplot as plt
  8 
  9 #对数据接口进行http请求
 10 def getHTMLText(url):
 11     try:
 12         r = requests.get(url, timeout=30)   #获取信息,请求超时时间为30秒
 13         r.raise_for_status()   #如果状态不是200,则引发异常
 14         r.encoding = r.apparent_encoding   #配置编码
 15         return r.text   #返回url对应的页面内容
 16     except:
 17         return "产生异常"
 18 
 19 #对数据JSON化,并提取我们想要的内容
 20 def filterHTMLText(lst,wbdata):
 21     try:
 22         data = json.loads(wbdata)   #对HTTP响应的数据JSON化
 23         newdata = data[\'result\']    #索引到我们所要的位置
 24         for i in newdata:   #对索引出来的JSON数据进行遍历和提取
 25             target = i[\'zb\']      #提取“指标”内容
 26             data_time = i[\'sj\']   #提取“数据时间”内容
 27             value = i[\'data\']     #提取“数值”内容
 28             attribute = i[\'db\']   #提取“所属栏目”内容
 29             lst.append([target,data_time,value,attribute])   #将数据存放到lst列表里
 30         return lst    #返回lst数据列表
 31     except:
 32         return "产生异常"
 33 
 34 #保存数据,生成xlsx格式文件
 35 def saveHTMLText(lst):
 36     try:
 37         headers = [\'指标\',\'数据时间\',\'数值\',\'所属栏目\']   #设置columns名称
 38         index = [i for i in range(1,len(lst)+1)]         #设置index值
 39         df = pd.DataFrame(lst,columns=headers,index=index)   #将数据列表转换为DataFrame对象
 40         if not os.path.exists(\'F:\\\\PycharmProject\'):   #判断磁盘里是否存在目标文件夹
 41             os.makedirs(\'F:\\\\PycharmProject\')   #不存在,则创建该文件夹并且生成xlsx文件
 42             df.to_excel(\'F:\\\\PycharmProject\\\\国家统计局数据.xlsx\')   
 43         else:
 44             df.to_excel(\'F:\\\\PycharmProject\\\\国家统计局数据.xlsx\')
 45         print("保存成功")   #返回“保存成功”的提示
 46     except:
 47         print("保存失败")   #返回“保存失败”的提示
 48 
 49 #主程序
 50 def main():
 51     uList = []   #存储爬取到的数据
 52     for YearIndex in range(1978,2017):   #遍历1978-2016年的URL
 53         for PageIndex in range(0,6):     #遍历每一年前6页的URL
 54             url = "http://data.stats.gov.cn/search.htm?s={0}{1}&m=searchdata&db=&p={2}".format(YearIndex,\'GDP\',PageIndex)  
 55             html = getHTMLText(url)      #调用getHTMLText函数
 56             filterHTMLText(uList,html)   #调用filterHTMLText函数
 57     for PageIndex in range(0,6):   #遍历2017-2018年前6页的数据
 58             url = "http://data.stats.gov.cn/search.htm?s=GDP&m=searchdata&db=&p={0}".format(PageIndex)
 59             html = getHTMLText(url)
 60             filterHTMLText(uList,html) 
 61     saveHTMLText(uList)   Python高级应用程序设计任务

Python高级应用程序设计任务

Python高级应用程序设计任务

Python高级应用程序设计任务

Python高级应用程序设计任务

Python高级应用程序设计任务