본문 바로가기

Crawler

① Crawling yelp

Yelp(옐프)를 crawling해보겠습니다.


Yelp(옐프)란 미국 최대의 지역 검색&리뷰 사이트로 흔히 맛집 정보로 알고있지만, 음식점 뿐만 아니라  미용실, 세탁소 등 미국 각 지역의 상점들에 대한 정보를 알 수 있는 서비스이다. 주로 미국에서 사용되며 나는 맛집정보에 관해서 정보를 수집할것이다.


yelp : https://www.yelp.com/


일단 yelp 사이트를 분석합니다.



이렇게 마인드맵을 사용하여 yelp에 어떤 정보들이 주어지는지 분석해봅니다.


저는 지역을 "Los Angeles, CA"로 검색해보겠습니다.

그러면 맨 처음으로 url을 확입합니다.

https://www.yelp.com/search?find_desc=&find_loc=Los+Angeles%2C+CA&ns=1임을 확인할 수 있습니다.


url을 분석해보면 검색 지역에 있는 ","(콤마)" "(공백)%2C, +( or %20)로 나타납니다.

https://www.yelp.com/search?find_desc=&find_loc=검색지역&ns=1 이렇게 변합니다.


첫번째로 for문을 제어하기위해 page수를 가져옵니다.

Los Angeles에 restaurant이 몇개가 있는지 가져오기 위해서 도구더보기 -> 개발자도구 ->    버튼을 눌르고 "Page 1 of 1117"을  클릭해 속성과 클래스 이름을 확인합니다.  이는 나중에 각 레스토랑의 url을 가져올때 for문을 제어하기 위해 사용합니다.



그리고 다음 페이지를 넘어가면 url이 변하는 것을 알 수 있습니다.

그러면 url이 https://www.yelp.com/search?find_desc=&find_loc=Los%20Angeles%2C%20CA&ns=1&start=10 임을 알 수 있습니다.

&start=10의 의미는 번호가 10다음 번호인 11부터 출력한다는 것입니다.


하지만 총 레스토랑의 수가 1000을 넘어가면 페이지를 제공하지 않음을 확인했습니다.

그래서 이를 확인하는법은 간단합니다. 

https://www.yelp.com/search?find_desc=&find_loc=Los%20Angeles%2C%20CA&ns=1&start=1000을 실행해보면 됩니다. 

이러면, 나중에 1000까지 for문을 실행하도록 구현하면 됩니다. 하지만 위의 page수를 사용하므로 1117*10한 값이 1000이 넘으면 1000번만 수행하고 넘지 않으면 추출한 page수만 수행하도록 만듭니다.




두번째는 각 레스토랑의 url을 가져오기 입니다.

일단 각 레스토랑의 이름을 누르면 그 레스토랑의 url로 넘어가기 때문에 이름의 속성과 class 이름을 알아봅니다.



각 레스토랑의 url이 속한 a태그의 class이름은 lemon--a__373c0__IEZFH link__373c0__29943 link-color--blue-dark__373c0__1mhJo link-size--inherit__373c0__2JXk5 입니다.

위에서 가져온 page수만큼 for문을 실행하며 한 페이지마다 10개의 레스토랑이 나타나고 각 레스토랑의 url을 가져옵니다.

여기까지 각 레스토랑의 businessUrl을 가져오는 코드가 완성됩니다.


▼최종코드


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# -*- coding: utf8 -*-
 
import requests
from bs4 import BeautifulSoup
import time
import re
import sys
import os
from time import sleep
 
class Information:
    def __init__(self):
        self.business_url = list()
        self.page_max = 0
        self.requests_num = 0
 
    def setinfo(self, url):
        self.url = url
 
    def requests_count(self, request_type):
        self.requests_num += 1
 
        if request_type == "web":
            time.sleep(20)
 
        if self.requests_num == 30:
            self.requests_num = 0
            time.sleep(180)
 
    def Collect_restaurant_page_cnt(self): # for문 제어를 위한 page수 크롤링
        #print(self.url)
        html = requests.get(self.url)
        soup = BeautifulSoup(html.text, "html.parser")
        self.requests_count("web")
 
        page_num = soup.find("span", attrs={"class":"lemon--span__373c0__3997G text__373c0__2pB8f text-color--normal__373c0__K_MKN text-align--left__373c0__2pnx_"})
        page_num = page_num.get_text().split(" ")[3]
 
        if int(page_num) >= 1000:       # 총 레스토랑의 개수가 1000이 넘으면 1000, 작은 경우 페이지수 그대로 page_max에 저장
            self.page_max = 1000
        else :
            self.page_max = int(page_num)
 
        #print(self.page_max)
 
 
    def Collect_restaurant_url(self):
        for i in range(0, self.page_max):
            restaurant_url_list = self.url+"&start="+str(i*10)
            print(restaurant_url_list)
            html1 = requests.get(restaurant_url_list)
            soup1 = BeautifulSoup(html1.text, "html.parser")
            self.requests_count("web")
            for restaurant_name in soup1.findAll('a', attrs={"class":"lemon--a__373c0__IEZFH link__373c0__29943 link-color--blue-dark__373c0__1mhJo link-size--inherit__373c0__2JXk5"}):
                if "?hrid=" not in restaurant_name['href']:      # 각 레스토랑의 이름에서 href속성의 url만 추출
                    self.business_url.append("https://www.yelp.com"+restaurant_name['href'])
                    
    def save_url(self,Location):
        self.Location = Location.replace("\n","")
        file = open("./Research_Url/"+self.Location+"_businessUrl.txt","w")
        file.write('\n'.join(self.business_url))
        self.business_url = list()
        file.close()
 
cs


다음에는 각 레스토랑의 정보들을 크롤링해보겠습니다.

반응형