前言
現在疫情肆虐,全台提升至第三級警戒,餐廳也被限制不能內用,只能被迫發展外帶(外送)或休店,因而許多人開始轉往像 foodpanda、Ubereats 此類餐飲外送平台來訂餐,也避免外出與人接觸的風險。
今天的Python網路爬蟲實例系列將來介紹 foodpanda(網頁版) 該如何搜尋餐廳、查看餐廳資訊與菜單,看看它是如何發出請求、解析回傳資料。
備註:此文僅教育學習,切勿用作商業用途,個人實作皆屬個人行為,本作者不負任何法律責任。
套件
此次 Python 爬蟲主要使用到的套件:
安裝
|
|
搜尋餐廳
請求路徑與參數
假如我目前位在"高雄車站",想要喝杯"星巴克"的美式咖啡,因此我到 foodpanda 搜尋"星巴克",點擊"搜尋"。
此時在瀏覽器的 開發人員工具 (F12 或 Ctrl + Shift + i) > Network(網路) > XHR 分頁,會看見一個 feed 的請求(如果沒出現再重新搜尋),裡面放的即是搜尋出來的餐廳結果。
切到 Headers 查看請求的方式與參數。
網址是 https://disco.deliveryhero.io/search/api/v1/feed
、使用 POST
方法、需要帶的 payload
。
我將其整理出來,相關參數如下:
Request URL:https://disco.deliveryhero.io/search/api/v1/feed
Request Methon:POST
Request Payload:
|
|
foodpanda 會依照你附近的餐廳去搜尋,因此請求內需要帶入經緯度,你可以用自己目前所在的位置,或指定特定位置。
例如我使用 Google 地圖點擊地點後,在網址列的部分可以看到此地點的經緯度:
q
參數就是放入搜尋的關鍵字。
limit
與 offset
即是限制此次請求的最大資料筆數與偏移值,如果請求你使用 limit:48 offset:0
(第一頁),那改成 limit:48 offset:48
就是第二頁。
其餘參數照原樣帶入即可,以及有些可以刪除。
回傳資料
回傳資料內,data['feed']['count']
會顯示此搜尋的餐廳總數,在 data['feed']['items'][0]['items']
存放著搜尋結果(餐廳列表)。
餐廳列表包含著每一間餐廳的基本資訊,像是"餐廳名稱"、"地址"、"評分"、"評論數量"、"餐廳圖片"等等,詳細可參考底下 JSON 內資料。
回覆資料範例:fp_search.json (單一一間餐廳)
範例程式
使用 Python 搭配 requests 套件的寫法如下:
|
|
* 傳入 Payload 前需要用 json.dumps()
將其轉成 JSON 格式。
* Headers 內要加入 content-type(HTTP 內容類型)
來表明用 JSON 格式來傳遞參數資料。
除了透過"搜尋關鍵字"來取得餐廳列表,接下來介紹常見的"附近所有餐廳"、"分類推薦的餐廳"兩種方式。
取得附近所有餐廳
請求路徑與參數
網址是 https://disco.deliveryhero.io/listing/api/v1/pandora/vendors
、使用 GET
方法以及需要的查詢參數Query String Parameters
。
經過測試,請求的標頭還需要帶上'x-disco-client-id': 'web'
。
整理出來,相關參數如下:
Request URL:https://disco.deliveryhero.io/listing/api/v1/pandora/vendors
Request Methon:GET
Request Headers:{'x-disco-client-id': 'web'}
Query String Parameters:
latitude: 22.6394088
longitude: 120.3025474
language_id: 6
include: characteristics
dynamic_pricing: 0
configuration: Original
country: tw
customer_id:
customer_hash:
budgets:
cuisine:
sort:
food_characteristic:
use_free_delivery_label: false
vertical: restaurants
limit: 48
offset: 0
customer_type: regular
還可以透過帶入不同的參數值,來達到對結果做不同的篩選。
取餐方式
外送
vertical: restaurants外帶自取
vertical: restaurants
opening_type: pickup生鮮雜貨
vertical: shop
排序方式
排序 | sort: |
---|---|
排序(預設) | |
評分最高 | rating_desc |
最快送達 | delivery_time_asc |
距離 | distance_asc |
例如想將結果的餐廳依照"評分最高到低"排序,則只需要將 sort 帶入 rating_desc (sort:rating_desc
)。
有折扣
has_discount: 1
料理種類
料理種類 | cuisine: |
---|---|
中港 | 166 |
健康餐 | 225 |
小吃 | 214 |
披薩 | 165 |
日韓 | 164 |
東南亞 | 252 |
歐式 | 175 |
漢堡 | 177 |
甜點 | 176 |
異國 | 183 |
素食 | 186 |
美式 | 179 |
飲料 | 181 |
麵食料理 | 201 |
可多選,例如:“日韓"和"麵食料理"就是 cuisine:164,201
。
特色種類
特色 | food_characteristic: |
---|---|
<pro專屬優惠> | 257 |
<店內價> | 55 |
<每月推薦> | 206 |
<熱搜人氣餐廳> | 207 |
<米其林推薦> | 205 |
<聚餐首選> | 241 |
<買一送一> | 239 |
Vogue野餐日 | 258 |
三明治 | 162 |
便當 | 58 |
咖哩 | 155 |
咖啡輕食 | 191 |
早餐 | 159 |
滷味 | 158 |
火鍋 | 160 |
炸雞 | 154 |
粥 & 湯 | 161 |
鐵板燒 | 156 |
餃子 | 157 |
與"料理種類"一樣可多選。
預算高低
預算 | budgets: |
---|---|
低 | 1 |
中 | 2 |
高 | 3 |
同樣可多選。
回傳資料
回傳資料內,data['status_code']
與 data['message']
顯示本次請求狀態;data['data']['available_count']
會顯示可用的餐廳總數;data['data']['aggregations']['cuisines']
顯示各種"料理種類"的餐廳數量;data['data']['aggregations']['foodCharacteristics']
顯示各個"特色"的餐廳數量;data['data']['items']
列出此次回傳的餐廳列表。
至於餐廳列表中,各餐廳的資訊與文章前一節"搜尋餐廳"的雷同,在此就不再贅述。
回覆資料範例:fp_nearby_restaurants.json
範例程式
使用 Python 搭配 requests 套件的寫法如下:
|
|
取得分類推薦的餐廳
這邊我不太知道要把它叫做什麼名稱,指的是剛進來首頁底下推薦的部分,如下圖:
請求路徑與參數
網址是 https://disco.deliveryhero.io/core/api/v1/swimlanes
、使用 GET
方法以及需要的查詢參數Query String Parameters
。
整理出來,相關參數如下:
Request URL:https://disco.deliveryhero.io/core/api/v1/swimlanes
Request Methon:GET
Query String Parameters:
brand: foodpanda
config: Original
latitude: 22.6394088
longitude: 120.3025474
language_code: zh
language_id: 6
country_code: tw
dynamic_pricing: 0
vertical_type: restaurants
opening_type: delivery
use_free_delivery_label: false
customer_type: regular
取餐方式
外送
config: Original
vertical_type: restaurants
opening_type: delivery外帶自取
config: pickup-control
vertical_type: restaurants
opening_type: pickup生鮮雜貨
config: shops-variant
vertical_type: shop,darkstores
opening_type: delivery
回傳資料
從回傳資料的 data['data']['items']
裡列出不同的推薦分類,例如"優惠主打星⭐"、"在家吃遍全世界"、"本月推薦"等等,各推薦分類底下的 vendors
中也列出各家餐廳。
而各家餐廳的資訊與文章"搜尋餐廳"的說明雷同,在此就不再贅述。
回覆資料範例:fp_category_restaurant.json
範例程式
使用 Python 搭配 requests 套件的寫法如下:
|
|
取得餐廳基本資料與菜單
餐廳基本資料與菜單是在同一個請求中。
請求路徑與參數
網址是 https://tw.fd-api.com/api/v5/vendors/{餐廳代碼}
、使用 GET
方法以及需要的查詢參數Query String Parameters
。
"餐廳代碼"從上方各種取得餐貼列表的方式,其中餐廳資訊裡的 code
欄位即顯示著此餐廳的代碼。
整理出來,相關參數如下:
Request URL:https://tw.fd-api.com/api/v5/vendors/{餐廳代碼}
Request Methon:GET
Query String Parameters:
include: menus
language_id: 6
dynamic_pricing: 0
opening_type: delivery
latitude: 22.639473
longitude: 120.3025185
此時可以改成距離較近的座標,或者乾脆不要帶入座標(但會導致回傳資料的距離不正確)。
回傳資料
從回傳資料的 data['data']
包含此餐廳的資訊,例如前面餐廳列表就有的店名、地址、最低訂購金額外,像是營業時間、折扣活動、餐廳分類、付款類型也有。還有重要的菜單資訊、配料資訊等等,都在這個請求的回應資料裡了。
回覆資料範例:fp_info_menu.json
範例程式
使用 Python 搭配 requests 套件的寫法如下:
|
|
完整程式碼
我將以上四種請求寫在同一個 class 中,並可以傳入不同的值來篩選,供需要的人參考。
附上完整程式碼:foodpanda_spider.py | GitHub
延伸練習
在"搜尋餐廳"與"取得附近所有餐廳"章節中,說到能透過
limit
和offset
來抓到更多的餐廳,試著自己實際寫寫看吧。試著輸入餐廳代碼後,程式自動顯示餐廳的"基本資訊"與隨機五樣"餐點資訊"。
結語
之後會繼續陸續寫一些網站的Python網路爬蟲實例,如果你正好是剛開始想學爬蟲的新手、想知道某網站如何爬取資料、遇到其他問題,也歡迎在底下留言,或追蹤 FB 粉專『IT空間』~ 🔔
還能回頭說明旅途還沒有開始,當你無法回頭的時候,才是真正的旅途。
—— 《比宇宙更遠的地方》
🔻 如果覺得喜歡,歡迎在下方獎勵我 5 個讚~