Python爬蟲_城市公交、地鐵站點(diǎn)和線路數(shù)據(jù)采集實(shí)例
城市公交、地鐵數(shù)據(jù)反映了城市的公共交通,研究該數(shù)據(jù)可以挖掘城市的交通結(jié)構(gòu)、路網(wǎng)規(guī)劃、公交選址等。但是,這類數(shù)據(jù)往往掌握在特定部門中,很難獲取?;ヂ?lián)網(wǎng)地圖上有大量的信息,包含公交、地鐵等數(shù)據(jù),解析其數(shù)據(jù)反饋方式,可以通過Python爬蟲采集。閑言少敘,接下來將詳細(xì)介紹如何使用Python爬蟲爬取城市公交、地鐵站點(diǎn)和數(shù)據(jù)。
首先,爬取研究城市的所有公交和地鐵線路名稱,即XX路,地鐵X號(hào)線??梢酝ㄟ^圖吧公交、公交網(wǎng)、8684、本地寶等網(wǎng)站獲取,該類網(wǎng)站提供了按數(shù)字和字母劃分類別的公交線路名稱。Python寫個(gè)簡單的爬蟲就能采集,可參看WenWu_Both的文章,博主詳細(xì)介紹了如何利用python爬取8684上某城市所有的公交站點(diǎn)數(shù)據(jù)。該博主采集了站點(diǎn)詳細(xì)的信息,包括,但是缺少了公交站點(diǎn)的坐標(biāo)、公交線路坐標(biāo)數(shù)據(jù)。這就讓人抓狂了,沒有空間坐標(biāo)怎么落圖,怎么分析,所以,本文重點(diǎn)介紹的是站點(diǎn)坐標(biāo)、線路的獲取。
以圖吧公交為例,點(diǎn)擊某一公交后,出現(xiàn)該路公交的詳細(xì)站點(diǎn)信息和地圖信息。博主頓感興奮,覺得馬上就要成功了,各種抓包,發(fā)現(xiàn)并不能解析??赡懿┲骷夹g(shù)所限,如有大神能從中抓到站點(diǎn)和線路的坐標(biāo)信息,請(qǐng)不寧賜教。這TM就讓人絕望了啊,到嘴的肥肉吃不了。
天無絕人之路,嘗試找找某地圖的API,發(fā)現(xiàn)可以調(diào)用,通過解析,能夠找到該數(shù)據(jù)的后臺(tái)地址。熟悉前端的可以試試,博主前端也就只會(huì)個(gè)hello world,不獻(xiàn)丑了。這是一種思路,實(shí)踐證明是可以的。
地圖API可以,那么通過地圖抓包呢?打開某圖主頁,直接輸入某市公交名稱,通過抓包,成功找到站點(diǎn)和線路信息。具體抓包信息如下圖所示,busline_list中詳細(xì)列出了站點(diǎn)和線路的信息,其中有兩條,是同一趟公交不同方向的數(shù)據(jù),略有差別,需注意。找到入口過后,接下來爬蟲就要大顯身手了。
主要爬取代碼如下,其實(shí)也很簡單,主函數(shù)如下。首先需要構(gòu)建傳入的參數(shù),主要的包括路線名稱,城市編碼,地理范圍,縮放尺度。地理范圍可以通過坐標(biāo)拾取器獲取,參數(shù)經(jīng)url編碼后,發(fā)送請(qǐng)求,判斷返回?cái)?shù)據(jù)是否符合要求(注:可能該線路地圖上停運(yùn)或不存在,也可能是訪問速度過快,反爬蟲機(jī)制需要人工驗(yàn)證,博主爬取的時(shí)候碰到過,所以后面設(shè)置了隨機(jī)休眠)。接下來,就是解析json數(shù)據(jù)了。代碼中的extratStations和extractLine,就是提取需要的字段,怎么樣,是不是很簡單。最后,就是保存了,站點(diǎn)和路線分別存儲(chǔ)。
def main(): df = pd.read_excel("線路名稱.xlsx",) BaseUrl = "https://ditu.amap.com/service/poiInfo?query_type=TQUERY&pagesize=20&pagenum=1&qii=true&cluster_state=5&need_utd=true&utd_sceneid=1000&div=PC1000&addr_poi_merge=true&is_classify=true&" for bus in df[u"線路"]: params = { 'keywords':'11路', 'zoom': '11', 'city':'610100', 'geoobj':'107.623|33.696|109.817|34.745' } print(bus) paramMerge = urllib.parse.urlencode(params) #print(paramMerge) targetUrl = BaseUrl + paramMerge stationFile = "./busStation/" + bus + ".csv" lineFile = "./busLine/" + bus + ".csv" req = urllib.request.Request(targetUrl) res = urllib.request.urlopen(req) content = res.read() jsonData = json.loads(content) if (jsonData["data"]["message"]) and jsonData["data"]["busline_list"]: busList = jsonData["data"]["busline_list"] ##busline 列表 busListSlt = busList[0] ## busList共包含兩條線,方向不同的同一趟公交,任選一趟爬取 busStations = extratStations(busListSlt) busLine = extractLine(busListSlt) writeStation(busStations, stationFile) writeLine(busLine, lineFile) sleep(random.random() * random.randint(0,7) + random.randint(0,5)) #設(shè)置隨機(jī)休眠 else: continue
附上博主的解析函數(shù):
def extratStations(busListSlt): busName = busListSlt["name"] stationSet = [] stations = busListSlt["stations"] for bs in stations: tmp = [] tmp.append(bs["station_id"]) tmp.append(busName) tmp.append(bs["name"]) cor = bs["xy_coords"].split(";") tmp.append(cor[0]) tmp.append(cor[1]) wgs84cor1 = gcj02towgs84(float(cor[0]),float(cor[1])) tmp.append(wgs84cor1[0]) tmp.append(wgs84cor1[1]) stationSet.append(tmp) return stationSet def extractLine(busListSlt): ## busList共包含兩條線,備注名稱 keyName = busListSlt["key_name"] busName = busListSlt["name"] fromName = busListSlt["front_name"] toName = busListSlt["terminal_name"] lineSet = [] Xstr = busListSlt["xs"] Ystr = busListSlt["ys"] Xset = Xstr.split(",") Yset = Ystr.split(",") length = len(Xset) for i in range(length): tmp = [] tmp.append(keyName) tmp.append(busName) tmp.append(fromName) tmp.append(toName) tmp.append(Xset[i]) tmp.append(Yset[i]) wgs84cor2 = gcj02towgs84(float(Xset[i]),float(Yset[i])) tmp.append(wgs84cor2[0]) tmp.append(wgs84cor2[1]) lineSet.append(tmp) return lineSet
爬蟲采集原始數(shù)據(jù)如下:
以下是某一條公交站點(diǎn)和線路的處理后的數(shù)據(jù)展示。由于不同的地圖商采用不同的坐標(biāo)系,會(huì)有不同程度的偏差,需要坐標(biāo)糾偏。下一步,博主將詳細(xì)介紹如何批量將這些站點(diǎn)和坐標(biāo)進(jìn)行坐標(biāo)糾正和矢量化。
相關(guān)文章
python3.5基于TCP實(shí)現(xiàn)文件傳輸
這篇文章主要為大家詳細(xì)介紹了python3.5基于TCP實(shí)現(xiàn)文件傳輸?shù)拇a,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07Django多個(gè)app urls配置代碼實(shí)例
這篇文章主要介紹了Django多個(gè)app urls配置代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11python實(shí)現(xiàn)將字符串中的數(shù)字提取出來然后求和
這篇文章主要介紹了python實(shí)現(xiàn)將字符串中的數(shù)字提取出來然后求和,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-04-04Python Django中間件,中間件函數(shù),全局異常處理操作示例
這篇文章主要介紹了Python Django中間件,中間件函數(shù),全局異常處理操作,結(jié)合實(shí)例形式分析了Django中間件,中間件函數(shù),全局異常處理相關(guān)操作技巧,需要的朋友可以參考下2019-11-11Tornado Application的實(shí)現(xiàn)
本文主要介紹了Tornado Application的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05django的分頁器Paginator 從django中導(dǎo)入類
這篇文章主要介紹了django的分頁器Paginator 從django中導(dǎo)入類,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07python使用xlrd和xlwt讀寫Excel文件的實(shí)例代碼
這篇文章主要介紹了python使用xlrd和xlwt讀寫Excel文件的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09Python中IO多路復(fù)用模塊selector的用法詳解
selector?是一個(gè)實(shí)現(xiàn)了IO復(fù)用模型的python包,實(shí)現(xiàn)了IO多路復(fù)用模型的?select、poll?和?epoll?等函數(shù),下面就跟隨小編一起來學(xué)習(xí)一下它的具體使用吧2024-02-02使用pandas忽略行列索引,縱向拼接多個(gè)dataframe
這篇文章主要介紹了使用pandas忽略行列索引,縱向拼接多個(gè)dataframe的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03