一、选题的背景
本次选题,我想从我的大学所在城市泉州入手,分析泉州公交分布,了解绿色出行对人们生活的意义和人们对绿色出行的重视。
美丽泉州是人民群众的福祉。为贯彻落实《国务院关于实施健康中国行动的意见》,促进健康环境建设,为推进国家生态文明试点示范市建设,深化全国文明城市、卫生城市创建多作贡献。泉州市号召全市百姓积极践行绿色出行、低碳出行、文明出行。而城市公共交通是城市基础设施的重要组成部分,在我国经济发展、城市建设和社会生活中占有重要地位,它直接关系着城市的经济发展与居民生活,对城市经济具有全局性、先导性的影响。
二、主题式网络爬虫设计方案
1.主题式网络爬虫名称
基于高德开放平台|高德地图API爬取泉州公交有关数据并进行分析
2.主题式网络爬虫爬取的内容与数据特征分析
通过高德地图开放平台爬取有关的公交线路,并提取标签整理成数据集csv文件进行分析,分析主要通过公交线路,区间站点,全程长度,站点经纬度来对泉州公交普及分析。
3.主题式网络爬虫设计方案概述(包括实现思路与技术难点)
(1)实现思路
1.首先是获取数据集,具体是从高德地图API(https://lbs.amap.com/)获取key来获取,关于参数和标签头文件名获取,感谢高德开放平台下的开发指南提供了参数名获
2.取数据后对数据进行清洗整理进csv文件。
3.对csv文件进行分析及数据可视 化。
(2)技术难点
1.对数据的切片和分布读取
2.对数据进行清洗和处理
3.对可用数据的可视化处理
4.对冗余数据的处理
三、主题页面的结构与特征分析
1.主题页面的结构与特征分析
2.节点(标签)查找方法与遍历方法 (必要时画出节点树结构)
由于高德地图开放平台下的开发指南已经给出,所以不需要再寻找。
2.节点(标签)查找方法与遍历方法 (必要时画出节点树结构)
由于高德地图开放平台下的开发指南已经给出,所以不需要再寻找。
四、网络爬虫程序设计(60 分) 爬虫程序主体要包括以下各部分,要附源代码及较详细注释,并在每部分程序后 面提供输出结果的截图。
(1)数据爬取与采集
1. 先对url进行测试,查看是否能够正常返回数据
1 #爬取网页异常处理的通用框架 2 import requests 3 url = \'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=ad243f840dbda301f753ffd0436035b6&output=json&city={}&offset=1&keywords={}&platform=JS\' 4 5 def requests_caputure(): 6 try: 7 r=requests.get(url,timeout=30)#请求超时时间为30秒 8 r.raise_for_status()#如果状态不是200,则引发异常 9 r.encoding=r.apparent_encoding #配置编码 10 return r.text 11 except: 12 return "产生异常" 13 14 if __name__ == \'__main__\': 15 response=requests_caputure() 16 print(response[:100])
运行结果
2.对url进行爬取泉州公交线路的始发站、终点站、行驶路径(行车轨迹)、站点名称和坐标、行驶距离等与公交车有关的基本信息,并将其保存到Execl表格中。
1 #导入爬虫所需的库 2 import requests 3 import json 4 import pandas as pd 5 import time 6 7 #用于记录爬取公交线路所需要的时间函数 8 def record_time(flag): 9 if flag==0: 10 global t0 11 t0=time.time() 12 else: 13 t1=time.time() 14 print("用时:%.2fs"%(t1-t0)) 15 print(time.strftime(\'%Y-%m-%d %H:%M:%S\',time.localtime(time.time()))) 16 17 #获取公交基本信息 18 #具体参考:高德地图api 路径规划-API文档-开发指南 https://lbs.amap.com/api/webservice/guide/api/direction#bus_list 19 def get_station(cityname,line): 20 global bus_num 21 #获取当前公交线路数据 利用高德开放平台创建适用web端的key,爬取公交站点信息 22 url = \'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=ad243f840dbda301f753ffd0436035b6&output=json&city={}&offset=1&keywords={}&platform=JS\'.format(cityname,line) 23 r = requests.get(url).text #请求文本内容 24 rt = json.loads(r) #将json格式数据转换为字典 25 try: 26 #读取当前公交线路主要信息 27 dt = {} #先定义一个dt数据集 28 dt[\'公交线路\'] = rt[\'buslines\'][0][\'name\'] #公交线路名字 29 dt[\'始发站点\'] = rt[\'buslines\'][0][\'start_stop\'] #始发站 30 dt[\'终点站\'] = rt[\'buslines\'][0][\'end_stop\'] #终点站 31 dt[\'区间站点\'] = rt[\'buslines\'][0][\'bounds\'] #行车区间(非始发站,终点站坐标) 32 dt[\'全程长度\'] = rt[\'buslines\'][0][\'distance\'] #全程长度 33 34 #获取沿途站点站名、对应坐标和“第几站”信息 35 station_name = [] 36 station_coords = [] 37 station_sequence = [] 38 39 for st in rt[\'buslines\'][0][\'busstops\']: 40 station_name.append(st[\'name\']) 41 station_coords.append(st[\'location\']) 42 station_sequence.append(st[\'sequence\']) 43 44 dt[\'沿途站点名\'] = station_name #沿途站点名 45 dt[\'沿途站点坐标\'] = station_coords #沿途站点坐标 46 dt[\'沿途站点第几站\'] = station_sequence #沿途站点第几站 47 48 bus_num+=1 #有效公交数+1 49 50 return pd.DataFrame(dt) #返回pd.DataFrame()类型 51 52 except: #try语句部分出错进入此部分(一般为站点名错误) 53 print(\'没有{}公交\'.format(line)) #输出没有的公交线路名字 54 return pd.DataFrame([]) #返回空的pd.DataFrame类型 55 56 #获取当前城市所有公交基本信息:线路名、行车区间、全程长度、沿途站点及坐标 57 def Bus_info(city,for_num): 58 all_bus=pd.DataFrame() 59 for i in range(1,for_num+1): 60 all_bus=pd.concat([all_bus,get_station(city,str(i)+\'路\')]) #不加这个\'路\'可能优先获取地铁 61 print("Bus_info函数遍历{}前{}路公交,有效公交线路数为:{}个".format(city,for_num,bus_num)) 62 all_bus.to_csv("{}前{}路公交(有效线路数:{})基本信息.csv".format(city,for_num,bus_num),encoding=\'utf-8-sig\') 63 64 65 if __name__=="__main__": 66 record_time(0)#用于记录开始时间 67 68 bus_num=0 #全局变量,计算有效遍历的公交数 69 city=\'泉州\' #需要查询公交信息的城市 70 for_num=1000 #遍历的线路数[1路,for_num路],通常公交线路数小于1000,具体可参考8684等网站 71 Bus_info(city,for_num) 72 73 record_time(1)#用于记录结束时间并输出用时 74 75
运行结果
csv文件如下
(2)文本分析(可选):jieba 分词、wordcloud 的分词可视化
1. #绘制词云,查看出现最多的站点
1 # 绘制词云,查看出现最多的站点 2 import jieba 3 from pylab import * 4 from wordcloud import WordCloud 5 df = pd.read_csv(\'C:/Users/bb/python-jupyter noteboook/泉州前1000路公交(有效线路数:120)基本信息.csv\') 6 text = \'\' 7 for line in df[\'沿途站点名\']: 8 text += line 9 # 使用jieba模块将字符串分割为单词列表 10 cut_text = \' \'.join(jieba.cut(text)) 11 color_mask = imread(\'C:/Users/bb/python-jupyter noteboook/66.jpg\') #设置背景图 12 cloud = WordCloud( 13 14 background_color = \'white\', 15 # 对中文操作必须指明字体 16 font_path=\'C:\windows\Fonts\STZHONGS.TTF\', 17 mask = color_mask, 18 max_words = 50, 19 max_font_size = 200 20 ).generate(cut_text) 21 22 # 保存词云图片 23 cloud.to_file(\'qzword1cloud.jpg\') 24 plt.imshow(cloud) 25 plt.axis(\'off\') 26 plt.show()
运行结果
2.循环泉州市的1000路以内的公交,获取这些线路的:路线名、行车区间、路程长度、站点数、区间直线距离等数据,并计算出这些公交线路的平均长度、平均站点数、平均站距。
1 import requests 2 import json 3 import pandas as pd 4 import time 5 from math import sin, asin, cos, radians, sqrt 6 #获取公交信息:线路名、行车区间(坐标)、路程、行车区间直线距离等 7 def Bus_inf(city,line): 8 global bus_num #全局变量,用于计算公交数目 9 try: 10 #获取数据 11 url = \'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=a5b7479db5b24fd68cedcf24f482c156&output=json&city={}&offset=1&keywords={}&platform=JS\'.format(city,line) 12 r = requests.get(url).text 13 rt = json.loads(r) 14 #读取当前公交线路基本信息 15 dt = {} 16 dt[\'line_name\'] = rt[\'buslines\'][0][\'name\'] #公交线路名字 17 dt[\'bounds\'] = rt[\'buslines\'][0][\'bounds\'] #行车区间(不是始发站,终点站坐标!!!) 18 dt[\'distance\'] = float(rt[\'buslines\'][0][\'distance\']) #全程长度 19 dt[\'station\'] = int(rt[\'buslines\'][0][\'busstops\'][-1][\'sequence\']) #全程站点数(包括始发站和终点站) 20 dt[\'station_dis\'] = dt[\'distance\']/(dt[\'station\']-1) #该路线站距 21 #计算直线系数 和 非直线系数=1/直线系数 22 #以下为两套求直线的方法:(1)求行车区间 (2)求始发站到终点站距离 23 lng1,lat1 =rt[\'buslines\'][0][\'bounds\'].split(\';\')[0].split(\',\') 24 lng2,lat2 =rt[\'buslines\'][0][\'bounds\'].split(\';\')[1].split(\',\') 25 dt[\'straight\'] = Geodistance(float(lng1),float(lat1),float(lng2),float(lat2)) #计算区间bounds的直线距离 26 lng1,lat1 = rt[\'buslines\'][0][\'busstops\'][0][\'location\'].split(\',\') #始发站坐标 27 lng2,lat2 = rt[\'buslines\'][0][\'busstops\'][-1][\'location\'].split(\',\') #终点站坐标 28 dt[\'straight2\'] = Geodistance(float(lng1),float(lat1),float(lng2),float(lat2)) #始发站到终点站的直线距离 29 #首尾距离小于1km即认为存在上下行(环形线路) 30 if dt[\'straight2\']<1.0: 31 print(dt[\'line_name\']) 32 dt[\'straight\']=dt[\'straight\']*2 #环形线直线距离乘2 33 lng1,lat1 = rt[\'buslines\'][0][\'busstops\'][0][\'location\'].split(\',\') #始发站坐标 34 lng2,lat2 = rt[\'buslines\'][0][\'busstops\'][int(dt[\'station\']/2)][\'location\'].split(\',\') #中间站坐标 35 dt[\'straight2\'] = Geodistance(float(lng1),float(lat1),float(lng2),float(lat2))*2 #始发站到中间站点距离且需要*2 36 37 dt[\'straight_dis\'] = dt[\'straight\']/dt[\'distance\'] #直线系数1=直线长度/路程长度 (0,1] 38 dt[\'non_straight_dis\'] = dt[\'distance\']/dt[\'straight\'] #非直线系数1=路程长度/直线长度 [1,∞) 39 dt[\'straight_dis2\'] = dt[\'straight2\']/dt[\'distance\'] #直线系数2=直线长度/路程长度 (0,1] 40 dt[\'non_straight_dis2\'] = dt[\'distance\']/dt[\'straight2\'] #非直线系数2=路程长度/直线长度 [1,∞) 41 42 bus_num+=1 #有效公交数+1 43 return pd.DataFrame(dt,index=[bus_num]) #下标index为“第几条公交线” 44 except: 45 #print(\'没有{}公交\'.format(line)) #正常情况下,这条语句不会执行 46 return pd.DataFrame() #读取数据失败,返回空的 47 48 def Bus_analysis(bus_info): 49 print(\'公交线路的平均长度:{:.6f} km\'.format(bus_info["distance"].mean())) 50 print(\'公交线路的平均站点数:{:.6f} 个\'.format(bus_info[\'station\'].mean())) 51 print(\'公交线路的平均站距1为:{:.6f} km/站\'.format(bus_info["distance"].sum()/(bus_info[\'station\'].sum()-bus_num))) 52 print(\'公交线路的平均直线系数(区间距离):{:.6f}\'.format(bus_info[\'straight\'].sum()/bus_info["distance"].sum())) 53 print(\'公交线路的平均非直线系数(区间距离):{:.6f}\'.format(bus_info["distance"].sum()/bus_info[\'straight\'].sum())) 54 print(\'公交线路的平均直线系数(首位距离):{:.6f}\'.format(bus_info[\'straight2\'].sum()/bus_info["distance"].sum())) 55 print(\'公交线路的平均非直线系数(首位距离):{:.6f}\'.format(bus_info["distance"].sum()/bus_info[\'straight2\'].sum())) 56 57 if __name__=="__main__": 58 t0=time.time() 59 60 bus_num=0 #设置全局变量数值(通常默认就是0) 61 city=\'泉州\' #需要查询公交信息的城市 62 for_num=120 #遍历的线路数[1路,for_num路],通常公交线路数小于1000,具体可参考8684等网站 63 all_buslines=pd.DataFrame() 64 for i in range(1,for_num+1): 65 all_buslines=pd.concat([all_buslines,Bus_inf(city,str(i)+\'路\')]) #不加这个\'路\'可能优先获取地铁 66 67 print("Bus_info函数遍历{}前{}路公交,有效公交线路数为:{}个的情况下:".format(city,for_num,bus_num)) 68 Bus_analysis(all_buslines) 69 70 all_buslines.to_csv("{}前{}路公交(有效线路数:{})基本信息.csv".format(city,for_num,bus_num),encoding=\'utf-8-sig\') 71 72 t1=time.time() 73 print("用时:%.2fs"%(t1-t0))
运行结果
(3)数据分析与可视化(例如:数据柱形图、直方图、散点图、盒图、分布图)
1.基于经纬度做泉州公交站点分布散点图
1 #导入库 2 import numpy as np 3 import scipy as sp 4 import pandas as pd 5 import matplotlib 6 import matplotlib.pyplot as plt 7 from scipy.optimize import leastsq 8 import random 9 import matplotlib as mpl 10 df = pd.read_csv(\'C:/Users/bb/python-jupyter noteboook/泉州前1000路公交(有效线路数:120)基本信息.csv\') #导入泉州公交数据集 11 12 df[[\'经度\',\'纬度\']] = df[\'沿途站点坐标\'].str.split(\',\', n=1, expand=True) #因为爬取的经纬度在同一格,但是要分开,故采用切片。 13 df[\'经度\']=df[\'经度\'].astype(float) #转换双精度类型 14 df[\'纬度\'] = df[\'纬度\'].astype(float) 15 16 #设置x轴数据,有点冗余这一步,下一步也是 17 x_data =df[\'经度\'] 18 y_data = df[\'纬度\'] 19 20 #设置坐标点颜色 21 colors = [\'#FF0000\', \'#0000CD\', \'#00BFFF\', \'#008000\', \'#FF1493\', \'#FFD700\', \'#FF4500\', \'#00FA9A\', \'#191970\', \'#9932CC\'] 22 #随机坐标颜色 23 colors = [random.choice(colors) for i in range(len(x_data))] 24 mpl.rcParams[\'font.family\'] = \'SimHei\' #用来正常显示中文标签 25 plt.style.use(\'ggplot\') #利用matplotlib绘图设置背景,用plt.style.available查出可用样式列表 26 #plt.style.available 27 # 设置大小 28 plt.figure(figsize=(18, 10), dpi=200) 29 # 绘制散点图 经度 纬度 传进去 设置 颜色 点的大小 30 plt.scatter(x_data, y_data, marker="o", s=30., c=colors) 31 32 # 添加描述信息 x轴 y轴 标题 33 plt.xlabel("经度") 34 plt.ylabel("纬度") 35 plt.title("泉州市公交站点分布情况") 36 plt.savefig(\'经纬度散点图.png\') 37 plt.show()
运行结果
2.可视化查看泉州公交线路的全程长度对比
1 #导入库 2 import numpy as np 3 import scipy as sp 4 import pandas as pd 5 import matplotlib 6 import matplotlib.pyplot as plt 7 from scipy.optimize import leastsq 8 9 df = pd.read_csv(\'C:/Users/bb/python-jupyter noteboook/泉州前1000路公交(有效线路数:120)基本信息.csv\') 10 chinese=matplotlib.font_manager.FontProperties(fname=\'C:\Windows\Fonts\simsun.ttc\') #设置正常读取表格中中文名 11 12 # 创建figure对象,设置画布大小 13 14 plt.figure(figsize=(50,40)) 15 16 Xi=np.array(df[\'公交线路\']) 17 Yi=np.array(df[\'全程长度\']) 18 19 from pylab import * #从pylab中导入所有的非私有类,函数,全局变量等,* 代表所有, 20 mpl.rcParams[\'font.sans-serif\'] = [\'SimHei\'] 21 mpl.rcParams[\'axes.unicode_minus\'] = False 22 23 #绘制矩形图,x,y轴数据,表名,颜色 24 plt.barh(Xi, Yi, label="公交线路长度统计",color=[\'b\',\'orange\',\'g\',\'r\',\'purple\',\'#FF4500\', \'#00FA9A\',\'Pink\',\'#00BFFF\',\'y\',\'cyan\']) 25 26 plt.title(\'泉州公交路线路长柱形图\') 27 plt.xlabel(\'总路程(km)\') 28 plt.ylabel(\'公交号\') 29 plt.show()
运行结果
3.将以上各部分的代码汇总,附上完整程序代码
1 #爬取网页异常处理的通用框架 2 import requests 3 url = \'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=ad243f840dbda301f753ffd0436035b6&output=json&city={}&offset=1&keywords={}&platform=JS\' 4 5 def requests_caputure(): 6 try: 7 r=requests.get(url,timeout=30)#请求超时时间为30秒 8 r.raise_for_status()#如果状态不是200,则引发异常 9 r.encoding=r.apparent_encoding #配置编码 10 return r.text 11 except: 12 return "产生异常" 13 14 if __name__ == \'__main__\': 15 response=requests_caputure() 16 print(response[:100]) 17 18 19 #------------------------------------------------------------------- 20 import requests 21 import json 22 import pandas as pd 23 import time 24 from math import sin, asin, cos, radians, sqrt 25 #获取公交信息:线路名、行车区间(坐标)、路程、行车区间直线距离等 26 def Bus_inf(city,line): 27 global bus_num #全局变量,用于计算公交数目 28 try: 29 #获取数据 30 url = \'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=a5b7479db5b24fd68cedcf24f482c156&output=json&city={}&offset=1&keywords={}&platform=JS\'.format(city,line) 31 r = requests.get(url).text 32 rt = json.loads(r) 33 #读取当前公交线路基本信息 34 dt = {} 35 dt[\'line_name\'] = rt[\'buslines\'][0][\'name\'] #公交线路名字 36 dt[\'bounds\'] = rt[\'buslines\'][0][\'bounds\'] #行车区间(不是始发站,终点站坐标!!!) 37 dt[\'distance\'] = float(rt[\'buslines\'][0][\'distance\']) #全程长度 38 dt[\'station\'] = int(rt[\'buslines\'][0][\'busstops\'][-1][\'sequence\']) #全程站点数(包括始发站和终点站) 39 dt[\'station_dis\'] = dt[\'distance\']/(dt[\'station\']-1) #该路线站距 40 #计算直线系数 和 非直线系数=1/直线系数 41 #以下为两套求直线的方法:(1)求行车区间 (2)求始发站到终点站距离 42 lng1,lat1 =rt[\'buslines\'][0][\'bounds\'].split(\';\')[0].split(\',\') 43 lng2,lat2 =rt[\'buslines\'][0][\'bounds\'].split(\';\')[1].split(\',\') 44 dt[\'straight\'] = Geodistance(float(lng1),float(lat1),float(lng2),float(lat2)) #计算区间bounds的直线距离 45 lng1,lat1 = rt[\'buslines\'][0][\'busstops\'][0][\'location\'].split(\',\') #始发站坐标 46 lng2,lat2 = rt[\'buslines\'][0][\'busstops\'][-1][\'location\'].split(\',\') #终点站坐标 47 dt[\'straight2\'] = Geodistance(float(lng1),float(lat1),float(lng2),float(lat2)) #始发站到终点站的直线距离 48 #首尾距离小于1km即认为存在上下行(环形线路) 49 if dt[\'straight2\']<1.0: 50 print(dt[\'line_name\']) 51 dt[\'straight\']=dt[\'straight\']*2 #环形线直线距离乘2 52 lng1,lat1 = rt[\'buslines\'][0][\'busstops\'][0][\'location\'].split(\',\') #始发站坐标 53 lng2,lat2 = rt[\'buslines\'][0][\'busstops\'][int(dt[\'station\']/2)][\'location\'].split(\',\') #中间站坐标 54 dt[\'straight2\'] = Geodistance(float(lng1),float(lat1),float(lng2),float(lat2))*2 #始发站到中间站点距离且需要*2 55 56 dt[\'straight_dis\'] = dt[\'straight\']/dt[\'distance\'] #直线系数1=直线长度/路程长度 (0,1] 57 dt[\'non_straight_dis\'] = dt[\'distance\']/dt[\'straight\'] #非直线系数1=路程长度/直线长度 [1,∞) 58 dt[\'straight_dis2\'] = dt[\'straight2\']/dt[\'distance\'] #直线系数2=直线长度/路程长度 (0,1] 59 dt[\'non_straight_dis2\'] = dt[\'distance\']/dt[\'straight2\'] #非直线系数2=路程长度/直线长度 [1,∞) 60 61 bus_num+=1 #有效公交数+1 62 return pd.DataFrame(dt,index=[bus_num]) #下标index为“第几条公交线” 63 except: 64 #print(\'没有{}公交\'.format(line)) #正常情况下,这条语句不会执行 65 return pd.DataFrame() #读取数据失败,返回空的 66 67 def Bus_analysis(bus_info): 68 print(\'公交线路的平均长度:{:.6f} km\'.format(bus_info["distance"].mean())) 69 print(\'公交线路的平均站点数:{:.6f} 个\'.format(bus_info[\'station\'].mean())) 70 print(\'公交线路的平均站距1为:{:.6f} km/站\'.format(bus_info["distance"].sum()/(bus_info[\'station\'].sum()-bus_num))) 71 print(\'公交线路的平均直线系数(区间距离):{:.6f}\'.format(bus_info[\'straight\'].sum()/bus_info["distance"].sum())) 72 print(\'公交线路的平均非直线系数(区间距离):{:.6f}\'.format(bus_info["distance"].sum()/bus_info[\'straight\'].sum())) 73 print(\'公交线路的平均直线系数(首位距离):{:.6f}\'.format(bus_info[\'straight2\'].sum()/bus_info["distance"].sum())) 74 print(\'公交线路的平均非直线系数(首位距离):{:.6f}\'.format(bus_info["distance"].sum()/bus_info[\'straight2\'].sum())) 75 76 if __name__=="__main__": 77 t0=time.time() 78 79 bus_num=0 #设置全局变量数值(通常默认就是0) 80 city=\'泉州\' #需要查询公交信息的城市 81 for_num=120 #遍历的线路数[1路,for_num路],通常公交线路数小于1000,具体可参考8684等网站 82 all_buslines=pd.DataFrame() 83 for i in range(1,for_num+1): 84 all_buslines=pd.concat([all_buslines,Bus_inf(city,str(i)+\'路\')]) #不加这个\'路\'可能优先获取地铁 85 86 print("Bus_info函数遍历{}前{}路公交,有效公交线路数为:{}个的情况下:".format(city,for_num,bus_num)) 87 Bus_analysis(all_buslines) 88 89 all_buslines.to_csv("{}前{}路公交(有效线路数:{})基本信息.csv".format(city,for_num,bus_num),encoding=\'utf-8-sig\') 90 91 t1=time.time() 92 print("用时:%.2fs"%(t1-t0)) 93 94 #---------------------------------------------------------------------- 95 96 # 绘制词云,查看出现最多的站点 97 import jieba 98 from pylab import * 99 from wordcloud import WordCloud 100 df = pd.read_csv(\'C:/Users/bb/python-jupyter noteboook/泉州前1000路公交(有效线路数:120)基本信息.csv\') 101 text = \'\' 102 for line in df[\'沿途站点名\']: 103 text += line 104 # 使用jieba模块将字符串分割为单词列表 105 cut_text = \' \'.join(jieba.cut(text)) 106 color_mask = imread(\'C:/Users/bb/python-jupyter noteboook/66.jpg\') #设置背景图 107 cloud = WordCloud( 108 109 background_color = \'white\', 110 # 对中文操作必须指明字体 111 font_path=\'C:\windows\Fonts\STZHONGS.TTF\', 112 mask = color_mask, 113 max_words = 50, 114 max_font_size = 200 115 ).generate(cut_text) 116 117 # 保存词云图片 118 cloud.to_file(\'qzword1cloud.jpg\') 119 plt.imshow(cloud) 120 plt.axis(\'off\') 121 plt.show() 122 123 124 #---------------------------------------------------------------------- 125 #导入爬虫所需的库 126 import requests 127 import json 128 import pandas as pd 129 import time 130 131 #用于记录爬取公交线路所需要的时间函数 132 def record_time(flag): 133 if flag==0: 134 global t0 135 t0=time.time() 136 else: 137 t1=time.time() 138 print("用时:%.2fs"%(t1-t0)) 139 print(time.strftime(\'%Y-%m-%d %H:%M:%S\',time.localtime(time.time()))) 140 141 #获取公交基本信息 具体参考:高德地图api 路径规划-API文档-开发指南 https://lbs.amap.com/api/webservice/guide/api/direction#bus_list 142 def get_station(cityname,line): 143 global bus_num 144 #获取当前公交线路数据 利用高德开放平台创建适用web端的key,爬取公交站点信息 145 url = \'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=ad243f840dbda301f753ffd0436035b6&output=json&city={}&offset=1&keywords={}&platform=JS\'.format(cityname,line) 146 r = requests.get(url).text #请求文本内容 147 rt = json.loads(r) #将json格式数据转换为字典 148 try: 149 #读取当前公交线路主要信息 150 dt = {} #先定义一个dt数据集 151 dt[\'公交线路\'] = rt[\'buslines\'][0][\'name\'] #公交线路名字 152 dt[\'始发站点\'] = rt[\'buslines\'][0][\'start_stop\'] #始发站 153 dt[\'终点站\'] = rt[\'buslines\'][0][\'end_stop\'] #终点站 154 dt[\'区间站点\'] = rt[\'buslines\'][0][\'bounds\'] #行车区间(非始发站,终点站坐标) 155 dt[\'全程长度\'] = rt[\'buslines\'][0][\'distance\'] #全程长度 156 157 #获取沿途站点站名、对应坐标和“第几站”信息 158 station_name = [] 159 station_coords = [] 160 station_sequence = [] 161 162 for st in rt[\'buslines\'][0][\'busstops\']: 163 station_name.append(st[\'name\']) 164 station_coords.append(st[\'location\']) 165 station_sequence.append(st[\'sequence\']) 166 167 dt[\'沿途站点名\'] = station_name #沿途站点名 168 dt[\'沿途站点坐标\'] = station_coords #沿途站点坐标 169 dt[\'沿途站点第几站\'] = station_sequence #沿途站点第几站 170 171 bus_num+=1 #有效公交数+1 172 173 return pd.DataFrame(dt) #返回pd.DataFrame()类型 174 175 except: #try语句部分出错进入此部分(一般为站点名错误) 176 print(\'没有{}公交\'.format(line)) #输出没有的公交线路名字 177 return pd.DataFrame([]) #返回空的pd.DataFrame类型 178 179 #获取当前城市所有公交基本信息:线路名、行车区间、全程长度、沿途站点及坐标 180 def Bus_info(city,for_num): 181 all_bus=pd.DataFrame() 182 for i in range(1,for_num+1): 183 all_bus=pd.concat([all_bus,get_station(city,str(i)+\'路\')]) #不加这个\'路\'可能优先获取地铁 184 print("Bus_info函数遍历{}前{}路公交,有效公交线路数为:{}个".format(city,for_num,bus_num)) 185 all_bus.to_csv("{}前{}路公交(有效线路数:{})基本信息.csv".format(city,for_num,bus_num),encoding=\'utf-8-sig\') 186 187 188 if __name__=="__main__": 189 record_time(0)#用于记录开始时间 190 191 bus_num=0 #全局变量,计算有效遍历的公交数 192 city=\'泉州\' #需要查询公交信息的城市 193 for_num=1000 #遍历的线路数[1路,for_num路],通常公交线路数小于1000,具体可参考8684等网站 194 Bus_info(city,for_num) 195 196 record_time(1)#用于记录结束时间并输出用时 197 198 199 #---------------------------------------------------------------- 200 #导入库 201 import numpy as np 202 import scipy as sp 203 import pandas as pd 204 import matplotlib 205 import matplotlib.pyplot as plt 206 from scipy.optimize import leastsq 207 import random 208 import matplotlib as mpl 209 210 df = pd.read_csv(\'C:/Users/bb/python-jupyter noteboook/泉州前1000路公交(有效线路数:120)基本信息.csv\') #导入泉州公交数据集 211 #df.head() 212 213 df[[\'经度\',\'纬度\']] = df[\'沿途站点坐标\'].str.split(\',\', n=1, expand=True) #因为爬取的经纬度在同一格,但是要分开,故采用切片。 214 df[\'经度\']=df[\'经度\'].astype(float) #转换双精度类型 215 df[\'纬度\'] = df[\'纬度\'].astype(float) 216 217 #设置x轴数据,有点冗余这一步,下一步也是 218 x_data =df[\'经度\'] 219 y_data = df[\'纬度\'] 220 221 #设置坐标点颜色 222 colors = [\'#FF0000\', \'#0000CD\', \'#00BFFF\', \'#008000\', \'#FF1493\', \'#FFD700\', \'#FF4500\', \'#00FA9A\', \'#191970\', \'#9932CC\'] 223 #随机坐标颜色 224 colors = [random.choice(colors) for i in range(len(x_data))] 225 mpl.rcParams[\'font.family\'] = \'SimHei\' #用来正常显示中文标签 226 plt.style.use(\'ggplot\') #利用matplotlib绘图设置背景,用plt.style.available查出可用样式列表 227 #plt.style.available 228 # 设置大小 229 plt.figure(figsize=(18, 10), dpi=200) 230 # 绘制散点图 经度 纬度 传进去 设置 颜色 点的大小 231 plt.scatter(x_data, y_data, marker="o", s=30., c=colors) 232 233 # 添加描述信息 x轴 y轴 标题 234 plt.xlabel("经度") 235 plt.ylabel("纬度") 236 plt.title("泉州市公交站点分布情况") 237 plt.savefig(\'经纬度散点图.png\') 238 plt.show() 239 240 241 #---------------------------------------------------------------- 242 #导入库 243 import numpy as np 244 import scipy as sp 245 import pandas as pd 246 import matplotlib 247 import matplotlib.pyplot as plt 248 from scipy.optimize import leastsq 249 250 df = pd.read_csv(\'C:/Users/bb/python-jupyter noteboook/泉州前1000路公交(有效线路数:120)基本信息.csv\') 251 chinese=matplotlib.font_manager.FontProperties(fname=\'C:\Windows\Fonts\simsun.ttc\') #设置正常读取表格中中文名 252 253 # 创建figure对象,设置画布大小 254 255 plt.figure(figsize=(50,40)) 256 257 Xi=np.array(df[\'公交线路\']) 258 Yi=np.array(df[\'全程长度\']) 259 260 from pylab import * #从pylab中导入所有的非私有类,函数,全局变量等,* 代表所有, 261 mpl.rcParams[\'font.sans-serif\'] = [\'SimHei\'] 262 mpl.rcParams[\'axes.unicode_minus\'] = False 263 264 #绘制矩形图,x,y轴数据,表名,颜色 265 plt.barh(Xi, Yi, label="公交线路长度统计",color=[\'b\',\'orange\',\'g\',\'r\',\'purple\',\'#FF4500\', \'#00FA9A\',\'Pink\',\'#00BFFF\',\'y\',\'cyan\']) 266 267 plt.title(\'泉州公交路线路长柱形图\') 268 plt.xlabel(\'总路程(km)\') 269 plt.ylabel(\'公交号\') 270 plt.show()
五、总结(10 分)
(1)经过对主题数据的分析与可视化,可以得到哪些结论?是否达到预期的目标?
结论:
1.泉州的公交系统十分发达
2.k207路是泉州行进路程最长一路
3.泉州交通资源利用率较高
2.在完成此设计过程中,得到哪些收获?以及要改进的建议?
收获:
1.通过上面的数据获取、分析与统计,我们不难看出公共交通作为城市经济和民生中最为重要的基础性设施,重视政府在城市公共交通中的重要地位和作用,提高对公共交通的政策扶持力度,进一步规范公共市场行为,提高公共交通企业市场竞争力.
2.从整个数据爬取项目中我学习了许多新的知识内容,对之前学习的内容进行了巩固。
建议:
需要改进的建议在于爬取的数据可分析的方向太少,下次可以尝试向公交的其他方面拓展。