Python寫一個自動點餐程序
為什么要寫這個
公司現在用meican作為點餐渠道,每天規定的時間是早7:00-9:40點餐,有時候我經常容易忘記,或者是在地鐵/公交上沒辦法點餐,所以總是沒飯吃,只有去樓下711買點飯團之類的玩意兒,所以這是促使我寫點餐小程序的原因。
點餐的流程
登錄 ---> 點餐 ---> 提交
哈哈,是不是很簡單,其實這個還好,說白了,就是登錄上去,然后拿到cookie,保持一個登錄狀態,然后再去點餐,點餐就是構造請求,發送到指定的點餐URL上就可以了。
登錄
首先我們點開
https://meican.com/
上面要求我們登錄,我們這里輸入自己的賬號密碼,登錄上去之后可以看見一個請求.
這個請求就是登錄的請求,我們看下需要傳什么參數,然后我們去完全構造這個請求,也就是參數一致,並且帶瀏覽器頭,這里我們也需要去保存cookie,也就是說,我們需要自己的賬號時刻保持online狀態,所以需要保存cookie,需要時候調用
所以我們需要實現如下功能
- 登錄請求構造
- 保持登錄狀態
- 保存cookies
- 使得后來的訪問都帶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 "點餐錯誤!"
所用的知識點一覽
- Python requetst的post,session
- cookie的保存和調用
- json的輸出和瀏覽
- random.choice 的列表元素隨機選擇
- Python構造請求和登錄邏輯