Day 2 – 寫爬蟲抓大眾點評的店家資料

這兩天為了做實驗需要一系列店家的資料,翻了一下 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')

相關連結


發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *