【Python爬蟲】爬取公共交通路網數據

程序來自于Github,以下這篇博客作為完整的學習記錄,也callback上一篇爬取公共交通站點的博文。

Bardbo/get_bus_lines_and_stations_data_from_gaode: 這個項目是基于高德開放平臺和公交網獲取公交線路及站點數據,并生成shp文件,代碼相對粗糙,但簡單可用https://github.com/Bardbo/get_bus_lines_and_stations_data_from_gaode

1. 導入庫

首先是程序需要的python庫。

import requests
import json
import pandas as pd
from lxml import etree
import time
from tqdm import tqdm
  • requests:用于發送HTTP請求,獲取網頁內容或API數據。

  • json:用于處理JSON格式的數據。

  • pandas:用于數據處理和保存為CSV文件。

  • lxml:用于解析HTML內容。

  • time:用于控制爬取速度,避免過快請求導致被封禁。

  • tqdm:用于顯示進度條,方便查看爬取進度。

2.?獲取城市公交線路名稱(get_bus_line_name?函數)

def get_bus_line_name(city_phonetic):url = 'http://{}.gongjiao.com/lines_all.html'.format(city_phonetic)r = requests.get(url).textet = etree.HTML(r)line_name = et.xpath('//div[@class="list"]//a/text()')return line_name

這里同樣也需要先爬取公交線路的名稱,函數需要傳入city_phonetic也就是城市的拼音(如?changsha、wuhan),函數會返回該城市所有公交線路的名稱列表(line_name)。

3. 爬取公交路線(get_line_station_data?函數)

獲取公交線路的url是高德的https://restapi.amap.com/v3/bus/linename?extensions=all&key={ak}&output=json&city={city}&offset=1&keywords={line_name}

那么先來看一下官方的介紹,這里使用的是公交路線關鍵字查詢,也就是說我們要輸入公交路線的關鍵字,例如15路等等。

返回的內容如下,status記錄了查詢成功與否,buslines中記錄了查詢成功的公交路線。

接下來來看代碼:

def get_line_station_data(city, line_name, ak, city_phonetic):print(f'正在獲取-->{line_name}')time.sleep(1)url = f'https://restapi.amap.com/v3/bus/linename?extensions=all&key={ak}&output=json&city={city}&offset=1&keywords={line_name}'r = requests.get(url).textrt = json.loads(r)try:if rt['buslines']:if len(rt['buslines']) == 0:print('no data in list..')else:dt = {}dt['line_name'] = rt['buslines'][0]['name']dt['polyline'] = rt['buslines'][0]['polyline']dt['total_price'] = rt['buslines'][0]['total_price']station_name = []station_coords = []for st in rt['buslines'][0]['busstops']:station_name.append(st['name'])station_coords.append(st['location'])dt['station_name'] = station_namedt['station_corrds'] = station_coordsdm = pd.DataFrame([dt])dm.to_csv(f'{city_phonetic}_lines.csv',mode='a',header=False,index=False,encoding='utf_8_sig')else:print('data not avaliable..')with open('data not avaliable.log', 'a') as f:f.write(line_name + '\n')except:print('error.. try it again..')time.sleep(2)get_line_station_data(city, line_name, ak, city_phonetic)

函數通過高德地圖API獲取某條公交線路的詳細信息,并保存到CSV文件中。通過構造API請求URL獲取公交線路數據,解析響應并提取線路名稱、路徑、票價、站點名稱和坐標,將數據保存到CSV文件,若數據不可用則記錄日志,失敗時等待2秒后重試。

如果爬取失敗的話,檢查一下key是否達到了限額,一天只能爬取5000次,爬取公交線路比較耗費次數。

爬取完成后來看一下保存的csv,總共5列。

  • A列:公交線路關鍵字(名稱)
  • B列:公交線路polyline,也就是線路途徑的每個點(注意不是站點,公交線路的每個拐點都會被記錄)
  • C列:總價
  • D列:途徑站點關鍵字(名稱)
  • E列:途徑站點經緯度坐標

4. 主程序調用

