Python寫一個自動點餐程序


Python寫一個自動點餐程序

為什么要寫這個

公司現在用meican作為點餐渠道,每天規定的時間是早7:00-9:40點餐,有時候我經常容易忘記,或者是在地鐵/公交上沒辦法點餐,所以總是沒飯吃,只有去樓下711買點飯團之類的玩意兒,所以這是促使我寫點餐小程序的原因。

點餐的流程

登錄 ---> 點餐 ---> 提交
哈哈,是不是很簡單,其實這個還好,說白了,就是登錄上去,然后拿到cookie,保持一個登錄狀態,然后再去點餐,點餐就是構造請求,發送到指定的點餐URL上就可以了。

登錄

首先我們點開
https://meican.com/

上面要求我們登錄,我們這里輸入自己的賬號密碼,登錄上去之后可以看見一個請求.

這個請求就是登錄的請求,我們看下需要傳什么參數,然后我們去完全構造這個請求,也就是參數一致,並且帶瀏覽器頭,這里我們也需要去保存cookie,也就是說,我們需要自己的賬號時刻保持online狀態,所以需要保存cookie,需要時候調用
所以我們需要實現如下功能

  1. 登錄請求構造
  2. 保持登錄狀態
  3. 保存cookies
  4. 使得后來的訪問都帶cookie

代碼如下

import json
import requests
import http.cookiejar as HC
session = requests.session()
session.cookies = HC.LWPCookieJar(filename='cookies')
def login_meican():
    """
    登錄美餐,尋找cookie文件,沒cookie文件就重新載入
    :return:
    """
    # 儲存cookie作為日后使用,三天clear一次
    try:
        session.cookies.load(ignore_discard=True)
    except:
        print('未找到cookies文件')
        save_cookie()

def save_cookie():
    """
    如果沒cookie,登錄邏輯
    :return:
    """
    login_url = 'https://meican.com/account/directlogin'

    # Headers
    hearsers = {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36",
        "Referer": "https://meican.com/login",
        "Origin": "https://meican.com",
        "Host": "meican.com",
        "Accept": "*/*"
    }

    # Login need data

    data = {
        "username": "xxxxxxxxxxx",
        "loginType": "username",
        "password": "xxxxxxxxxxx",
        "remember": "true"
    }

    try:
        r = session.post(login_url, headers=hearsers, data=data)
        r.raise_for_status()
        session.cookies.save()
    except Exception as e:
        print("login error!")
        return 0

上面的代碼實現了登錄。

點餐

找到菜單

這里需要找到菜單,因為截圖忘了截,這里就直接公布吧,找到菜單需要兩個參數,一個是uuid,另一個是addrid,也就是你登陸的憑證+你所在地區的id,沒有這兩個是無法找出菜單的,並且也無法繼續點餐流程。

如何獲得這兩個參數

在登錄的時候我發現了一個URL,這個URL是 https://meican.com/preorder/api/v2.1/calendaritems/list?withOrderDetail=false&beginDate=2019-09-04&endDate=2019-09-04
這個URL下的返回有我們要的參數,uuid 和 addrid,所以構造請求去獲取這兩個參數

def get_for_my_order():
    """
    找到usertorken, addrid
    :return:
    """
    user_dict = {}
    Now_date = datetime.date.today()
    z = session.get("https://meican.com/preorder/api/v2.1/calendaritems/list?withOrderDetail=false&beginDate={Now}&endDate={Now}".format(Now=Now_date))
    x = json.loads(z.text)
    user_dict["uuid"] = x["dateList"][0]["calendarItemList"][0]["userTab"]["uniqueId"]
    user_dict["addrid"] = x["dateList"][0]["calendarItemList"][0]["userTab"]["corp"]["addressList"][0]["uniqueId"]
    return user_dict

構造獲取菜單請求

找到獲取菜單的URL
https://meican.com/preorder/api/v2.1/recommendations/dishes?tabUniqueId={uuid}&targetTime={Now}+09:40
這里需要一個參數uuid,調取我們獲取參數的函數

def get_menu():
    """
    獲取餐單邏輯
    :return:
    """
    menu_dict = {}
    menu_list = []
    Now_date = datetime.date.today()
    uuid = get_for_my_order()["uuid"]
    z = session.get("https://meican.com/preorder/api/v2.1/recommendations/dishes?tabUniqueId={uuid}&targetTime={Now}+09:40".format(uuid = uuid, Now=Now_date))
    menu = json.loads(z.text)["myRegularDishList"]
    for i in menu:
        menu_dict["id"] = i["id"]
        menu_dict["name"] = i["name"]
        z = copy.deepcopy(menu_dict)
        menu_list.append(z)
    return menu_list

輸出所有的菜單,以一個list作為輸出

提交

構造點餐請求

首先先找到點餐的URL
https://meican.com/preorder/api/v2.1/orders/add
查看點餐需要的參數:

    data = {
       "corpAddressUniqueId": addrid,
       "order": x,
       "remarks": y,
       "tabUniqueId": uuid,
       "targetTime":target_time,
       "userAddressUniqueId":addrid
   }

構造點餐請求

def order_action():
    """
    點餐邏輯
    :return:
    """
    addrid = get_for_my_order()["addrid"]
    uuid = get_for_my_order()["uuid"]
    menu_list = get_menu()
    menu_id = choice(menu_list)["id"]
    target_time = str(datetime.date.today()) + " " + "09:40"
    x = str([{"count":1,"dishId":menu_id}])
    y = str([{"dishId":menu_id,"remark":""}])

    data = {
        "corpAddressUniqueId": addrid,
        "order": x,
        "remarks": y,
        "tabUniqueId": uuid,
        "targetTime":target_time,
        "userAddressUniqueId":addrid
    }

    headers = {
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36"
    }
    try:
        z = session.post("https://meican.com/preorder/api/v2.1/orders/add", headers=headers, data=data)
        z.raise_for_status()
    except:
        return "點餐錯誤!"

所用的知識點一覽

  1. Python requetst的post,session
  2. cookie的保存和調用
  3. json的輸出和瀏覽
  4. random.choice 的列表元素隨機選擇
  5. Python構造請求和登錄邏輯


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM