Open roberthsu2003 opened 1 month ago
Python code:
# 下載台北市youbike及時資料(json),解析資料
# - URL: https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json
# - 查出目前可借車輛數為3輛以內的站點
# - 查出目前可還車輛數為3輛以內的站點
# - 將維護的站點移除
import traceback
import json
import requests
from requests import Response
from pprint import pprint
from pydantic import (
BaseModel,
RootModel,
Field,
ValidationError,
field_validator
)
import pyinputplus as pyip
from random import choices
# Inherited from PyDantic BaseModel
class UBike(BaseModel):
act:bool
mday:str
sarea:str
sna:str
ar:str
latitude:float
longitude:float
available_rent_bikes:int
available_return_bikes:int
total:int
# Inherited from PyDantic RootModel
class UBikeRoot(RootModel):
root:list[UBike]
# Return True if each pattern matched
def _search_bike_any(item:dict, patterns:list[dict]) -> bool:
for (k, v) in patterns.items():
if item[k] > 0 and item[k] <= v:
return True
return False
# Return True if all patterns matched
def _search_bike_all(item:dict, patterns:list[dict]) -> bool:
for (k, v) in patterns.items():
if item[k] <= 0 or item[k] > v:
return False
return True
def _search_bike(dlist:list[dict], key:str, val_min:float=1, val_max:float=1, sort:bool=False, sort_key:str='mday', reverse=True):
_dlst:list[dict] = list(filter(lambda item:item[key] >= val_min and item[key] <= val_max, dlist))
if sort:
_dlst = sorted(_dlst, key=lambda item: item[sort_key], reverse=reverse)
return _dlst
def _display_sites_random(dlist:list[dict], sort:bool=True, sort_key:str='mday', reverse=True):
max:int = len(dlist)
if max == 0:
return None
try:
n:int = pyip.inputInt(f"請輸入要隨機顯示的站點(1~{max}): ", min=1, max=max)
dlst_random:list[dict] = choices(dlist, k=n)
if sort:
dlst_random = sorted(dlst_random, key=lambda item: item[sort_key], reverse=reverse)
i:int = 0
for d in list(dlst_random):
i += 1
print(f"第 {i} 筆")
for (k, v) in d.items():
print(f"\t{k}: {v}")
except Exception as e:
raise e
def main():
title:str = "臺北市 U-Bike 即時資訊"
try:
ubike_url:str = "https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json"
resp:Response = requests.get(ubike_url)
if not resp.ok:
print(f"ERROR: 下載{title}失敗")
return
# This JSON include integer and float, but python json module cannot parse these data
# How to correct these ?
# Load generic text and call model_validate() to get data in required fields
jaon_raw:UBikeRoot= UBikeRoot.model_validate(json.loads(resp.text))
# convert UBikeRoot to dictionary list by model_dump()
ubike_full:list[dict] = jaon_raw.model_dump()
print(f"{title}:")
print(f"全部有 {len(ubike_full)} 個 U-Bike 站點")
# filter data
# 1.Search for active sites
act:bool = True
ubike_act:list[dict] = list(filter(lambda item:item['act'] == act, ubike_full))
patterns:dict[str: int] = { "available_rent_bikes": 3, "available_return_bikes": 3 }
display_mode:int = 1 # default display or condition
if display_mode == 1:
# 2. Search for bikes to rent
key:str = "available_rent_bikes"
ubike_lst:list[dict] = _search_bike(ubike_act, key, val_max=patterns[key])
print(str.format("\n營運中且可借車輛數在 {} 輛(含)以內的有站點 {} 個", patterns[key], len(ubike_lst)))
_display_sites_random(ubike_lst)
# 3. Search for bikes to return
key = "available_return_bikes"
ubike_lst:list[dict] = _search_bike(ubike_act, key, val_max=patterns[key])
print(str.format("\n營運中且可還車輛數在 {} 輛(含)以內的站點有 {} 個", patterns[key], len(ubike_lst)))
_display_sites_random(ubike_lst)
else:
# 2. Search available rental and return bikes using or criteria
# For my practice
# Try to use a dictionary to store search criteria
# For functions with more parameters, use the special lambda function approach
ubike_lst:list[dict] = list(filter(lambda item:_search_bike_any(item, patterns), ubike_act))
print("\n搜尋")
print(str.format("\t- {}", '營運中' if act else '休息中'))
print(str.format("\t- 可借車輛數: {} 輛(含)以內", patterns['available_rent_bikes']))
print(str.format("\t- 可還車輛數: {} 輛(含)以內", patterns['available_return_bikes']))
cnt:int = len(ubike_lst)
print(f"\t共有 {cnt} 個符合條件的站點")
_display_sites_random(ubike_lst)
except Exception as e:
print(f"EXCEPTION: {e}")
traceback.print_exc()
if '__main__' == __name__:
main()
Result:
臺北市 U-Bike 即時資訊:
全部有 1420 個 U-Bike 站點
營運中且可借車輛數在 3 輛(含)以內的有站點 276 個
請輸入要隨機顯示的站點(1~276): 3
第 1 筆
act: True
mday: 2024-06-13 15:01:22
sarea: 中山區
sna: YouBike2.0_長春路137巷口
ar: 民生東路二段134號前
latitude: 25.05791
longitude: 121.53114
available_rent_bikes: 3
available_return_bikes: 20
total: 23
第 2 筆
act: True
mday: 2024-06-13 14:58:12
sarea: 士林區
sna: YouBike2.0_社子市場
ar: 延平北路六段67號旁
latitude: 25.0881
longitude: 121.50873
available_rent_bikes: 1
available_return_bikes: 10
total: 15
第 3 筆
act: True
mday: 2024-06-13 14:46:20
sarea: 南港區
sna: YouBike2.0_力行橋(南港)
ar: 研究院路一段101巷16弄2號南側
latitude: 25.05172
longitude: 121.61686
available_rent_bikes: 3
available_return_bikes: 15
total: 18
營運中且可還車輛數在 3 輛(含)以內的站點有 108 個
請輸入要隨機顯示的站點(1~108): 3
第 1 筆
act: True
mday: 2024-06-13 15:01:23
sarea: 中正區
sna: YouBike2.0_中山徐州路口
ar: 中山南路/徐州路(東南側)
latitude: 25.04178
longitude: 121.51907
available_rent_bikes: 13
available_return_bikes: 1
total: 26
第 2 筆
act: True
mday: 2024-06-13 15:01:17
sarea: 中正區
sna: YouBike2.0_法務部
ar: 重慶南路一段130號旁
latitude: 25.03705
longitude: 121.51249
available_rent_bikes: 20
available_return_bikes: 1
total: 27
第 3 筆
act: True
mday: 2024-06-13 14:53:19
sarea: 松山區
sna: YouBike2.0_光復南路46巷
ar: 光復南路46巷10號東側
latitude: 25.04606
longitude: 121.55665
available_rent_bikes: 13
available_return_bikes: 3
total: 16
請幫我查出目前可借車輛數為3輛以內的站點 請幫我查出目前可還車輛數為3輛以內的站點 請將維護的站點移除
import requests
import pyinputplus as pyip
from pprint import pprint
from requests import Response
from pydantic import BaseModel,RootModel,Field,ValidationError,field_validator
from random import choices
class UB(BaseModel):
場站中文名稱:str = Field(alias='sna')
場站區域:str = Field(alias='sarea')
資料更新時間:str = Field(alias='mday')
地點:str = Field(alias='ar')
act:bool
場站總停車格:int = Field(alias='total')
場站目前車輛數量:int = Field(alias='available_rent_bikes')
空位數量:int = Field(alias='available_return_bikes')
緯度:float = Field(alias='latitude')
經度:float = Field(alias='longitude')
class Root(RootModel):
root:list[UB]
def main():
youbike_url = 'https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json'
res:Response = requests.get(youbike_url)
all_data = res.json()
try:
root:Root = Root.model_validate(all_data)
except ValidationError as error:
print(error)
data_list:list[dict] = root.model_dump()
filter_list:list[dict] = list(filter(lambda item:False if item['act']==0 else True,data_list))
filter_list_rent_less3:list[dict] = list(filter(lambda item:True if item['場站目前車輛數量']<3 else False,data_list))
filter_list_return_less3:list[dict] = list(filter(lambda item:True if item['空位數量']<3 else False,data_list))
print(f"台北市YouBike有{len(data_list)}站點,目前正常運作站點共{len(filter_list)}個")
num = pyip.inputInt("請輸入隨機顯示的站點數(1~5): ", min=1, max=5)
print(num)
print(f"\n可借車輛數為3輛以內的站點有{len(filter_list_rent_less3)}站")
num_list:list[dict] = choices(filter_list_rent_less3, k=num)
for sta in num_list:
seq = filter_list_rent_less3.index(sta)
print(f"No.{seq}")
pprint(sta, indent=2, sort_dicts=False)
print(f"\n可還車輛數為3輛以內的站點有{len(filter_list_return_less3)}站")
num_list:list[dict] = choices(filter_list_return_less3, k=num)
for sta in num_list:
seq = filter_list_return_less3.index(sta)
print(f"No.{seq}")
pprint(sta, indent=2, sort_dicts=False)
if __name__ == '__main__':
main()
run:
台北市YouBike有1420站點,目前正常運作站點共1411個
請輸入隨機顯示的站點數(1~5): 2
可借車輛數為3輛以內的站點有383站
No.123
{ '場站中文名稱': 'YouBike2.0_景興路102巷口',
'場站區域': '文山區',
'資料更新時間': '2024-06-13 08:28:14',
'地點': '景華街52巷/景興路102巷',
'act': True,
'場站總停車格': 14,
'場站目前車輛數量': 0,
'空位數量': 14,
'緯度': 24.99438,
'經度': 121.54376}
No.326
{ '場站中文名稱': 'YouBike2.0_虎林永吉路口',
'場站區域': '信義區',
'資料更新時間': '2024-06-13 09:21:22',
'地點': '永吉路356號東側',
'act': True,
'場站總停車格': 15,
'場站目前車輛數量': 1,
'空位數量': 13,
'緯度': 25.04519,
'經度': 121.57712}
可還車輛數為3輛以內的站點有156站
No.3
{ '場站中文名稱': 'YouBike2.0_臺大男七舍前',
'場站區域': '大安區',
'資料更新時間': '2024-06-13 09:19:19',
'地點': '長興街/長興街80巷口西側',
'act': True,
'場站總停車格': 20,
'場站目前車輛數量': 18,
'空位數量': 2,
'緯度': 25.01537,
'經度': 121.54698}
No.93
{ '場站中文名稱': 'YouBike2.0_康寧路三段99巷17弄口',
'場站區域': '內湖區',
'資料更新時間': '2024-06-13 09:09:20',
'地點': '康寧路三段99巷19號對側',
'act': True,
'場站總停車格': 15,
'場站目前車輛數量': 13,
'空位數量': 2,
'緯度': 25.0721,
'經度': 121.60991}
@roberthsu2003
請幫我查出目前可借車輛數為3輛以內的站點
請幫我查出目前可還車輛數為3輛以內的站點
請將維護的站點移除
youbike = 'https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json'
![]()
請問查詢腳踏車數量的這二個條件是 and 還是 or?又或是分為二筆查詢結果?
@roberthsu2003
請幫我查出目前可借車輛數為3輛以內的站點
請幫我查出目前可還車輛數為3輛以內的站點
請將維護的站點移除
youbike = 'https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json'
![]()
請問查詢腳踏車數量的這二個條件是 and 還是 or?又或是分為二筆查詢結果?
沒有限制喔
@roberthsu2003
請幫我查出目前可借車輛數為3輛以內的站點
請幫我查出目前可還車輛數為3輛以內的站點
請將維護的站點移除
youbike = 'https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json'
![]()
請問查詢腳踏車數量的這二個條件是 and 還是 or?又或是分為二筆查詢結果?
沒有限制喔
瞭解
請幫我查出目前可借車輛數為3輛以內的站點
請幫我查出目前可還車輛數為3輛以內的站點
請將維護的站點移除