1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > python外环是什么意思_爬取上海地铁站并且规划出行路线

python外环是什么意思_爬取上海地铁站并且规划出行路线

时间:2021-01-18 00:45:13

相关推荐

python外环是什么意思_爬取上海地铁站并且规划出行路线

源码源码:源码链接

需求和目标

爬取网站:上海地铁的百科词条

获取的爬虫数据结果保存样式如下

{

'莘庄站':

{'subway': ['上海地铁1号线', '上海地铁5号线'],

'neibour': ['外环路站', '春申路站']},

'莲花路站':

{'subway': ['上海地铁1号线'],

'neibour': ['外环路站', '锦江乐园站']}

}

爬取的数据保存中这种格式是为了方便后续处理

根据爬取的数据可以根据起点和终点规划出行路线

爬虫步骤:

爬取上海地铁的百科词条,获取到地铁线路的名称和链接

爬取地铁详情页,提取站点信息并保存

爬虫部分

class ShangHaiSubway:

def __init__(self):

self.headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'

}

self.url = '/item/%E4%B8%8A%E6%B5%B7%E5%9C%B0%E9%93%81/1273732?fr=aladdin'

self.station_dict = defaultdict(list)

def get_xpath_obj(self, url):

'''根据url获取xpath对象'''

response = requests.get(url, headers=self.headers)

text = response.content.decode()

return etree.HTML(text)

def get_subways(self, xpath_obj):

'''解析xpath 对象,获取地铁的链接和地铁名称'''

subways = xpath_obj.xpath('//table[@log-set-param="table_view"][1]//tr/td//a')

for subway in subways:

name = subway.xpath('./text()')

href = subway.xpath('./@href')

if not all([name, href]): continue

name = name[0]

href = '' + href[0]

yield name, href

def get_stations(self, subway_name, href):

'''访问地铁链接,获取到地铁线路的每一个站点,构造最终数据'''

xpath_obj = self.get_xpath_obj(href)

stations = xpath_obj.xpath('//table[@log-set-param="table_view"][1]//tr')

before = None

for station in stations:

station = station.xpath('./td')

if len(station) <= 1: continue

flag = len(station)

station = station[0].xpath('.//text()')

if not station: continue

if station[0] in ['站名', '车站', '内圈']: continue

if station[0].startswith('往') and flag == 2: continue

station = station[0]

if self.station_dict[station]:

self.station_dict[station]['subway'].append(subway_name)

if before:

self.station_dict[station]['neibour'].append(before)

self.station_dict[before]['neibour'].append(station)

before = station

else:

if before:

self.station_dict[station] = {

'subway': [subway_name], 'neibour': [before]

}

self.station_dict[before]['neibour'].append(station)

else:

self.station_dict[station] = {

'subway': [subway_name], 'neibour': []

}

before = station

def run(self):

xpath_obj = self.get_xpath_obj(self.url)

for name, href in self.get_subways(xpath_obj):

self.get_stations(name, href)

return self.station_dict

根据爬取到的数据规划路线

详细逻辑解释参考这篇博客

def search(start, destination, connection_graph, sort_rule):

'''

connection_graph: 站点关系拓扑图

'''

# 所有行程解决方案

pathes = [[start]]

visited = set()

while pathes:

# 单个行程解决方案

path = pathes.pop(0)

middle_point = path[-1]

if middle_point in visited: continue

# print(connection_graph,middle_point,'mid')

if not connection_graph[middle_point]:

print('输入地铁站有误')

break

successors = connection_graph[middle_point]['neibour']

for city in successors:

if city in path: continue

new_path = path + [city]

pathes.append(new_path)

if city == destination:

print('path:', pathes)

return new_path

visited.add(middle_point)

pathes.append(new_path)

pathes = sort_rule(pathes)

def least(pathes):

pathes.sort(key=len)

return pathes

if __name__ == '__main__':

shang_hai_subway = ShangHaiSubway()

station_dict = shang_hai_subway.run()

print(station_dict)

path = search('杨高南路站','莘庄站',station_dict,least)

for s in path:

