Python을 사용하여 Yelp를 스크랩하는 방법

댓글: 0

Yelp에서 데이터를 스크랩하면 이름, URL, 요리, 평점과 같은 세부 정보를 포함하여 지역 식당에 대한 귀중한 인사이트를 얻을 수 있습니다. 이 튜토리얼에서는 요청과 lxml Python 라이브러리를 사용하여 Yelp 검색 결과를 스크랩하는 방법을 보여드립니다. 프록시 사용, 헤더 처리, XPath로 데이터 추출 등 여러 가지 기술을 다룹니다.

1단계: 환경 설정

스크래핑 프로세스를 시작하기 전에 Python과 필요한 라이브러리가 설치되어 있는지 확인하세요:

pip install requests
pip install lxml

이러한 라이브러리는 Yelp에 HTTP 요청을 보내고, HTML 콘텐츠를 구문 분석하고, 필요한 데이터를 추출하는 데 도움이 됩니다.

2단계: Yelp에 요청 보내기

먼저 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 헤더 이해하기

웹사이트에 요청을 할 때는 적절한 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)

3단계: lxml로 HTML 콘텐츠 구문 분석

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 사용

XPath는 HTML 문서에서 노드를 탐색하고 선택하기 위한 강력한 도구입니다. 이 자습서에서는 XPath 표현식을 사용하여 각 레스토랑 요소에서 레스토랑 이름, URL, 요리 및 등급을 추출해 보겠습니다.

다음은 각 데이터 요소에 대한 구체적인 XPath입니다:

  1. 레스토랑 이름: .//div[@class="businessName__09f24__HG_pC y-css-ohs7lg"]/div/h3/a/text()
  2. 레스토랑 URL: .//div[@class="businessName__09f24__HG_pC y-css-ohs7lg"]/div/h3/a/@href
  3. 요리: .//div[@class="priceCategory__09f24___4Wsg iaPriceCategory__09f24__x9YrM y-css-2hdccn"]/div/div/div/a/button/span/text()
  4. 평가: .//div[@class="y-css-9tnml4"]/@aria-label

4단계: 각 레스토랑 목록에서 데이터 추출

이제 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)

5단계: 데이터를 JSON으로 저장

데이터를 추출한 후에는 데이터를 구조화된 형식으로 저장해야 합니다. 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 댓글