背景
眾所周知,上海前些天買菜十分緊張。我所在的地方僅存的供應商也只剩叮咚買菜了,但是只有每天早上6點和8點半會釋放出運力,由於早上起不來,只能白天看着庫存刷是否有運力釋放,但是耗時耗力。於是在清明放假時,想着封在家里也沒啥事,就研究了一下怎么買菜。
環境
Python、Charles(需要能夠抓到https)。
思路
要在有庫存的時候能夠自動下單並且向我的手機發送推送,以免超時未支付。
第一步-抓包
要想知道是否有運力,和自動下單,則必須要能夠拿到查詢運力的接口和下單的接口。
一般通過抓包的方式能夠獲取到接口。於是,我先嘗試用叮咚買菜app抓包,不出所料,是抓不到的。這時候,只能看看其他渠道了,得知叮咚買菜還有小程序端,於是嘗試用小程序抓包,結果自然是可以抓到包,這兩個接口就分別是查詢配送站點運力和下單的接口。注意,下單時我們需要選取送達時間,之后我們如果查詢到了某個時間段有運力的話,需要將下單接口的送達時間參數改成查詢到有運力的時間段,這樣比較麻煩。恰好,叮咚推出了“自動嘗試可用時間”下單功能
。要想以這種方式下單,我們先用Charles的Map Local功能把getMultiReserve的接口的
字段改成true,這樣時間就會展示成上面那張圖。接口我們可以點擊下單按鈕,拿到下單接口的數據。
第二步-邏輯寫進代碼
這里分享一個十分好用的網站 https://curlconverter.com/,這個網站可以把cURL直接轉成各種語言的代碼塊。
代碼邏輯也十分簡單,就是不停的用requests提供的方法調用getMultiReserve接口,看是否有運力,一旦有運力,立即調用addNewOrder接口去下單。
在下單后,需要讓我們知道,這里的處理方法是使用iOS設備,下載一個叫“bark”的app(十分推薦),注冊設備后,會提供url,直接用get方法調用就能夠向設備發送推送,可以在url中定義推送的內容和聲音。
import time
import requests
proxy = '106.14.255.124:80'
proxies = {
'http': 'http://' + proxy,
'https': 'https://' + proxy
} # 這里可以添加個代理(池),防止ip被封
cookies = {}
headers = {}
data_order = ''
data_time = ''
while 1:
response_time = requests.post('https://maicai.api.ddxq.mobi/order/getMultiReserveTime', headers=headers,
cookies=cookies,
data=data_time).text
print(response_time)
if "當前運力緊張" not in response_time and "自動嘗試可用時段" not in response_time:
response_order = requests.post('https://maicai.api.ddxq.mobi/order/addNewOrder', headers=headers,
cookies=cookies,
data=data_order).text
requests.get('https://api.day.app//檢測到有運力,趕快下單?sound=minuet') # 向手機推送
print(time.strftime('%H:%M:%S', time.localtime()) + '檢測有運力,已嘗試下單')
print(response_order)
else:
print(time.strftime('%H:%M:%S', time.localtime()) + '檢測沒有運力')
time.sleep(3)
其他
自動下單成功的前提是購物車內的商品信息沒有發生改變,譬如庫存、價格等。如果發生了變更,需要及時修改腳本里的請求data。要是嫌麻煩的話,可以只輪詢getMultiReserve接口,當有運力時再手動下單即可(一般運力釋放都會持續一會兒,收到推送立馬去下單,成功率還是很高的)。下單成功后需要及時付款。
todo
以上代碼在調了下單接口后,還是會重復運行的,使用過程中出現了重復鎖單的情況。因為沒對下單接口的返回進行分析,后期可以優化一下,如果下單成功或下單失敗,發送相應的通知,並終止程序運行。