본문 바로가기

회고록(TIL&WIL)

TIL2022.06.05 TODAY_LUNCH(요기요 크롤링, csv load-DB 저장)

요기요크롤링

음식점 데이터들을 모으기 위해서 요기요 사이트를 크롤링하였습니다.

API를 이용해서 크롤링해오는 방법도 있었으나 생각보다 많은 데이터들을 가져오지않고 방법도 확실하게 알지 못해서

selenium을 이용해서 직접 웹사이트에 하나하나 접근해서 BeautifulSoup로 각각의 태그에 있는 value들을 가져와서

데이터를 모아서 csv형태로 저장하는 방식으로 데이터 수집

crawling.py

# 요기요 크롤링
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import time, os
import pandas as pd
import requests


# 한식 요기요 페이지 가게 리스트
link = "https://www.yogiyo.co.kr/mobile/#/"

# 크롬드라이버 연결
driver = webdriver.Chrome('D:/chromedriver_win32/chromedriver.exe')
driver.get(link)
driver.refresh()

# 화면 크기 지정
driver.maximize_window() # 화면 최대화 모드로 변경
time.sleep(1)

# 요소 찾기 - 검색창찾고 키 전송
search = driver.find_element_by_css_selector('.form-control')
search.clear()
search.send_keys('서울특별시 강남구 역삼동 858 강남역')

# 데이터 프레임 생성
df = pd.DataFrame(columns=['name', 'address', 'image'])

for i in range(1, 50):
    # 검색어 새로 고침
    search.send_keys(Keys.ENTER)
    time.sleep(3)

    # 카테고리 리스트 클릭
    driver.find_element_by_xpath('//*[@id="category"]/ul/li[6]').click()
    time.sleep(2)

    if i >= 25:
        # 화면 맨아래로 스크롤 한번
        driver.execute_script('window.scrollTo(0, 550);')
        time.sleep(2)

    # 가게찾아서 클릭
    driver.find_element_by_xpath(f'//*[@id="content"]/div/div[4]/div/div[2]/div[{i}]/div').click()
    time.sleep(2)

    # 크롤링 작업
    # 레스토랑 정보 선택
    restaurant_info = driver.find_element_by_xpath('//*[@id="content"]/div[2]/div[1]')
    # 레스토랑 정보들 긁어와서 퓨티풀수프해서 HTML 파싱
    soup = BeautifulSoup(restaurant_info.get_attribute('innerHTML'), 'html.parser')
    # 가게이름, 주소, 가게 대표 이미지 찾기
    name = soup.find(class_='restaurant-name ng-binding').text
    address = soup.select_one('#info > div:nth-child(2) > p:nth-child(4) > span').text
    image = soup.find(class_='logo')['style']
    # 가게 대표 이미지 url 가져와서 파일로 저장
    image_url = image.split('url')[1].split('"')[1]

    img_data = requests.get(image_url).content
    path = 'static/' + name + '.jpg'
    with open(path, 'wb') as handler:
        handler.write(img_data)

    print(name, address, image_url)

    df = df.append({
        'name': name,
        'address': address,
        'image': path,
        'category': '양식'
    }, ignore_index=True)

print(df)
# csv 파일로 저장
df.to_csv('restaurant_we.csv', index=False)

driver.stop_client()
driver.close()

카테고리(한식,중식,일식,양식)별로 총 4번 작업해서 데이터 하나로 합쳐서 restaurant.csv 파일 완성

 

csv load-DB 저장

db_uploader.py

#임포트
import os
import sys
import csv
import django

#환경변수 세팅(뒷부분은 프로젝트명.settings로 설정한다.)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "today_lunch.settings")
django.setup()

# model import
from restaurant.models import *

#읽어들일 csv 디렉토리를 각 변수에 담는다.
RESTAURANT = 'restaurant.csv'

#함수 정의하기 (row부분엔 해당 table의 row명을 적어준다.)
def insert_Restaurant():
	# 카테고리들이 Foreign key 로 설정되어있기 때문에 우선 create
    Categories.objects.create(restaurant_category='한식')
    Categories.objects.create(restaurant_category='중식')
    Categories.objects.create(restaurant_category='일식')
    Categories.objects.create(restaurant_category='양식')
    with open(RESTAURANT, encoding='utf-8') as csv_file:
        data_reader = csv.reader(csv_file)
        next(data_reader, None)
        for row in data_reader:
            if row[0]:
                name = row[0]
                address = row[1]
                image = row[2]
                category = row[3]
                print(name, address, image, category)
                Restaurant.objects.create(restaurant_name=name,
                                          restaurant_address=address,
                                          restaurant_image=image,
                                          restaurant_category_id=category)
    print('MENU DATA UPLOADED SUCCESSFULY!')
#print 부분은 터미널에서 파일을 실행했을때 데이터 입력이 잘 되었는지 확인하는 용도로써 필수요소는 아니다.
# 함수 실행
insert_Restaurant()