国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Python實現命令行監控北京實時公交之一

vboy1010 / 2093人閱讀

摘要:開頭先放上效果展示在命令行輸入,顯示基本信息,如下在命令行輸入,顯示北京路公交車的位置,如下紅色的說明在梅園附近有一輛公交車,并且會不斷刷新。

開頭先放上效果展示

在命令行輸入 python bus.py -i,顯示app基本信息,如下:

在命令行輸入 python bus.py 438,顯示北京438路公交車的位置,如下:

紅色的B說明在梅園附近有一輛438公交車,并且會不斷刷新。

GitHub地址 - https://github.com/Harpsichor...


開發過程

作為一個在北京西二旗郊區上班的苦逼,不敢太早下班,怕領導心里不滿,又不敢走太晚,不然趕不上末班公交車了,雖然加班打車能報銷,但打不著車!因此實時公交成立必備神器。


目前用的主要兩個查公交的途徑是車來了微信小程序北京公交微信公眾號,經過用了一段時間發現北京公交的結果是更準的,但是用起來不方便,需要點擊多次才能看到結果,如圖:

由于想寫一個監控公交車的小程序,車快到了能自動提醒。


經過在北京公交官網的一番搜索、分析,發現下面兩個可以使用的URL:

http://www.bjbus.com/home/ind...
北京公交官網首頁,從這里可以獲取所有的公交車編號

http://www.bjbus.com/home/aja...
AJAX接口,獲取指定公交車的路線、站名、目前公交車的位置

獲取所有公交車

先看第一個,是官網首頁,使用requests去獲取,返回的是整個頁面的html, 公交車的編號在圖中顯示的這個dd標簽中:

我們可以使用正則表達式結合一些字符串操作,將所有公交車編號獲取到一個list中,代碼如下:

index_url = r"http://www.bjbus.com/home/index.php"