if __name__ == '__main__':city = '益陽'city_phonetic = 'yiyang'ak = '###'  # 這里建議更改為自己的keystart_time = time.time()print(f'==========正在獲取 {city} 線路名稱==========')line_names = get_bus_line_name(city_phonetic)print(f'{city}在公交網上顯示共有{len(line_names)}條線路')for line_name in tqdm(line_names):get_line_station_data(city, line_name, ak, city_phonetic)end_time = time.time()print(f'我爬完啦, 耗時{end_time - start_time}秒')

自己需要設置的是最開始的city、city_phonetic、ak.

程序調用了上面的函數并記錄了爬取的時間。

5. 線路、站點轉成shp

那么有了這個csv怎么可視化呢?

那么作者就寫了DataToShp這個?類用于將公交線路和站點數據從CSV文件轉換為Shapefile格式,主要功能包括:

get_station_data:將站點坐標和名稱從字符串格式轉換為列表格式,將數據從橫向展開為縱向,并去除重復項;

get_line_data:將線路的折線數據從字符串格式轉換為列表格式;

create_station_shp:創建站點Shapefile,包含站點名稱和坐標;

create_lines_shp:創建線路Shapefile,包含線路名稱和折線坐標;

其實作者其實在這里還引入了從高德的火星坐標系轉換為WGS_84的函數,但是大部分時候這種轉換并不可靠,所以建議高德爬取的數據就搭配高德地圖進行可視化使用。

# -*- coding: utf-8 -*-
# @Author: Bardbo
# @Date:   2020-11-09 21:09:12
# @Last Modified by:   Bardbo
# @Last Modified time: 2020-11-09 21:59:35
import pandas as pd
import numpy as np
import shapefile
# import converterclass DataToShp:def __init__(self, filename):self.data = pd.read_csv(filename,names=['line_name', 'polyline', 'price','station_names', 'station_coords'])def get_station_data(self):df_stations = self.data[['station_coords', 'station_names']]# 將原本的一行字符串變為列表df_stations['station_coords'] = df_stations['station_coords'].apply(lambda x: x.replace('[', '').replace(']', '').replace('\'', '').split(', '))df_stations['station_names'] = df_stations['station_names'].apply(lambda x: x.replace('[', '').replace(']', '').replace('\'', '').split(', '))# 橫置的數據變為縱向的數據station_all = pd.DataFrame(\np.column_stack((\np.hstack(df_stations['station_coords'].repeat(list(map(len, df_stations['station_coords'])))),np.hstack(df_stations['station_names'].repeat(list(map(len, df_stations['station_names'])))))),columns=['station_coords','station_names'])# 去除重復station_all = station_all.drop_duplicates()# # 坐標轉換# station_all['st_coords_wgs84'] = station_all['station_coords'].apply(#     self.stations_to_wgs84)station_all.reset_index(inplace=True)self.stations = station_alldef get_line_data(self):df_lines = self.data[['line_name', 'polyline']]df_lines['polyline'] = df_lines['polyline'].apply(lambda x: x.split(';'))# # 坐標轉換# df_lines['lines_wgs84'] = df_lines['polyline'].apply(#     self.lines_to_wgs84)df_lines.reset_index(inplace=True)self.lines = df_lines# def stations_to_wgs84(self, coor):#     xy = coor.split(',')#     lng, lat = float(xy[0]), float(xy[1])#     return converter.gcj02_to_wgs84(lng, lat)## def lines_to_wgs84(self, coor):#     ls = []#     for c in coor:#         xy = c.split(',')#         lng, lat = float(xy[0]), float(xy[1])#         ls.append(converter.gcj02_to_wgs84(lng, lat))#     return lsdef create_station_shp(self, city_phonetic):w = shapefile.Writer(f'./data/{city_phonetic}_stations.shp')w.field('name', 'C')# 確保所有坐標都是浮動類型for i in range(len(self.stations)):coords = self.stations.loc[i, 'station_coords'].split(',')  # 獲取坐標lat = float(coords[0])  # 強制轉換為浮動類型lon = float(coords[1])  # 強制轉換為浮動類型# 確保坐標是浮動類型w.point(lat, lon)  # 寫入點w.record(self.stations.loc[i, 'station_names'])  # 寫入記錄w.close()def create_lines_shp(self, city_phonetic):w = shapefile.Writer(f'./data/{city_phonetic}_lines.shp')w.field('name', 'C')for i in range(len(self.lines)):polyline = self.lines['polyline'][i]# 如果 polyline 是字符串,則使用 split();如果是列表,則直接使用if isinstance(polyline, list):polyline = [list(map(float, point.split(','))) for point in polyline]# 確保 polyline 是列表類型,進行寫入w.line([polyline])w.record(self.lines['line_name'][i])w.close()if __name__ == '__main__':dts = DataToShp('yiyang_lines.csv')dts.get_station_data()dts.get_line_data()dts.create_station_shp()dts.create_lines_shp()print('shp文件創建完成')

