top of page
  • SoYeon Cho

[Caffeineea] 2. Data Gathering and Processing

최종 수정일: 2021년 9월 4일


*프로젝트에 사용되는 데이터는 탐앤탐스, 스타벅스, 이디야, 빽다방, 메가커피, 할리스로 총 6개의 카페의 데이터를 사용하였습니다. *



📝 [A. 데이터 수집]

-> 초기에 파이썬으로 이용한 웹크롤링을 통해 데이터를 수집하는 것으로 계획을 세웠습니다. 그러나 각 회사마다 영양정보를 표기하는 방식 이 달라 크게 2가지 방식을 사용하여 정보를 수집하는 방법으로 변경하여 데이터를 수집하였습니다.


① 웹크롤링이 가능한 데이터 수집

-> 빽다방, 메가커피, 할리스

파이썬으로 웹크롤링을 하기 위해 HTML의 원하는 부분만 이용할 수 있게 하는 ""BeautifulSoup "라는 파이썬 라이브러리를 사용했습니다. HTML문서에 담긴 내용을 가져 오기 위해서 requests라는 라이브러리를 사용했습니다. 두 개의 라이브러리를 사용하여 HTML 에서 원하는 부분의 태그를 탐색하여 해당 태그에 해당하는 부분의 데이터를 불러들여왔으며, 필요한 내용의 태그를 확인하는 것은 2가지 방법을 이용했습니다.


첫 번째로는, SelectorGaget이라는 크롬의 확장자 프로그램을 이용하였습니다. SelectorGaget은 실행시키고 원하는 데이터를 클릭하면 아래 사진과 같이 해당 데이터가 어떤 태그, 클래스명, id를 갖는지 표시해주는 프로그램입니다.


두번째로는, 크롬의 개발자도구를 이용하였습니다. 개발자도구를 열어 HTML 문서 마우스 커서를 올리면 문서에 해당하는 부분이 표시가 됩니다.



② 웹크롤링이 불가능한 데이터 수집

-> 이디야, 스타벅스, 탐앤탐스


이디야와 탐앤탐스는 웹크롤링을 하는 것이 불가능했습니다. ①에서 언급한 사이트들은 해당 커피의 영양정보가 모두 한 페이지 안에 있었으나 이디야와 탐앤탐스의 경우는 몇 개의 정보가 표시가 되고 “더보기”버튼을 눌러서 음료의 정보를 보는 방식이었습니다. ①에서 언급한 것과 같은 방식으로 웹크롤링을 시도했으나 첫 페이지에 표시가 된 정보만을 불러 오고 더보기 버튼을 누르면 나오는 정보들을 불러들여올 수 없었습니다. 모두 같은 클래스명을 사용했음에도 크롤링을 하였을 때 첫 페이지에 해당하는 정보들만이 표시가 되었습니다. 그래서 이디야와 탐앤탐스의 경우 크롤링이 아닌 다른 방식으로 데이터를 처리하여야 했습니다. 이디야와 탐앤탐스 모두 음료의 사진이 표시가 되어있고 이 사진을 클릭하면 음료의 이름, 설명, 영양 정보가 나오는 방식으로 표기가 되어 있었습니다. 사진들을 클릭하여 정보를 띄우고 드래그를 하여 정보를 복사하였습니다. 그리고 이 파일을 txt로 저장하고 Python에서 read 모드로 읽어 들였습니다.



스타벅스의 경우 표로 나열된 영양정보 데이터가 있어 이를 드래그하여 txt파일로 저장 하고 Python에서 읽어 들였습니다.




 


🔧 [B. 데이터 가공]

-> 데이터 수집 단계에서 얻은 데이터들은 여러 정보를 담고 있었습니다. 하지만 그 중 필요로하는 정보는 한정적이었기 때문에 필요한 정보들만 추려 원하는 형태로 변형시키는 과정을 거쳐야 했습니다.



< 가공 과정 >
정보들 중 커피이름. 카페인 함량, 칼로리, 나트륨, 당류, 포화지방, 단백질에 해당하는 정보들만 모아 [ 커피이름. 카페인 함량, 칼로리, 나트륨, 당류, 포화지방, 단백질] 를 element로 갖는nested list의 형태로 만들기.



a. 카페별 데이터 ( -> menu바 중 ALL CAFÉ에 해당 )


[ 커피이름. 카페인 함량, 칼로리, 나트륨, 당류, 포화지방, 단백질] 의 형태로 구성된 nested list는 “카페명 _coffee_nutri”라는 이름으로 지정했고, 다음과 같은 과정을 거쳐 데이터를 가공했다.


① 음료 이름과 영양 정보만 남기고 필요 없는 정보 지우기

수집한 데이터에는 메뉴명과 영양정보 말고도 다른 정보들이 섞여있었습니다. 음료 이름이 여러번 적혀 있기도 했고 영어로 된 메뉴 이름, 음료에 대한 설명, 알레르기 성분, 창닫기 등등 여러 정보가 포함되어 있었습니다. 또한, 각각의 카페에서 수집한 데이터가 포함하고 있 는 정보의 형태가 모두 달랐다. 때문에 각각의 데이터들을 for문을 이용해서 필요 없는 정보들은 제거 시켜주었습니다.


