一、公交线路上下行方向数据的爬取
处理公交数据中,缺少公交地理信息数据,利用高德地图API可以爬取该数据。网上关于这部分的爬取代码有很多,整体思路是先爬取公交线路名称,再去高德API获取公交线路数据。网上的大多数代码都是爬取公交单向线路的数据,在现有代码的基础上,完善了一下爬取公交上下行方向数据的代码。
爬取到最终的数据形式:
主要参考:
http://www.python88.cn/art/7357/www.python88.cn Python爬虫--城市公交、地铁站点和线路数据采集 - whgiser - 博客园www.cnblogs.com# -*- 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