如下就是可視化后的效果【爬的時候無意中發現學校這多了兩條公交,深入鄂州,win!】

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/71354.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/71354.shtml
英文地址,請注明出處:http://en.pswp.cn/web/71354.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Stable Diffusion模型高清算法模型類詳解

Stable Diffusion模型高清算法模型類詳細對比表 模型名稱核心原理適用場景參數建議顯存消耗細節增強度優缺點4x-UltraSharp殘差密集塊(RDB)結構優化紋理生成真實人像/建筑攝影重繪幅度0.3-0.4,分塊尺寸768px★★★★★☆皮膚紋理細膩,但高對比場景易出現…

VUE_使用Vite構建vue項目

創建項目 // 安裝vite npm install vite// 創建名為vite-app的項目 npm create vite vite-app --template vue// 到項目目錄 cd vite-app// 安裝依賴 npm install// 運行項目 npm run dev// 打包 npm run build// 打包預覽 npm run serve 增加路由 // 安裝路由 npm add vue-r…

ctf網絡安全賽題

CTF簡介 CTF(Capture The Flag)中文一般譯作奪旗賽,在網絡安全領域中指的是網絡安全技術人員之間進行技術競技的一種比賽形式。CTF起源于1996年DEFCON全球黑客大會,以代替之前黑客們通過互相發起真實攻擊進行技術比拼的方式。發展…

【朝夕教育】《鴻蒙原生應用開發從零基礎到多實戰》004-TypeScript 中的泛型

標題詳情作者簡介愚公搬代碼頭銜華為云特約編輯,華為云云享專家,華為開發者專家,華為產品云測專家,CSDN博客專家,CSDN商業化專家,阿里云專家博主,阿里云簽約作者,騰訊云優秀博主&…

性能測試監控工具jmeter+grafana

1、什么是性能測試監控體系? 為什么要有監控體系? 原因: 1、項目-日益復雜(內部除了代碼外,還有中間件,數據庫) 2、一個系統,背后可能有多個軟/硬件組合支撐,影響性能的因…

互聯網時代如何保證數字足跡的安全,以防個人信息泄露?

用戶在網絡上所做的幾乎所有事情,包括瀏覽、社交媒體活動、搜索查詢、在線訂閱,甚至購物,都會留下一條數據線索,這些數據可用于創建用戶在線身份的詳細檔案。如果這些信息暴露,惡意行為者可能會利用它們將用戶置于各種…

C# IEquatable<T> 使用詳解

總目錄 前言 在 C# 開發中&#xff0c;IEquatable<T> 是一個泛型接口&#xff0c;用于定義類型的相等性比較邏輯。通過實現 IEquatable<T>&#xff0c;可以為自定義類型提供高效的、類型安全的相等性比較方法。本文將詳細介紹 IEquatable<T> 的使用方法、應…

web第四天

Dom操作元素 innerText、innerHTML、value(input and textarea用到) 更改屬性&#xff0c;樣式 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wid…

LabVIEW基于IMAQ實現直線邊緣檢測

本程序基于 NI Vision Development 模塊&#xff0c;通過 IMAQ Find Straight Edges 函數&#xff0c;在指定 ROI&#xff08;感興趣區域&#xff09; 內檢測多條直線邊緣。用戶可 動態調整檢測參數 或 自定義ROI&#xff0c;實時觀察識別效果&#xff0c;適用于 高精度視覺檢測…

費曼學習法13 - 數據表格的魔法:Python Pandas DataFrame 詳解 (Pandas 基礎篇)