print(s+str(station_dict[s]['subway'])+'↓')

结果如下

杨高南路站['上海地铁7号线']↓

高科西路站['上海地铁6号线', '上海地铁7号线']↓

东明路站['上海地铁6号线', '上海地铁13号线']↓

成山路站['上海地铁8号线', '上海地铁13号线']↓

长清路站['上海地铁7号线', '上海地铁13号线']↓

后滩站['上海地铁7号线']↓

龙华中路站['上海地铁7号线', '上海地铁12号线']↓

龙华站['上海地铁11号线', '上海地铁12号线']↓

龙漕路站['上海地铁3号线', '上海地铁12号线']↓

石龙路站['上海地铁3号线']↓

上海南站站['上海地铁1号线', '上海地铁3号线']↓

锦江乐园站['上海地铁1号线']↓

莲花路站['上海地铁1号线']↓

外环路站['上海地铁1号线']↓

莘庄站['上海地铁1号线', '上海地铁5号线']↓

显示还不够,没有换乘提示,继续优化:

if __name__ == '__main__':

shang_hai_subway = ShangHaiSubway()

station_dict = shang_hai_subway.run()

print(station_dict)

path = search('杨高南路站', '莘庄站', station_dict, least)

# for s in path:

# print(s+str(station_dict[s]['subway'])+'↓')

subway = None

for i in range(len(path) - 1):

station = path[i]

if len(station_dict[station]['subway']) == 1:

subway = station_dict[station]['subway'][0]

else:

new_subway = set(station_dict[path[i + 1]]['subway']) & set(station_dict[path[i]]['subway'])

new_subway = new_subway.pop()

if not subway:

subway = new_subway

else:

if new_subway != subway:

print('换乘到', new_subway)

subway = new_subway

print(station, subway)

print(path[-1],subway)

结果如下

杨高南路站 上海地铁7号线

换乘到 上海地铁6号线

高科西路站 上海地铁6号线

换乘到 上海地铁13号线

东明路站 上海地铁13号线

成山路站 上海地铁13号线

换乘到 上海地铁7号线

长清路站 上海地铁7号线

后滩站 上海地铁7号线

换乘到 上海地铁12号线

龙华中路站 上海地铁12号线

龙华站 上海地铁12号线

换乘到 上海地铁3号线

龙漕路站 上海地铁3号线

石龙路站 上海地铁3号线

换乘到 上海地铁1号线

上海南站站 上海地铁1号线

锦江乐园站 上海地铁1号线

莲花路站 上海地铁1号线

外环路站 上海地铁1号线

莘庄站 上海地铁1号线

可以看到刚才我们7号线应该是可以不换乘的但是我们的排序策略是经历的总站数最少而不是换乘最少。其实高德地图之前是两种策略都会提供。现在我已不在魔都了。我们现在来定义换乘最少的排序规则

def least_change(pathes):

def get_change_times(path):

subway = None

times = 0

for i in range(len(path) - 1):

station = path[i]

if len(station_dict[station]['subway']) == 1:

subway = station_dict[station]['subway'][0]

else:

new_subway = set(station_dict[path[i + 1]]['subway']) & set(station_dict[path[i]]['subway'])

new_subway = new_subway.pop()

if not subway:

subway = new_subway

else:

if new_subway != subway:

times += 1

subway = new_subway

return times

pathes.sort(key=get_change_times)

return pathes

新的排序规则结果如下

杨高南路站 上海地铁7号线

高科西路站 上海地铁7号线

云台路站 上海地铁7号线

耀华路站 上海地铁7号线

长清路站 上海地铁7号线

后滩站 上海地铁7号线

换乘到 上海地铁12号线

龙华中路站 上海地铁12号线

龙华站 上海地铁12号线

龙漕路站 上海地铁12号线

换乘到 上海地铁1号线

漕宝路站 上海地铁1号线

上海南站站 上海地铁1号线

锦江乐园站 上海地铁1号线

莲花路站 上海地铁1号线

外环路站 上海地铁1号线

莘庄站 上海地铁1号线

原文链接:/weixin_44673043/article/details/107496631

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。