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 |