第二篇&#xff1a;數據表格的魔法&#xff1a;Python Pandas DataFrame 詳解 (Pandas 基礎篇) 開篇提問&#xff1a; 回憶一下&#xff0c;我們上一篇文章學習了 Pandas 的一維數據結構 Series&#xff0c;它可以看作是帶 “標簽” 的列表。 但現實世界中的數據&#xff0c;…

一周學會Flask3 Python Web開發-在模板中渲染WTForms表單視圖函數里獲取表單數據

鋒哥原創的Flask3 Python Web開發 Flask3視頻教程&#xff1a; 2025版 Flask3 Python web開發 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili 為了能夠在模板中渲染表單&#xff0c;我們需要把表單類實例傳入模板。首先在視圖函數里實例化表單類LoginForm&#xff0c;然…

小紅書湖倉架構的躍遷之路

作者&#xff1a;李鵬霖(丁典)&#xff0c;小紅書-研發工程師&#xff0c;StarRocks Contributor & Apache Impala Committer 本文整理自小紅書工程師在 StarRocks 年度峰會上的分享&#xff0c;介紹了小紅書自助分析平臺中&#xff0c;StarRocks 與 Iceberg 結合后&#x…

數據結構第五節:排序

1.常見的排序算法 插入排序&#xff1a;直接插入排序、希爾排序 選擇排序&#xff1a;直接選擇排序、堆排序 交換排序&#xff1a;冒泡排序、快速排序 歸并排序&#xff1a;歸并排序 排序的接口實現&#xff1a; // 1. 直接插入排序 void InsertSort(int* a, int n); // 2. 希…

BambuStudio學習筆記:FaceDetector類

面檢測器類解析 這段代碼定義了一個名為 FaceDetector 的 C 類&#xff0c;用于處理三維模型中的面檢測。以下是該類的具體說明&#xff1a; 頭文件保護 #ifndef slic3r_FaceDetector_hpp_ #define slic3r_FaceDetector_hpp_這部分代碼防止頭文件被多次包含。 命名空間聲明…

C++發展

目錄 ?編輯C 的發展總結&#xff1a;?編輯 1. C 的早期發展&#xff08;1979-1985&#xff09; 2. C 標準化過程&#xff08;1985-1998&#xff09; 3. C 標準演化&#xff08;2003-2011&#xff09; 4. C11&#xff08;2011年&#xff09; 5. C14&#xff08;2014年&a…

LeetCode 21. 合并兩個有序鏈表(Python)

將兩個升序鏈表合并為一個新的 升序 鏈表并返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。 輸入&#xff1a;l1 [1,2,4], l2 [1,3,4] 輸出&#xff1a;[1,1,2,3,4,4] 示例 2&#xff1a; 輸入&#xff1a;l1 [], l2 [] 輸出&#xff1a;[] 示例 3&#xff1a; 輸…

FPGA 配置原理

用戶編程控制的FPGA 是通過加載比特位流配置內部的存儲單元實現的。該存儲單元就是所謂的配置單元&#xff0c;它必須在器件上電后進行配置&#xff0c;從而設置查找表&#xff08;LUT&#xff09;的屬性、連線方式、IOB 電壓標準和其它的用戶設計。 1.配置幀 以Xilinx 公司的…

測試人員如何更好的跟蹤BUG

軟件測試中BUG跟蹤是確保軟件質量的關鍵環節。測試人員不僅需要發現BUG&#xff0c;還需有效管理其狀態&#xff0c;從報告到修復驗證的全過程。如何更好地跟蹤BUG&#xff0c;成為測試人員提升效率的重要課題。本文將詳細探討測試人員可以采用的策略&#xff0c;包括使用工具、…

lamp平臺介紹

一、lamp介紹 網站&#xff1a; 靜態 動態 php語言 .php 作用&#xff1a;運行php語言編寫動態網站應用 lamp Linux Apache MySQL PHP PHP是作為httpd的一個功能模塊存在的 二、部署lamp平臺 1、測試httpd是否可正常返回PHP的響應 2、測試PHP代碼是否可正常連接數據…

2025年滲透測試面試題總結-字某跳動-滲透測試實習生(題目+回答)

網絡安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 字某跳動-滲透測試實習生 滲透流程信息收集如何處理子域名爆破中的泛解析問題繞過CDN尋找真實IPPHPINFO頁面關注…