通过前面的探究,我们大体知道如何获取一个城市的公交数据,并绘制了公交行驶路径散点图(效果不是很理想)。
其实散点图感觉更适合类似于绘制公交站点这样的信息(行驶轨迹有其他更好的绘制技巧),故本篇博客将整理之前爬取公交数据的代码,可视化相关公交站点信息,并透过可视化信息知道哪些站点是关键站点!
和之前一样,本文依旧是基于青岛市来分析
(1)青岛前20路公交基本信息
我(最近)写代码一个基本原则就是,大家拿去就能运行
当然,基本的运行环境得保证没问题,本博客为:Anaconda 中的Spyder软件
(补充说明:bounds变量行车区间(非始发站,终点站坐标),是一个类似对角线的概念!)
import requests
import json
import pandas as pd
import time
#自己写的用于记录时间函数
def record_time(flag):
if flag==0:
global t0
t0=time.time()
else:
t1=time.time()
print("用时:%.2fs"%(t1-t0))
print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
#获取公交基本信息
def get_station(cityname,line):
global bus_num
#1、获取当前公交线路数据
url = 'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=a5b7479db5b24fd68cedcf24f482c156&output=json&city={}&offset=1&keywords={}&platform=JS'.format(cityname,line)
r = requests.get(url).text
rt = json.loads(r)
try:
#2、读取当前公交线路主要信息
dt = {}
dt['line_name'] = rt['buslines'][0]['name'] #公交线路名字
dt['start_stop'] = rt['buslines'][0]['start_stop'] #始发站
dt['end_stop'] = rt['buslines'][0]['end_stop'] #终点站
dt['bounds'] = rt['buslines'][0]['bounds'] #行车区间(非始发站,终点站坐标)
dt['distance'] = rt['buslines'][0]['distance'] #全程长度
#3、获取沿途站点站名、对应坐标和“第几站”信息
station_name = []
station_coords = []
station_sequence = []
for st in rt['buslines'][0]['busstops']:
station_name.append(st['name'])
station_coords.append(st['location'])
station_sequence.append(st['sequence'])
dt['station_name'] = station_name #沿途站点名
dt['station_coords'] = station_coords #沿途站点坐标
dt['station_sequence'] = station_sequence #沿途站点第几站
bus_num+=1 #有效公交数+1
return pd.DataFrame(dt) #返回pd.DataFrame()类型
except: #try语句部分出错进入此部分(一般为站点名错误)
print('没有{}公交'.format(line)) #输出没有的公交线路名字,可省略
return pd.DataFrame([]) #返回空的pd.DataFrame类型
#获取当前城市所有公交基本信息:线路名、行车区间、全程长度、沿途站点及坐标
def Bus_info(city,for_num):
all_bus=pd.DataFrame()
for i in range(1,for_num+1):
all_bus=pd.concat([all_bus,get_station(city,str(i)+'路')]) #不加这个'路'可能优先获取地铁
print("Bus_info函数遍历{}前{}路公交,有效公交线路数为:{}个".format(city,for_num,bus_num))
all_bus.to_csv("{}前{}路公交(有效线路数:{})基本信息.csv".format(city,for_num,bus_num),encoding='utf-8-sig')
if __name__=="__main__":
record_time(0)#用于记录开始时间
bus_num=0 #全局变量,计算有效遍历的公交数
city='青岛' #需要查询公交信息的城市
for_num=20 #遍历的线路数[1路,for_num路],通常公交线路数小于1000,具体可参考8684等网站
Bus_info(city,for_num)
record_time(1)#用于记录结束时间并输出用时
(3)站点位置可视化(部分)
绘图工具:高德开放平台|Map Lab(不是很难,摸索摸索,很快就能上手!)
下图中,颜色深表示有重合
(1)直接可运行出结果的代码
和上面一样,爬取青岛市前20路的公交,只获取行驶轨迹的坐标
import requests
import json
import pandas as pd
import time
#自己写的用于记录时间函数
def record_time(flag):
if flag==0:
global t0
t0=time.time()
else:
t1=time.time()
print("用时:%.2fs"%(t1-t0))
print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
#获取公交的行驶轨迹数据
def get_line(cityname,line,path,num):
url = 'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=a5b7479db5b24fd68cedcf24f482c156&output=json&city={}&offset=1&keywords={}&platform=JS'.format(cityname,line)
r = requests.get(url).text
rt = json.loads(r)
try:
polyline=rt['buslines'][0]['polyline']
path=path+polyline
return num+1,path
except:
print('没有{}公交'.format(line)) #正常情况下,这条语句不会执行
return num,path
#获取当前城市所有公交的行驶轨迹
def Bus_lines(city,for_num):
path_str=''
bus_num=0
for i in range(1,for_num+1):
bus_num,path_str=get_line(city,str(i)+'路',path_str,bus_num)
path={}
path['station_coords']=path_str.split(";")
print("Bus_lines函数遍历{}前{}路公交,有效公交线路数为:{}个,轨迹坐标为:{}条".format(city,for_num,bus_num,len(path['station_coords'])))
pd.DataFrame(path).to_csv('{}前{}路公交(有效线路数:{})轨迹坐标数据.csv'.format(city,for_num,bus_num),index=False,encoding='utf-8')
if __name__=="__main__":
record_time(0)
city='青岛' #需要查询公交信息的城市
for_num=20 #遍历的线路数[1路,for_num路],通常公交线路数小于1000,具体可参考8684等网站
bus_num=0 #全局变量,计算有效遍历的公交数
Bus_lines(city,for_num)
record_time(1)
(2)运行结果
保存的表格自由坐标数据,5935条
(3)结合站点可视化(部分)
站点为红色,路径为黄色,深色部分表示有重合
这个时候我们就会思考:能不能将轨迹图用不同颜色标注出来?
(1)能直接出结果的代码
因为2部分获取代码的方式特殊性,这里的功能看似和2变化不大(就加了个线路名),实际改动的地方还挺多的
import requests
import json
import pandas as pd
#获取公交的行驶轨迹数据
def get_line(cityname,line):
global bus_num
url = 'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=a5b7479db5b24fd68cedcf24f482c156&output=json&city={}&offset=1&keywords={}&platform=JS'.format(cityname,line)
r = requests.get(url).text
rt = json.loads(r)
try:
path={}
polyline=rt['buslines'][0]['polyline'] #获取公交路径名字
path['station_coords']=polyline.split(";") #拆分路径,将其分布于各行中
path['line_name'] = rt['buslines'][0]['name'] #获取公交线路名字
bus_num+=1
return pd.DataFrame(path)
except:
print('没有{}公交'.format(line)) #正常情况下,这条语句不会执行
return pd.DataFrame()
#获取当前城市所有公交的行驶轨迹
def Bus_lines(city,for_num):
all_buslines=pd.DataFrame()
for i in range(1,for_num+1):
all_buslines=pd.concat([all_buslines,get_line(city,str(i)+'路')]) #不加这个'路'可能优先获取地铁
print("Bus_lines函数遍历{}前{}路公交,有效公交线路数为:{}个,轨迹坐标为:{}条".format(city,for_num,bus_num,len(all_buslines['station_coords'])))
all_buslines.to_csv('{}前{}路公交(有效线路数:{})轨迹坐标数据.csv'.format(city,for_num,bus_num),index=False,encoding='utf-8-sig')
if __name__=="__main__":
city='青岛' #需要查询公交信息的城市
for_num=20 #遍历的线路数[1路,for_num路],通常公交线路数小于1000,具体可参考8684等网站
bus_num=0 #全局变量,计算有效遍历的公交数
Bus_lines(city,for_num)
(2)实验结果:
(3)可视化效果(部分)
高德地图只支持同时显示7种不同线路颜色,emmmm,其实效果还不错!
(1)分析
通过for循环的方法自然有其优越性:给个大体范围,等上几分钟,就能出所需要城市的几乎所有线路的公交信息!
但是,这样获取终究难免会有遗漏,而且也不能指定特定区域,故这里通过8684青岛公交获取了青岛市区所有公交线路,并演示在获取公交名文本的情况下,如何读取对应公交信息。
(2)通过读取文本获取公交相关信息
import requests
import json
import pandas as pd
import time
#自己写的用于记录时间函数
def record_time(flag):
if flag==0:
global t0
t0=time.time()
else:
t1=time.time()
print("用时:%.2fs"%(t1-t0))
print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
#获取公交基本信息
def get_station(cityname,line):
#1、获取当前公交线路数据
url = 'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=a5b7479db5b24fd68cedcf24f482c156&output=json&city={}&offset=1&keywords={}&platform=JS'.format(cityname,line)
r = requests.get(url).text
rt = json.loads(r)
try:
#2、读取当前公交线路主要信息
dt = {}
dt['line_name'] = rt['buslines'][0]['name'] #公交线路名字
dt['start_stop'] = rt['buslines'][0]['start_stop'] #始发站
dt['end_stop'] = rt['buslines'][0]['end_stop'] #终点站
dt['bounds'] = rt['buslines'][0]['bounds'] #行车区间(始发站,终点站坐标)
dt['distance'] = rt['buslines'][0]['distance'] #全程长度
#3、获取沿途站点站名、对应坐标和“第几站”信息
station_name = []
station_coords = []
station_sequence = []
for st in rt['buslines'][0]['busstops']:
station_name.append(st['name'])
station_coords.append(st['location'])
station_sequence.append(st['sequence'])
dt['station_name'] = station_name #沿途站点名
dt['station_coords'] = station_coords #沿途站点坐标
dt['station_sequence'] = station_sequence #沿途站点第几站
return pd.DataFrame(dt) #返回pd.DataFrame()类型
except: #try语句部分出错进入此部分(一般为站点名错误)
print('没有{}公交'.format(line)) #指定公交路线情况下,词条语句不会执行!
return pd.DataFrame() #返回空的pd.DataFrame类型
#获取青岛市区所有公交基本信息:线路名、行车区间、全程长度、沿途站点及坐标
def Bus_info():
with open("公交线路.txt", "r", encoding="utf-8") as f:
bus_name = f.readlines() #读取当前文件夹公交车线路名
bus_name = bus_name[0].split(",") #将获取的线路名文件通过','进行拆分
all_bus=pd.DataFrame()
for i in bus_name:
all_bus=pd.concat([all_bus,get_station('青岛',i)])
print("获取青岛市区{}条路线基本信息成功!".format(len(bus_name)))
all_bus.to_csv("青岛市区{}条路线基本信息.csv".format(len(bus_name)),encoding='utf-8-sig')
if __name__=="__main__":
record_time(0)#用于记录开始时间
Bus_info() #已知文本具体信息都有,不需要传参
record_time(1)#用于记录结束时间并输出用时
(4)青岛市区256条线路站点位置可视化
①市区站点鸟瞰图
深颜色代表重合(多条线路汇集处),密恐不知道感觉咋样?
②站点分布⭐形图
这样一来,哪些站点是关键站点就比较清楚了
③站点热度分布示意图
觉得上图分布还不够直观?那就来看看大小点图
⑤来点小汽车?
青岛几个关键的景点都在这张图里了<( ̄︶ ̄)↗[GO!]
其实这篇博客还是蛮实用的,得到的城市公交站点热度分布效果挺不错的!
找一个你感兴趣的城市(家乡)试一试?( •̀ .̫ •́ )✧