📝 ex -> 다음은 이디야의 영양정보 데이터 입니다. 이 데이터 중에서 "커피이름. 카페인 함량, 칼로리, 나트륨, 당류, 포화지방, 단백질"에 해당하는 정보만을 수집하기 위해 데이터들이 어떻게 구성되어 있는지 분석하는 과정을 수행했습니다. 1번째 줄에는 커피메뉴라는 데이터가 있고 그 이후로는 창닫기가 나오기 전까지 모두 같은 메뉴에 대한 설명이 나옵니다. 이에 첫번째 줄에 있는 불필요한 정보를 지우고, 창닫기가 나오기 전까지를 하나의 메뉴에 대한 정보로 설정하였습니다. 이후 "창닫기"라는 string을 기준으로 split을 하였습니다. 이후 Iced와 hot음료를 구분해 name_list를 만들어내었습니다. 그 후 영양정보 데이터를 수집하기 위해 for문을 통해 data를 한 줄씩 돌리면서 kcal이 포함된 line을 선별해 nutri_list의 element로 추가하였습니다.


name_list = [ "아인슈페너", "아메리카노", "라떼", "카푸치노", ...]
nutri_list = [ "칼로리 (103kcal)당류 (13g)단백질 (1g)포화지방 (2.0g)나트륨 (5mg)카페인 (103mg)", ....]

nutri_list의 각 요소들을 for문을 돌리면서 필요한 정보들만 추출하는 작업을 진행했습니다. nutri_list의 각 element를 " "(white space)로 나누어 필요한 정보들을 nutri_organized_list에 저장했습니다.

nutri_organized_list = [ [ 103, 13, 1, 2.0, 5, 103],  [203, 20, 5, 4.2, 8, 90],  ... ]


② 영양정보를 원하는 순서대로 배열하기

각각의 카페 홈페이지마다 영양정보를 표기하는 순서가 달랐습니다. 데이터를 모두 [커피이름. 카페인 함량, 칼로리, 나트륨, 당류, 포화지방, 단백질] 의 형태로 표현하기 위해서 다른 순서로 표기되어 있던 데이터를 원하는 형태로 바꾸어주었습니다.

📝 ex -> nutri_organized_list에 저장된 정보는 처음에 설정한 데이터의 순서와 맞지 않았습니다. 따라서 기존 데이터를 원하는 순서에 맞게 새롭게 list에 저장을 하였습니다.

nutri_organized_list = [ [ 103, 13, 1, 2.0, 5, 103],  [203, 20, 5, 4.2, 8, 90],  ... ]

nutri_organized_list_2 = [ [ 103, 103, 5, 13, 2, 1],  [103, 267, 110, 36, 4.9, 8],  ... ]


③ 음료이름과 영양정보를 따로 수집한 경우 두 데이터 합치기 (한 번에 수집한 경우는 제외)

크롤링을 통해 정보를 수집하는 과정에서 음료의 이름과 영양정보를 따로 가져오는 경우 가 있었습니다. 이런 경우에 두 정보가 하나의 list에서 표현될 수 있도록 for문을 통해 하나의 list로 만들어주었습니다.

📝ex -> 1번의 이디야 예시에서 언급한 두 데이터를 모아 하나의 list로 설정하였습니다.

name_list = [ "아인슈페너", "연유콜드브루", "라떼", "카푸치노", ...]
nutri_organized_list_2 = [ [ 103, 103, 5, 13, 2, 1],  [103, 267, 110, 36, 4.9, 8],  ... ]

ediya_coffee_nutri = [ ["아인슈페너", 103, 103, 5, 13, 2, 1], [ "연유콜드브루", 103, 267, 110, 36, 4.9, 8] ,  .....  ]


 


b. 음료별 데이터

-> 메뉴바 중 HIGH-CAFFEINE, LOW-CAFFEINE, DECAFFEINE HIGH-CAFFEINE, LOW-CAFFEINE


메뉴바에서는 각각 아메리카노, 라떼, 콜드브루, 에스프레소 를 카페인이 높은 순, 낮은 순으로 표기하였습니다. 이를 위해 데이터를 [카페이름, 커피이름. 카 페인 함량, 칼로리, 나트륨, 당류, 포화지방, 단백질] 의 형태로 변형했습니다.


① 아메리카노, 라떼, 콜드브루, 에스프레소에 해당하는 정보만 모으기

a번에서 수집한 각 카페의 전체 커피 데이터에서 아메리카노, 라떼, 콜드브루, 에스프레소 메뉴에 해당하는 LIST만을 따로 뽑아 리스트의 0번 인덱스의 “카페이름”을 insert하여 americano.txt, latte.txt, coldbrew.txt, espresso.txt 파일로 저장을 하였습니다.

ediya_coffee_nutri = [ ["아인슈페너", 103, 103, 5, 13, 2, 1], [ "연유콜드브루", 103, 267, 110, 36, 4.9, 8] ,  .....  ]

ediya_name = [ ["이디야", "아인슈페너", 103, 103, 5, 13, 2, 1], ["이디야",  "연유콜드브루", 103, 267, 110, 36, 4.9, 8] ,  .....  ]




-> cafe_func.py 파일을 만들어 각각의 음료의 정보를 수집하기 위한 함수를 정의했습니다. 예를 들어 americano 함수에서는 (1번에서 가공한 최종 데이터 list, café_name) 2개의 파라미터를 받아들여 list element에 “아메리카노”가 포함되어 있으면 해당 데이터를 americano.txt에 add하는 방식으로 데이터를 처리하였습니다.


② 카페인 함량이 높은 순으로 낮은 순으로 정렬하기

①에서 수집한 데이터를 카페인이 높고 낮은 순으로 정렬하기 위해 새로운 파이썬 파일 을 만들었습니다. 수집한 데이터는 모두 list 안의 string 타입의 데이터로 저장이 되어 있었기 때문에 크고 작은 순을 나열하기 위해서는 int나 float의 형태로 변환을 시켜주었습니다. 그 후 sort를 함으로서 해당 데이터를 카페인이 함량이 높거나 낮은 순으로 정렬하여 저장하였습니다.




 


2021.04 ~ 2021.06



조회수 11회댓글 0개

최근 게시물

전체 보기
게시물: Blog2_Post
bottom of page