阿里工程師如何叫外賣?99%的人猜不到
阿里妹導讀:為了解決訂餐的煩惱,來自高德的阿里工程師勤碩,用技術做了一個非常好玩的事情,希望能給你帶來一些啟發,讓我們一起快樂工作、認真生活。
情景重現
“啪啪啪…”,在一陣急促的鍵盤敲擊聲中,時間不知不覺已經到了4點60分,我已經坐在顯示器前超過3個小時了,辦公室又熱又悶,可以明顯覺察到空氣是不流通的,電腦的風扇散熱提醒我應該調整一下姿勢。
於是我決定起來走一走,站起身,突然覺得身體有點異樣,餓了…
一看錶,已經是4點61分。完蛋,又完美地錯過了5點的訂餐時間… 看來今天的晚餐註定又要湊合捱餓了。哎,要是有一個提醒我及時訂飯的服務就好了,鬧鐘?不不,那麼low的東西怎麼能彰顯我的geek精神呢。
對,做一個釘釘機器人吧,不不,只做一個機器人怎麼夠,既然要做就做個全套的,再研究一下美餐的訂餐資料,找到最好吃的最受歡迎的套餐,恩,聽起來不錯,就這樣,動手!
背景介紹
在開始今天的“故事”之前,先跟大家科普一下:美餐App。
這個外賣App的主要功能,是每天能夠定時定點投喂外賣給加班的程式猿,而美餐的訂餐最後截止時間在每天的下午5點準時停止。所以如果你沉迷工作廢寢忘食而錯過了投食的申請時間,那麼抱歉,對於沒有時間出去吃一頓的加班汪來說,你就要餓肚子了…
如何抓取資料?
美餐的資料是個很頭疼的問題,因為美餐並不是一個2C的應用,它是企業直接對接美餐,員工才有許可權去瀏覽餐廳的資訊,所以在網上直接爬資料的傳統方法就行不通了。
後來我通過App抓包的方法,發現使用自己的獨立賬號可以抓到所有高德員工有許可權訂餐的公開餐廳資料,整理了一下介面之後總結出了從餐廳選擇到訂餐流程的各個介面的意義(中間還意外的發現了原來美餐還提供了一個web端入口…)。很好,這樣就可以直接拿官方公開的資料開始做資料收集工作了。
訂餐的第一步,也就是選擇可選訂餐地點,這個跟員工的部門有關,我也只能看到高德員工可選的地點,得到的資料格式是這樣(去掉了一些無關的資料):
// API: https://meican.com/preorder/data/group?x={ userId }
{
groups:[
{ title:"首開", ... },
{ title:"方恆國際", ... },
...
]
}
選擇地點之後接著要選擇訂餐時間點,每個時間點的餐廳會有不同,並且帶著當前時間是否可訂的狀態(這個狀態也是我們做訂餐機器人判斷是否可訂餐的重要依據,欄位status),介面資料如下(去掉了一些無關資料):
// API: https://meican.com/preorder/api/v2.1/calendarItems/list?beginDate=2017-11-1&endDate=2017-11-8&withOrderDetail=false)
// 預設會得到一週的可訂餐資訊,也可以設定開始時間和結束時間
{
dateList: [
{
calendarItemList:[
{
openingTime:{
closeTime:"16:30",
...
},
title:"高德地圖(首開外賣)晚餐1"
status:"NOT_YET",
...
從介面資料還可以知道訂餐截止的時間,那麼就可以根據這個做出最晚訂餐時間的安排計劃,比如我希望能在截止時間前30分鐘提醒我。
接著選擇我們想要的時間地點組合,例如上面的 “18:30 高德地圖(首開外賣)晚餐1”,就會得到所有可選店鋪的列表:
// API: https://meican.com/preorder/api/v2.1/restaurants/list?&tabUniqueId=ff4df9a0-9851-4205-adae-b154cc05d811&targetTime=2017-11-01+16:30
{
restaurantList: [
{
availableDishCount:80,
dishLimit:100,
latitude:39.991464,
longitude:116.396763,
name:"宅食送(UBP店)",
...
返回資料裡不光有店鋪資訊和地理位置,居然還有可以總訂餐量(dishLimit)和當前可訂量(availableDishCount),這就十分貼心了,這個資料就可以用來分析餐廳受歡迎的情況。
如何設計一個發通知的機器人?
我們已經得到了資料,那麼就需要完成計劃的第一步,做一個釘釘機器人來告訴我“該訂餐了”。步驟如圖所示:
開啟釘釘的聊天視窗,找到機器人
直接新增機器人,然後選擇自定義機器人
然後下一步,最後會給你一個webhook,那個就是用來發送推送的hook
然後只需要在程式碼裡合適的時機post這個webhook 就可以觸發機器人在當前聊天群裡的動作了
推送有個很好的功能就是支援markdown,這樣就可以很方便的組織內容。
更加詳細的推送內容格式和方法參考這裡的釘釘官方開發文件:
https://open-doc.dingtalk.com/docs/doc.htm?spm=a219a.7629140.0.0.karFPe&treeId=257&articleId=105735&docType=1
我選用Node.JS來做推送服務,首先是抓取資料,做過濾,格式轉換,然後當 ”status“值為“AVAILABLE”且當前時間比結束時間早3個小時的時候通知我,程式碼會隔一分鐘訪問一次介面,這樣就不會在同一分鐘內通知我兩遍,這樣推送的程式碼就完成了(程式碼我會放在文章結束)。
另外我還在推送內容里加上一張來自網路的隨機美圖來促進我的食慾。
最後把工程放入Docker裡,每天在後臺跑著,通過機器人定時推送給我訊息,就再也不用擔心錯過訂餐啦~
終極問題——吃什麼?
吾日三省吾身,早中晚餐該吃啥。
對於有選擇恐懼症的我來說,每天在思考吃什麼這個終極哲學問題上浪費了大量的時間,而且在App上並沒有圖示和評價,所以這大概是一次基於個人經驗和口口相傳的盲選…
為了解決這個問題,我們抓到的資料不正好派上用場嘛,於是我把所有時間點的所有店鋪的資料都抓下來看看。
看看資料
然而真實情況是資料量並不大,我嘗試過抓取幾個月前半年以前的資料,但是發現所有的資料大概只會儲存一個月左右的。
全部出現過的店鋪資料
高德望京周圍店鋪地理位置圖
可以看到店鋪大致都是分佈在公司的周圍,畢竟太遠的也不會承接這麼大規模的送餐。有一個比較好玩的是有一個很奇葩的店鋪開在海上,恩… 這一定是個髒資料…
得到資料之後,我們先來計算每日總訂餐率,取了60天的資料,去除了一些干擾資料之後,用當天所有實際餐廳訂餐數除以餐廳可訂總數,得到每日總訂餐數(r為出現餐廳數量,order為該餐廳訂餐數,dish為該餐廳可訂總量):
這樣可以反映出當天的總體訂餐情況,可以看到起資料還是有明顯起伏的。然後我檢查了他們對應的時間,其中10-29日達到了100%訂餐,也就是所有店鋪的餐全部訂光了,檢查了一下資料,發現那一天只有一家店鋪在提供晚飯,所以被訂光也是可以理解的。
之後計算餐廳的平均訂餐率(雖然餐廳資料量級比較小,但訂餐率也能在某種程度上反映餐廳的訂餐實際情況,也不失為一種判斷標準),具體來說就是將餐廳出現天數中的訂餐量之和除以可訂餐總量之和,餐廳訂餐率如下:(days為出現天數,order為訂餐數,dish為可訂總量):
這也就側面反映了餐廳的受歡迎程度。計算後發現近60天的訂餐率最高的是金百萬,有87.7%的訂餐率,成為最受大家歡迎的店鋪,其次是麗華快餐,訂餐率達到87.1%,第三名是小芝麻。而最不受歡迎的店鋪果然是蘭州牛肉拉麵,訂餐率只有12.3%,這也挺符合大家平時的評價…
通過這樣就找到公司附近這段時間最優質的外賣,對於我這種選擇恐懼症來說,大大縮短了選擇的時間,還可以定期看一看最近的店鋪情況,會第一時間發現有新的店鋪加入,這樣就在訂餐的時候,掌握更多更好的資訊。比較遺憾的是,美餐並不提供每個餐廳裡菜品的訂餐資料,不然我們就可以根據這個選擇最受歡迎的菜品。
寫在最後
因為實際需求的關係,所以只做了美餐的資料爬取和分析,希望本文能夠拋磚引玉,有興趣的同學也可以對其它外賣平臺做一些資料的挖掘分析,拯救每天思考吃什麼的終極哲學問題。
如果大家有什麼更好的解決方案,也歡迎在留言區討論,我們一起探討交流~
部分圖片攝影:阿里小二尼澳
你可能還喜歡
點選下方圖片即可閱讀
關注「阿里技術」
把握前沿技術脈搏