
這兩天為了做實驗需要一系列店家的資料,翻了一下 Open Data 沒看到類似的資料,想起來之前在上海會用大眾點評來查餐廳,於是開始寫爬蟲來抓店家的資料。
分析 HTML 結構
來到大眾點評高雄的美食列表,通過 Chrome 開發者工具我們可以看到:

- 店家列表是在 <div id=”searchList”></div> 之間
- 每一個店家的資料都是通過 <dd></dd> 包起來的
- 店家名稱在 <li class=”shopname”></li> 之間
- 店家地址在 <li class=”address”></li> 之間
於是我們一樣可以通過 HTMLSession 拿到整個 HTML, 然後取出我們要的內容。
from requests_html import HTMLSession response = session.get(url) # 拿到所有的店家 searchedItems = response.html.find('#searchList') shops = [] for searchedItem in searchedItems: # 拿到 shopname & address items = searchedItem.find('ul.detail') for item in items: name = '' address = '' tel = '' name = item.find('li.shopname a', first=True).attrs['title'] addressTel = item.find('li.address', first=True).text addressTel = addressTel.split('\xa0\xa0') if len(addressTel) == 1: address = addressTel[0] elif len(addressTel) == 2: address = addressTel[0] tel = addressTel[1] shop = {"name": name, "address": address, "tel": tel} shops.append(shop)
如何自動爬下一頁?

我想到可以從每一個列表底下的 pagination 下手,
如果沒有「下一頁」的按鈕,就當作是最後一頁了。

通過 <a class=”NextPage”></a> 其中的 data-ga-page 我們可以拿到下一頁
然後再跑一次我們上面提到的下載流程。
我這裡把上面的方法定義成 downloadFromUrl 來調用。
# 頁數 nextPage = response.html.find('a.NextPage', first=True) if(type(nextPage) == 'NoneType'): print('has no next page') if(nextPage != None): nextPage = nextPage.attrs['data-ga-page'] downloadFromUrl(baseUrl, nextPage)
如何下載所有的城市呢?
其實 URL 本身就可以看出規律
https://www.dianping.com/城市名稱/分類/{p + 頁數}
https://www.dianping.com/kaohsiung/food/p2

而大眾點評在城市選單上可以看到所有城市的英文名稱,於是一切就好辦了。
我把具體的 code 放到 Github 上提供參考。
# 定義所有的城市 cities = [ 'kaohsiung', 'Hengchun', 'hualien', 'keelung', 'chiayi', 'kenting', 'miaoli', 'riyuetan', 'penghu', 'taipei', 'taitung', 'tainan', 'taiwan', 'taichung', 'taoyuan', 'newtaipei', 'hsinchu', 'ilan', 'zhanghua' ] # 下載單一城市所有頁數的資訊 def downloadFromCity(cityName, category): downloadUrl = baseUrl + '/' + cityName + '/' + category + '/p' downloadFromUrl(downloadUrl, 1) # 下載所有城市的資訊 for city in cities: downloadFromCity(city, 'food')