今天是2021.4.11,距离上次写博客已经有半年之久了,遥想半年之前,刚刚结束了在新浪的实习,踏上坎坷的秋招之路。那时的我才发现,自己掌握的知识竟是如此匮乏,不仅深度和广度都远远不够,甚至连基础都掌握不牢,技能更是一穷二白,而这一悲惨的现状竟然延续到了今天。
回顾过去的半年,虽然找到了工作,写完了毕业论文,但在专业技术上仍然可以说是顿足不前,寒假带回去的两本书原封不动的带了回来,电脑却又新购置了一台,属实让人汗颜。
今天破天荒的登上了博客,原因是完成了一个小的功能,虽然代码仍然写得惨不忍睹,但是结果还是不错的,我也有了动力写写2021年的第一篇博客。
起因是和同门聊到租房,我一边抱怨我和女票的单位离的有一点远不知道怎么租房,一边在百度地图上想要在两个单位间找到一个中点,作为租房的候选位置。找来找去发现中点附近的车站到我俩的单位都得换乘,没有一个车站能够让我们不经过换乘就到达各自的单位。就在我百无聊赖的一个个车站乱点时,我发现每个车站都会标明经过该车站的所有公交车。此时我脑中冒出一个想法,如果爬取两人所在公司门口车站中所有的公交车,再将其路线图复现出来,找到经过两人公司门口公交车线路的交点,不就能够找到所有租房的可能了吗。之后再找到最合适的点就不在话下了。
想到这里,我十分激动。说干就。。。晚上再干吧,还得改论文呢,ε=(´ο`*)))唉。
到了晚上,我强忍住LOL一把的冲动,打开了百度地图,观察了一会儿,发现此事可行!原因是可以在源代码里找到路线上每一个点的数据,包含站点名,left到左边界相对位置,和top到上边界的相对位置。
然后我简单尝试了一下,requests.get果然是爬不到源代码的,放弃,那就一个个粘呗。
过了一会儿,我终于粘好了8条线路的数据,写出了我第一个代码
import re
point_list = []
html = """数据"""
data_list = html.split("</div>")
for data in data_list[:-2]:
title = re.search('title=\"(.*?)\"', data).group(1)
left = float(re.search('left: (.*?)px;', data).group(1))
top = 937-float(re.search('top: (.*?)px;', data).group(1))
if title == "北京市海淀区G109(晋元桥)":
p1 = (left, top)
if title == "北京市海淀区万柳西路":
p2 = (left, top)
if title and title != "我的家" and title != "北京市海淀区G109(晋元桥)" and title != "北京市海淀区万柳西路" :
point_list.append([left,top,title])
distance = ((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)**0.5
for point in point_list:
point[0] = (point[0]-p1[0])/distance*100
point[1] = (point[1]-p1[1])/distance*100
print(point_list)
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False ## 设置正常显示符号
X = np.array([point[0] for point in point_list])
Y = np.array([point[1] for point in point_list])
plt.figure(figsize=(10,10))
plt.plot(X, Y)
# plt.ylim(ymin = 0, ymax = 937)
# plt.xlim(xmin = 0, xmax = 1365)
for i in range(len(point_list)):
plt.scatter(point_list[i][0], int(point_list[i][1]), color='b')
txt = [point[2] for point in point_list]
plt.rcParams['font.sans-serif']=['SimHei']
for i in range(len(point_list)):
plt.annotate(txt[i], xy = (point_list[i][0], point_list[i][1]), xytext = (point_list[i][0]+.1, point_list[i][1]+1))
程序的大概意思就是找到每个点的横纵坐标和名字,然后把它描绘出来。但是由于这个坐标是相对坐标,所以肯定是不准的,你缩小一下地图,这些坐标都会变化。但我们最后要把所线路放到一张图上,比例尺一定要一样,这里我选择在地图上找两个固定的点p1(x1,y1)和p2(x2,y2),p1和p2的距离distance=(x1 - x2)2 + (y1 - y2)2)**0.5。每次读取了坐标信息后的点p(x,y)后,将((x-x1)/distance, (y-y1)/distance)作为该点的真实坐标。因为两固定点之间距离是固定的,除去distance之后就将比例尺统一了。
整出来就是这么一个样子:(其实前面还有好几版,开始写的根本跑不出来。。。)
而原图是这么一个样子:
我giao,大概方向是对的,但是失真很明显,为什么会失真呢,后来才发现是因为画图时自动把Y轴拉长了。。。继续
把所有线路叠加之后的效果:
单人线路图有一个问题,百度地图上的相对坐标都是整数,所以带来了失真,导致本来该在一起的站点在图上错开了。我的做法是找到一个公共点,对比不同线路在这个点上的误差,对没条线路坐标进行更新,简单来说就是差多少补多少。最后虽然还是没有完全重合,但是总归是好些了。
最后就是把两张图重合在一起,再找到相交的站点,这一步同样需要两张图间的同步,找到一个公共站点消除误差,不然误差有点大。得到最后的图:
再把相交站点和通过的线路加上:
齐活!虽然不知道这个是代码怎么跑起来的,但是:
附上代码
import re
name1 = 马赛克
name2 = 马赛克
point_list_list1 = []
html_list1 = [
"""
马赛克
""",
]
point_list_list2 = []
html_list2 = [
"""
马赛克
""",
]
for index in range(len(html_list1)):
html = html_list1[index]
point_list = []
data_list = html.split("</div>")
for data in data_list[:-2]:
title = re.search('title=\"(.*?)\"', data).group(1)
left = float(re.search('left: (.*?)px;', data).group(1))
top = 937-float(re.search('top: (.*?)px;', data).group(1))
if title == "北京市海淀区G109(晋元桥)":
p1 = (left, top)
if title == "北京市海淀区万柳西路":
p2 = (left, top)
if title and title != "我的家" and title != "北京市海淀区G109(晋元桥)" and title != "北京市海淀区万柳西路" :
point_list.append([left,top,title,name1[index]])
distance = ((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)**0.5
for point in point_list:
point[0] = (point[0]-p1[0])/distance*100
point[1] = (point[1]-p1[1])/distance*100
for point in point_list:
if point[2] == '马赛克':
cur_loc = (point[0], point[1])
if point[2] == '马赛克':
p1_loc = (point[0], point[1])
for point in point_list:
point[0] = point[0] - (cur_loc[0] - simble_loc[0])
point[1] = point[1] - (cur_loc[1] - simble_loc[1])
point_list_list1.append(point_list)
for index in range(len(html_list2)):
html = html_list2[index]
point_list = []
data_list = html.split("</div>")
for data in data_list[:-2]:
title = re.search('title=\"(.*?)\"', data).group(1)
left = float(re.search('left: (.*?)px;', data).group(1))
top = 937-float(re.search('top: (.*?)px;', data).group(1))
if title == "北京市海淀区G109(晋元桥)":
p1 = (left, top)
if title == "北京市海淀区万柳西路":
p2 = (left, top)
if title and title != "我的家" and title != "北京市海淀区万柳西路" and title != "北京市海淀区G109(晋元桥)" :
point_list.append([left,top,title,name2[index]])
distance = ((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)**0.5
for point in point_list:
point[0] = (point[0]-p1[0])/distance*100
point[1] = (point[1]-p1[1])/distance*100
for point in point_list:
if point[2] == '马赛克':
cur_loc = (point[0], point[1])
if point[2] == '马赛克':
p2_loc = (point[0], point[1])
for point in point_list:
point[0] = point[0] - (cur_loc[0] - simble_loc[0])
point[1] = point[1] - (cur_loc[1] - simble_loc[1])
point_list_list2.append(point_list)
for point_list in point_list_list2:
for point in point_list:
point[0] = point[0] - (p2_loc[0] - p1_loc[0])
point[1] = point[1] - (p2_loc[1] - p1_loc[1])
station_line_dic1 = dict()
for point_list in point_list_list1:
for point in point_list:
station = point[2]
line = point[3]
if station not in station_line_dic1.keys():
station_line_dic1[station] = []
station_line_dic1[station].append(line)
station_line_dic2 = dict()
for point_list in point_list_list2:
for point in point_list:
station = point[2]
line = point[3]
if station not in station_line_dic2.keys():
station_line_dic2[station] = []
station_line_dic2[station].append(line)
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize=(100,100))
# plt.ylim(ymin = -200, ymax = 200)
# plt.xlim(xmin = -200, xmax = 200)
already_txt1 = []
for point_list in point_list_list1:
X = np.array([point[0] for point in point_list])
Y = np.array([point[1] for point in point_list])
plt.plot(X, Y , color="orange")
for i in range(len(point_list)):
plt.scatter(point_list[i][0], int(point_list[i][1]), color='b')
txt = [point[2] for point in point_list]
plt.rcParams['font.sans-serif']=['SimHei']
for i in range(len(point_list)):
if txt[i] not in already_txt1:
plt.annotate(txt[i], xy = (point_list[i][0], point_list[i][1]), xytext = (point_list[i][0]+.1, point_list[i][1]+1))
already_txt1.append(txt[i])
already_txt2 = []
for point_list in point_list_list2:
X = np.array([point[0] for point in point_list])
Y = np.array([point[1] for point in point_list])
plt.plot(X, Y , color="blue")
for i in range(len(point_list)):
plt.scatter(point_list[i][0], int(point_list[i][1]), color='b')
txt = [point[2] for point in point_list]
plt.rcParams['font.sans-serif']=['SimHei']
for i in range(len(point_list)):
if txt[i] not in already_txt2:
plt.annotate(txt[i], xy = (point_list[i][0], point_list[i][1]), xytext = (point_list[i][0]+.1, point_list[i][1]+1))
already_txt2.append(txt[i])
for txt1 in already_txt1:
for txt2 in already_txt2:
if txt1 == txt2:
print(txt1)
print("马赛克:", station_line_dic1[txt1])
print("马赛克:", station_line_dic2[txt1])
plt.show()