def get_bus_code_list():
    with open("db/bus.txt", "r", encoding="utf-8") as f:
        db_data = json.loads(f.read())
        if db_data["time"] >= time() - 12*3600:
            print("Getting bus code from db...")
            return db_data["data"]
    resp = requests.get(index_url).content.decode("utf-8")
    print("Getting bus code from web...")
    bus_code_string = re.findall("
([sS]*?)
", resp) bus_code_string = bus_code_string[0].strip().replace("", "") bus_code_list = bus_code_string.split("")[:-1] db_data = { "time": time(), "data": bus_code_list } with open("db/bus.txt", "w", encoding="utf-8") as f: f.write(json.dumps(db_data, ensure_ascii=False, indent=2)) return bus_code_list

注意為了避免每次都要聯網獲取,我將數據用json.dumps保存到了bus.txt里,并設置了一個保存時間,每次請求這個數據的時候,會先從bus.txt里讀取,如果數據還在有效期內(12*3600秒),則直接使用。


獲取指定公交車的位置

而如果獲取公交車的實時狀態,那么需要去GET請求一個這樣格式的url

http://www.bjbus.com/home/ajax_rtbus_data.php?act=busTime&selBLine=17&selBDir=5223175012989176770&selBStop=9

那么可以看到這個url4個參數,分別是act(固定為busTime),selBLine(表示公交車編號),selBDir(表示公交車線路的編號),selBStop(表示上車的車站),請求上面的這個url時,返回的結果是json對象,并且有個key"html",這個html的部分結構如下圖:

首先開頭是一段類似提示性的信息,然后一個ul無序列表,每一個li標簽中都有一個divid是遞增的數字或者是數字加一個m,純數字的div還有對應的車站名,帶m的則是空的,我理解帶m的表示車站之間的中間區域。注意div中的i標簽,有的有classclstag這兩個屬性,這代表的就是公交車了,并且clstag的值表示公交車距離我們選擇上車的車站selBStop=9還有多遠,如果是已經過站的車,這個值則為空或-1。所以直接給出代碼如下,代碼解釋也寫在注釋里:

main_url = r"http://www.bjbus.com/home/ajax_rtbus_data.php"

# 獲取公交車的位置,參數為公交車編號,線路編號,上車站點的編號
def get_bus_status(bus_code, direction, station_no):
    payload = {
        "act": "busTime",
        "selBLine": bus_code,
        "selBDir": direction,
        "selBStop": station_no
    }
    # 帶參數的Get方法,將返回對象json化,獲取key為"html"的內容
    resp = requests.get(main_url, params=payload).json()["html"]
    print("Getting bus status from web...")
    # 這部分使用正則太復雜,因此使用BeautifulSoup解析html
    soup = BeautifulSoup(resp, "html.parser")
    # html開頭的路線,并將bs的string類型轉換為普通string
    path = str(soup.find(id="lm").contents[0]) 
    # html開頭的提示性信息,獲取上車車站的名稱,路線的運營時間
    station_name, operation_time, *_ = soup.article.p.string.split("xa0")
    # tip獲取html開頭的提示性信息的具體文本,例如最近一輛車還有多遠
    tip = ""
    for content in soup.article.p.next_sibling.contents:
        if isinstance(content, str):
            tip += content.replace("xa0", "")
        else:
            tip += content.string
    bus_position = []
    # 獲取所有有公交車的標簽(即有clstag這個屬性的)
    for tag in soup.find_all("i", attrs={"clstag": True}):
        temp_dic = dict()
        # 獲取車站的id
        station_id = tag.parent["id"]
        # 如果id不帶m,說明公交車離車站較近,near_station為True
        temp_dic["near_station"] = False if "m" in station_id else True
        station_id = station_id.replace("m", "")
        temp_dic["station_id"] = station_id
        # 獲取公交車離上車車站的距離,如果已過站則為-1
        temp_dic["distance"] = int(tag["clstag"]) if tag["clstag"].isdigit() else -1
        # 此時temp_dic有車站id,距離,及near_station三個屬性,將其append到list
        bus_position.append(temp_dic)
    result = {
        "path": path,
        "station_name": station_name,
        "operation_time": operation_time,
        "bus_position": bus_position,   # A list of dict
        "tip": tip
    }
    # 返回的結果包含較多內容,后續按需要選取部分數據使用
    return result

獲取公交車路線代碼和公交車所有車站

剛剛我們的函數獲取公交車的位置,需要公交車編號、路線編號和車站編號三個參數,在一開始我們獲取了所有北京公交車的編號,并存儲在bus.txt中,那么怎么獲取路線的編號的呢?同樣用Chrome瀏覽器分析北京公交官網的訪問過程,可以找到這樣一個鏈接:

http://www.bjbus.com/home/ajax_rtbus_data.php?act=getLineDirOption&selBLine=438

其返回的結果是這樣的(可以試試直接用瀏覽器訪問):

很明顯option中的value就是公交車路線的代碼,因此也很容易寫出一個獲取公交車路線代碼的函數,如下:

main_url = r"http://www.bjbus.com/home/ajax_rtbus_data.php"

def get_bus_direction(bus_code):
    # 先從文本中讀取,避免重復聯網訪問
    with open("db/direction.txt", "r", encoding="utf-8") as f:
        db_data = json.loads(f.read())
        bus_direction = db_data.get(str(bus_code))
        if bus_direction and bus_direction["time"] >= time() - 12*3600:
            print("Getting bus direction from db...")
            return bus_direction["data"]
    payload = {
        "act": "getLineDirOption",
        "selBLine": bus_code
    }
    resp = requests.get(url=main_url, params=payload).content.decode("utf-8")
    print("Getting bus direction from web...")
    # 正則獲取編號
    direction_no = re.findall("value="(d+)"", resp)
    if not direction_no:
        print("%s路公交車未找到" % str(bus_code))
        return []
    # 正則獲取路線
    direction_path = re.findall(str(bus_code) + "(.*?)<", resp)
    data = []
    for j in range(2):
        direction_path_str = direction_path[j][1:-1]
        data.append([direction_no[j], direction_path_str])
    # 最新數據寫入文本
    with open("db/direction.txt", "w+", encoding="utf-8") as f:
        db_data[str(bus_code)] = {
            "time": time(),
            "data": data
        }
        f.write(json.dumps(db_data, ensure_ascii=False, indent=2))
    return data

獲取公交車的車站也是類似的,其url是:

http://www.bjbus.com/home/ajax_rtbus_data.php?act=getDirStationOption&selBLine=438&selBDir=5204817486192029180

其返回的結果是:

直接上代碼:

def get_bus_stations(bus_code, direction):
    with open("db/station.txt", "r", encoding="utf-8") as f:
        db_data = json.loads(f.read())
        bus_station = db_data.get(str(bus_code) + "#" + str(direction))
        if bus_station and bus_station["time"] >= time() - 12 * 3600:
            print("Getting bus station from db...")
            return bus_station["data"]
    payload = {
        "act": "getDirStationOption",
        "selBLine": bus_code,
        "selBDir": direction
    }
    resp = requests.get(main_url, params=payload).content.decode("utf-8")
    print("Getting bus station from web...")
    stations = re.findall("", resp)[1:]
    with open("db/station.txt", "w+", encoding="utf-8") as f:
        db_data[str(bus_code) + "#" + str(direction)] = {
            "time": time(),
            "data": stations
        }
        f.write(json.dumps(db_data, ensure_ascii=False, indent=2))
    return stations

至此,功能函數就都已經寫好了,剩余的是實現命令行輸出結果的功能,在后續文章說明。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/41521.html

相關文章

  • Python實現命令監控北京實時公交之二

    摘要:鏈接前文實現命令行監控北京實時公交之一開頭先放上效果展示在命令行輸入,顯示基本信息,如下在命令行輸入,顯示北京路公交車的位置,如下紅色的說明在梅園附近有一輛公交車,并且會不斷刷新。 鏈接前文:Python實現命令行監控北京實時公交之一 開頭先放上效果展示 在命令行輸入 python bus.py -i,顯示app基本信息,如下: showImg(https://segmentfaul...

    fasss 評論0 收藏0
  • 高德地圖 Javascript API 入門(六)

    摘要:高德地圖入門六出行規劃公交路徑公交換乘服務,提供起終點公交路線規劃服務,整合步行方式初始化加載公交線路插件實例化北京必須值,搭乘公交所在城市可選值,搜索結果的標注線路等均會自動添加到此地圖上可選值,顯示搜索列表的容器可選值,詳細信息駕駛策略 高德地圖 Javascript API 入門(六) 出行規劃 公交路徑 公交換乘服務,提供起、終點公交路線規劃服務,整合步行方式 初始化 // 加...

    idisfkj 評論0 收藏0
  • 那些有趣/用的 Python

    摘要:梁振英在星期二月日的答問大會開始之際在其演說中道歉,但強調他在違章建筑問題上沒有隱瞞的意圖和動機。 圖片處理 pip install pillow from PIL import Image import numpy as np a = np.array(Image.open(test.jpg)) b = [255,255,255] - a im = Image.fromarray(...

    Pikachu 評論0 收藏0
  • 斯坦福新深度學習系統 NoScope:視頻對象檢測快1000倍

    摘要:通過利用一系列利用視頻局部性的優化,顯著降低了在每個幀上的計算量,同時仍保持常規檢索的高精度。的差異檢測器目前是使用逐幀計算的邏輯回歸模型實現的。這些檢測器在上的運行速度非常快,每秒超過萬幀。也就是說,每秒處理的視頻幀數超過幀。 視頻數據正在爆炸性地增長——僅英國就有超過400萬個CCTV監控攝像頭,用戶每分鐘上傳到 YouTube 上的視頻超過300小時。深度學習的進展已經能夠自動分析這些...

    xcold 評論0 收藏0
  • 2021年8月國產數據庫大事記

    摘要:本文整理了年月國產數據庫大事件和重要產品發布消息。柏睿數據庫加速安全卡面向全球重磅發布。月日,在全球數字經濟大會成果發布會上,中國移動北京分公司與國產數據庫領域新銳企業柏睿數據簽署戰略合作協議。本次大賽主要面向全國愛好數據庫的高校學生。 本文整理了2021年8月國產數據庫大事件和重要產品發布消息。目錄8月國產數據庫大事記TOP108月國產數據庫大事記時間線產品/版本發布兼容認證8月排行榜新增...

    Scorpion 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<