高德地图获取公交站点_Python爬取公交站点和线路数据(上下行双向)

一、公交线路上下行方向数据的爬取

处理公交数据中,缺少公交地理信息数据,利用高德地图API可以爬取该数据。网上关于这部分的爬取代码有很多,整体思路是先爬取公交线路名称,再去高德API获取公交线路数据。网上的大多数代码都是爬取公交单向线路的数据,在现有代码的基础上,完善了一下爬取公交上下行方向数据的代码。

爬取到最终的数据形式:

b8f03c0694aa6d5a0fad329986d1aa9d.png
公交站点数据

68639b127b87b0670e07bc4807ebd155.png
公交线路数据

主要参考:

http://www.python88.cn/art/7357/​www.python88.cn Python爬虫--城市公交、地铁站点和线路数据采集 - whgiser - 博客园​www.cnblogs.com
e9edae37d50ccd3fc3a2122c191495a5.png
# -*- coding: utf-8 -*-
"""
Created on Thu May 14 07:45:55 2020
本代码可用于爬取多个城市的上下行公交线路和站点数据
只需要在代码中设定参数:
citys = ['taiyuan','datong']  # 城市总列表
chinese_city_names = ['太原','大同']  # 城市对应中文名
headers = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36' # 浏览器user-agnet
file_path = 'C://Users//xaoxu//Desktop//bus_data//' # 数据存储路径
@author: xaoxu
"""

import requests
import pandas as pd
import json
import re
import time
from bs4 import BeautifulSoup
import math

#获取首字母
def getInitial(cityName,headers):
    url = 'https://{}.8684.cn/list1'.format(cityName)
    headers = {
    'User-Agent':headers}
    data = requests.get(url,headers=headers)
    soup = BeautifulSoup(data.text, 'lxml')
    initial = soup.find_all('div',{
    'class':'tooltip-inner'})[3]
    initial = initial.find_all('a')
    ListInitial = []
    for i in initial:
        ListInitial.append(i.get_text())
    return ListInitial

#根据ListInitial的各项爬取各项的首字母公交
def getLine(cityName,n,headers,lines):
    url = 'https://{}.8684.cn/list{}'.format(cityName,n)
    headers = {
    'User-Agent':headers}
    data = requests.get(url,headers=headers)
    soup = BeautifulSoup(data.text, 'lxml')
    busline = soup.find('div',{
    'class':'list clearfix'})
    busline = busline.find_all('a')
    for i in busline:
        lines.append(i.get_text())

# 公交坐标信息转化
x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626  # π
a = 6378245.0  # 长半轴
ee = 0.00669342162296594323  # 扁率

def gcj02towgs84(lng, lat):
    """
    GCJ02(火星坐标系)转GPS84
    :param lng:火星坐标系的经度
    :param lat:火星坐标系纬度
    :return:
    """
    if out_of_china(lng, lat):
        return lng, lat
    dlat = transformlat(lng - 105.0, lat - 35.0)
    dlng = transformlng(lng - 105.0, lat - 35.0)
    radlat = lat / 180.0 * pi
    magic = math.sin(radlat)
    magic = 1 - ee * magic * magic
    sqrtmagic = math.sqrt(magic)
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
    dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
    mglat = lat + dlat
    mglng = lng + dlng
    return [lng * 2 - mglng, lat * 2 - mglat]


def transformlat(lng, lat):
    ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 
        0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
    ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
            math.sin(2.0 * lng * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(lat * pi) + 40.0 *
            math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
    ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *
            math.sin(lat * pi / 30.0)) * 2.0 / 3.0
    return ret


def transformlng(lng, lat):
    ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 
        0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
    ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
            math.sin(2.0 * lng * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(lng * pi) + 40.0 *
            math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
    ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *
            math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
    return ret

def out_of_china(lng, lat):
    
    """
    判断是否在国内,不在国内不做偏移
    :param lng:
    :param lat:
    :return:
    """
    if lng < 72.004 or lng > 137.8347:
        return True
    if lat < 0.8293 or lat > 55.8271:
        return True
    return False

def coordinates(c):
    lng,lat = c.split(',')
    lng,lat = float(lng),float(lat)
    wlng,wlat = gcj02towgs84(lng,lat)
    return wlng,wlat

# 爬取公交站点信息
def get_dt(city,line):
    url = 'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=559bdffe35eec8c8f4dae959451d705c&output=json&city={}&offset=2&keywords={}&platform=JS'.format(city,line)
    r = requests.get(url).text
    rt = json.loads(r)
    try:
        if rt['buslines']:
            if len(rt['buslines']) == 0:  #有名称没数据
                print('no data in list..')
            else:
                du = []
                for cc in range(len(rt['buslines'])):
                    dt = {}
                    dt['line_name'] = rt['buslines'][cc]['name'] 
    
                    st_name = []
                    st_coords = []
                    st_sequence = []
                    for st in rt['buslines'][cc]['busstops']:
                        st_name.append(st['name'])
                        st_coords.append(st['location'])
                        st_sequence.append(st['sequence'])
    
                    dt['station_name'] = st_name
                    dt['station_coords'] = st_coords
                    dt['sequence'] = st_sequence
                    du.append(dt)                
                dm = pd.DataFrame(du)
                return dm
        else:
            pass
    except:
        print('error..try it again..')
        time.sleep(2)
        get_dt(city,line)

# 获取公交线路数据信息
def get_line(city,line):
    url = 'https://restapi.amap.com/v3/bus/linename?s=rsv3&extensions=all&key=559bdffe35eec8c8f4dae959451d705c&output=json&city={}&offset=2&keywords={}&platform=JS'.format(city,line)
    r = requests.get(url).text
    rt = json.loads(r)
    try:
        if rt['buslines']:
            if len(rt['buslines']) == 0:  #有名称没数据
                print('no data in list..')
            else:
                du = []
                for cc in range(len(rt['buslines'])):
                    dt = {}
                    dt['line_name'] = rt['buslines'][cc]['name'] 
                    dt['polyline'] = rt['buslines'][cc]['polyline']
                    du.append(dt)
                dm = pd.DataFrame(du)
                return dm
        else:
            pass
    except:
        print('error..t
  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值