import re
import csv
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
# 필요한 모듈 임포트
csv_name = "starbucks_prc.csv"
csv_open = open(csv_name, "w+", encoding="utf-8")
csv_writer = csv.writer(csv_open)
# csv 파일 자동으로 불러 읽어 저장하는 로직
url = "https://www.starbucks.co.kr/menu/drink_list.do"
driver = webdriver.Chrome("/Users/daminan/Downloads/chromedriver")
driver.get(url)
html = driver.page_source
bs = BeautifulSoup(html, 'html.parser')
# 셀레니움 이용했긴 했지만 뷰티플 숲 같이 이용
drinks = bs.find_all("li", {"class" : "menuDataSet"})
for drink in drinks:
img_tag = drink.find('img')
img_url = img_tag['src']
name = img_tag['alt']
csv_writer.writerow((name, img_url))
# 마침 이미지 url에 음료 이름과 이미지 url이 같이 있었음.
csv_open.close()
driver.quit()
# 꼭 파일 닫아주기. 크롬창 닫기(자동 종료)
시도 1 : 먼저 for loop 를 이용하여 find, find_all로 찾은 자료를 루핑하여 스트링을 낸다. : 스트링을 만들긴 했지만 이후 정렬이 되지 않아 실패
시도 2 : 스트링을 리스트화 시켜서 for loop시킨 후 정렬한다 : 글자가 하나 씩 나와서 다 깨지는 바람에 실패
시도 3: 표 형태(tr, td 착안) 이용해서 pandas 이용 : 이해 불가로 실패
시도 4: 태그의 선택자 이용하여 for loop 돌리기 :
음료 이름과 표 내용을 한 줄씩 가져오기 위해 루프 돌렸으나 중간 중간 막히는 데이터가 있었고 룹이 되지 않음. 실패
# kcal = bs.select('#container > div.content > div.product_result_wrap.product_result_wrap01 > div > dl > dd:nth-child(4) > table:nth-child(2) > tbody > tr > td:nth-child(2)')
# sugar = bs.select('#container > div.content > div.product_result_wrap.product_result_wrap01 > div > dl > dd:nth-child(4) > table:nth-child(2) > tbody > tr > td:nth-child(3)')
# protein = bs.select('#container > div.content > div.product_result_wrap.product_result_wrap01 > div > dl > dd:nth-child(4) > table:nth-child(2) > tbody > tr > td:nth-child(4)')
# sodium = bs.select('#container > div.content > div.product_result_wrap.product_result_wrap01 > div > dl > dd:nth-child(4) > table:nth-child(2) > tbody > tr > td:nth-child(5)')
# fat = bs.select('#container > div.content > div.product_result_wrap.product_result_wrap01 > div > dl > dd:nth-child(4) > table:nth-child(2) > tbody > tr > td:nth-child(6)')
# caffein = bs.select('#container > div.content > div.product_result_wrap.product_result_wrap01 > div > dl > dd:nth-child(4) > table:nth-child(2) > tbody > tr > td:nth-child(7)')
# print(names)
# with open(csv_name, "w+", encoding = "utf-8") as file:
# for i in range(1, len(names) + 1):
# print(name[i])
# names = name[i]['name']
# kcal = kcal[i]['kcal']
# sugar = sugar[i]['sugar']
# protein = protein[i]['protein']
# sodium = sodium[i]['sodium']
# fat = fat[i]['fat']
# caffein = caffein[i]['caffein']
# print([name, kcal, sugar, protein, sodium, fat, caffein])
멘토님 코칭 : 위의 작업까지 같이 도와주시긴 함. 크롤링 중 표를 크롤링 하는 작업은 상당히 고되고 쉽지 않음.(하려면 할 순 있음). 일단 다른 주제에 집중하기로.
하지만 포기할 수 없었다.
시도 5 : pandas
import pandas as pd
tables = pd.read_html("https://www.starbucks.co.kr/menu/drink_list.do")
print(tables[0])
에러 : ImportError: lxml not found, please install it
이유 : pip install
lxml 미설치
과정 상 나온 결과 :
Empty DataFrame
Columns: [메뉴, 칼로리(Kcal), 당류(g), 단백질(g), 나트륨(mg), 포화지방(g), 카페인(mg)]
실패 이유 : 깊은 td, tr을 가져 오지 못 함
시도 6 : pip install html5lib
설치하여 pandas 응용하기
for body in bs("tbody"):
body.unwrap()
df = pd.read_html(str(bs), flavor="bs4")
print(df[0])
-결과
메뉴 칼로리(Kcal) 당류(g) 단백질(g) 나트륨(mg) 포화지방(g) 카페인(mg)
0 나이트로 바닐라 크림 75 10 1 20.0 2 245
1 나이트로 콜드 브루 5 0 0 5.0 0 245
2 돌체 콜드 브루 265 29 8 115.0 9 150
3 바닐라 크림 콜드 브루 125 11 3 58.0 6 150
4 제주 비자림 콜드 브루 340 44 10 115.0 8 105
5 콜드 브루 5 0 0 11.0 0 150
6 콜드 브루 몰트 510 40 10 147.8 20 150
7 콜드 브루 플로트 230 18 3 69.0 10 150
이게 제대로 된건지 모르겠으나 일단 원하는데로 표가 나왔다. 다른 음료도 나올 수 있는지 진행해봐야겠다.
해본 결과 :
for body in bs("tbody"):
body.unwrap()
df = pd.read_html(str(bs), flavor="bs4")
print(df)
모든 결과가 표로 나왔다!!!
시도 : 마찬가지로 for loop , find_all, find 이용하여 자료 추출. 추출까지는 완료했으나 음료와 엮지 못해 실패. 음료와 엮으려면 음료와 태그가 엮여있어야 하는데 이것도 표 형태로 따로 저장되어 있었음.(dt, dd태그). 그리고 csv 파일로 봐도 이상하게 저장되어 있다.(내용이 없고 컬럼만 있음)