Yelp에서 데이터를 스크랩하면 이름, URL, 요리, 평점과 같은 세부 정보를 포함하여 지역 식당에 대한 귀중한 인사이트를 얻을 수 있습니다. 이 튜토리얼에서는 요청과 lxml Python 라이브러리를 사용하여 Yelp 검색 결과를 스크랩하는 방법을 보여드립니다. 프록시 사용, 헤더 처리, XPath로 데이터 추출 등 여러 가지 기술을 다룹니다.
스크래핑 프로세스를 시작하기 전에 Python과 필요한 라이브러리가 설치되어 있는지 확인하세요:
pip install requests
pip install lxml
이러한 라이브러리는 Yelp에 HTTP 요청을 보내고, HTML 콘텐츠를 구문 분석하고, 필요한 데이터를 추출하는 데 도움이 됩니다.
먼저 HTML 콘텐츠를 가져오기 위해 Yelp 검색 결과 페이지에 GET 요청을 보내야 합니다. 방법은 다음과 같습니다:
import requests
# Yelp 검색 페이지 URL
url = "https://www.yelp.com/search?find_desc=restaurants&find_loc=San+Francisco%2C+CA"
# HTML 콘텐츠를 가져오기 위해 GET 요청을 보냅니다.
response = requests.get(url)
# 요청이 성공했는지 확인
if response.status_code == 200:
print("Successfully fetched the page content")
else:
print("Failed to retrieve the page content")
웹사이트에 요청을 할 때는 적절한 HTTP 헤더를 포함해야 합니다. 헤더에는 요청을 하는 브라우저나 도구를 식별하는 사용자 에이전트와 같은 요청에 대한 메타데이터가 포함될 수 있습니다. 이러한 헤더를 포함하면 대상 웹사이트의 차단이나 스로틀링을 피하는 데 도움이 될 수 있습니다.
헤더를 설정하는 방법은 다음과 같습니다:
headers = {
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'accept-language': 'en-IN,en;q=0.9',
'cache-control': 'no-cache',
'dnt': '1',
'pragma': 'no-cache',
'priority': 'u=0, i',
'sec-ch-ua': '"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Linux"',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'none',
'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36',
}
response = requests.get(url, headers=headers)
대량의 페이지를 스크랩할 때 대상 사이트에 의해 IP 주소가 차단될 위험이 있습니다. 이를 방지하려면 프록시 서버를 사용하는 것이 좋습니다. 이 가이드에서는 자동 로테이션 기능이 있는 동적 프록시 서버를 사용하는 것이 좋습니다. 이렇게 하면 프록시 서버 설정을 한 번만 설정하면 되고, 로테이션을 통해 주기적으로 IP 주소를 변경하여 액세스를 유지하므로 차단될 가능성을 줄일 수 있습니다.
proxies = {
'http': 'http://username:password@proxy-server:port',
'https': 'https://username:password@proxy-server:port'
}
response = requests.get(url, headers=headers, proxies=proxies)
HTML 콘텐츠가 확보되면 다음 단계는 이를 구문 분석하여 관련 데이터를 추출하는 것입니다. 이를 위해 lxml 라이브러리를 사용하겠습니다.
from lxml import html
# lxml을 사용하여 HTML 콘텐츠 구문 분석
parser = html.fromstring(response.content)
검색 결과 페이지의 개별 레스토랑 목록을 타깃팅해야 합니다. 이러한 요소는 XPath 표현식을 사용하여 식별할 수 있습니다. Yelp의 경우, 목록은 일반적으로 특정 데이터-testid 속성을 가진 div 요소로 래핑됩니다.
# 개별 레스토랑 요소 추출
elements = parser.xpath('//div[@data-testid="serp-ia-card"]')[2:-1]
XPath는 HTML 문서에서 노드를 탐색하고 선택하기 위한 강력한 도구입니다. 이 자습서에서는 XPath 표현식을 사용하여 각 레스토랑 요소에서 레스토랑 이름, URL, 요리 및 등급을 추출해 보겠습니다.
다음은 각 데이터 요소에 대한 구체적인 XPath입니다:
이제 HTML 콘텐츠가 있고 잠재적인 IP 차단을 처리했으므로 각 레스토랑 목록에서 필요한 데이터를 추출할 수 있습니다.
restaurants_data = []
# 각 레스토랑 요소에 대해 반복
for element in elements:
# 레스토랑 이름 추출
name = element.xpath('.//div[@class="businessName__09f24__HG_pC y-css-ohs7lg"]/div/h3/a/text()')[0]
# 레스토랑 URL 추출
url = element.xpath('.//div[@class="businessName__09f24__HG_pC y-css-ohs7lg"]/div/h3/a/@href')[0]
# 요리 추출
cuisines = element.xpath('.//div[@class="priceCategory__09f24___4Wsg iaPriceCategory__09f24__x9YrM y-css-2hdccn"]/div/div/div/a/button/span/text()')
# 평점 추출
rating = element.xpath('.//div[@class="y-css-9tnml4"]/@aria-label')[0]
# 데이터를 저장할 사전 만들기
restaurant_info = {
"name": name,
"url": url,
"cuisines": cuisines,
"rating": rating
}
# 목록에 레스토랑 정보 추가
restaurants_data.append(restaurant_info)
데이터를 추출한 후에는 데이터를 구조화된 형식으로 저장해야 합니다. JSON은 이러한 목적으로 널리 사용되는 형식입니다.
import json
# 데이터를 JSON 파일에 저장
with open('yelp_restaurants.json', 'w') as f:
json.dump(restaurants_data, f, indent=4)
print("Data extraction complete. Saved to yelp_restaurants.json")
import requests
from lxml import html
import json
# Yelp 검색 페이지 URL
url = "https://www.yelp.com/search?find_desc=restaurants&find_loc=San+Francisco%2C+CA"
# 브라우저 요청을 모방하도록 헤더 설정하기
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept-Language': 'en-US,en;q=0.5'
}
# 필요한 경우 프록시 설정
proxies = {
'http': 'http://username:password@proxy-server:port',
'https': 'https://username:password@proxy-server:port'
}
# HTML 콘텐츠를 가져오기 위해 GET 요청을 보냅니다.
response = requests.get(url, headers=headers, proxies=proxies)
# 요청이 성공했는지 확인
if response.status_code == 200:
print("Successfully fetched the page content")
else:
print("Failed to retrieve the page content")
# lxml을 사용하여 HTML 콘텐츠 구문 분석
parser = html.fromstring(response.content)
# 개별 레스토랑 요소 추출
elements = parser.xpath('//div[@data-testid="serp-ia-card"]')[2:-1]
# 추출된 데이터를 저장할 목록을 초기화합니다.
restaurants_data = []
# 각 레스토랑 요소에 대해 반복
for element in elements:
# 레스토랑 이름 추출
name = element.xpath('.//div[@class="businessName__09f24__HG_pC y-css-ohs7lg"]/div/h3/a/text()')[0]
# 레스토랑 URL 추출
url = element.xpath('.//div[@class="businessName__09f24__HG_pC y-css-ohs7lg"]/div/h3/a/@href')[0]
# 요리 추출
cuisines = element.xpath('.//div[@class="priceCategory__09f24___4Wsg iaPriceCategory__09f24__x9YrM y-css-2hdccn"]/div/div/div/a/button/span/text()')
# 평점 추출
rating = element.xpath('.//div[@class="y-css-9tnml4"]/@aria-label')[0]
# 데이터를 저장할 사전 만들기
restaurant_info = {
"name": name,
"url": url,
"cuisines": cuisines,
"rating": rating
}
# 목록에 레스토랑 정보 추가
restaurants_data.append(restaurant_info)
# 데이터를 JSON 파일에 저장
with open('yelp_restaurants.json', 'w') as f:
json.dump(restaurants_data, f, indent=4)
print("Data extraction complete. Saved to yelp_restaurants.json")
사용자가 제한을 우회하고 차단을 피하려면 HTTP 헤더를 올바르게 구성하고 프록시를 활용하는 것이 중요합니다. 최적화되고 안전한 스크래핑 환경을 위해서는 IP 로테이션 자동화를 고려하세요. 동적 주거 또는 모바일 프록시를 사용하면 이 프로세스를 크게 개선하여 탐지 및 차단 가능성을 줄일 수 있습니다.
댓글: 0