21.3.2

0

<CSV 및 크롤링 경험>

  1. 과제 1: 스타벅스 메뉴 홈페이지에서 음료와 이미지 URL을 연결하기 코드
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. 과제 2 : 위스타벅스 자료 바탕으로 스타벅스 홈페이지에서 자료 크롤링 해보기
  • 해보려고 했던 크롤링 자료 : 영양정보, 카테고리
  • 결과 : 실패

영양정보

시도 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

  • 표가 사용된 HTML 태그에서는 다른 접근이 필요하다. 판다스에 대해 알아보고 사용했다.

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 파일로 봐도 이상하게 저장되어 있다.(내용이 없고 컬럼만 있음)

결론 : 스타벅스 홈페이지가 크롤링에는 아주 쉬운 난이도는 아니었다. 하지만 엮여있는 자료는 충분히 크롤링할 수 있었도 이 기회에 find, find_all 사용법. 셀리니움 사용법, csv 파일 만들기는 많이 익숙해졌다.

실패를 통해 배운점 :

  • 에러를 찾을 때는 print로 하나 하나 위로 올라가며 찾는다.
  • 셀리니움 사용 시 쓸 수 있는 메서드, 함수에 대해서 나중에 시간이 나면 조금이나마 배워보자는 것을 다짐했다.(있는지 몰랐다. 워낙 bs4만 쓰다 보니..)
  • 판다스 및 다양한 모듈에 대해서(물론 설치했지만 배웠다.)
    참고 링크 :
    참고 스택오버플로어
profile
커피 내리고 향 맡는거 좋아해요. 이것 저것 공부합니다.

0개의 댓글