[DataBase] DB 에 적재할 데이터 가공하기 (Feat.Python) 🦏
개요 🙋
위 사이트에서 커피와 관련된 브랜드별 영양 정보 를 크롤링하여
필요한 정보만을 가공하여 사용하려고 한다.
크롤링한 데이터는 아래와 같다.
이 데이터에서 필요한 정보는 브랜드
, 메뉴
, 카페인
이다.
먼저,
번거롭지만 수기로 1 차 가공을 통해 아래와 같은 정보를 얻은 상태이다.
이 정보를 바탕으로,
MySQL
에 쿼리문을 사용하여 데이터를 적재하려고 하는데,
쿼리문으로 사용하기엔 다소 형식이 맞지 않다고 판단되어,
이를 {brand, name, caffeine}
형식으로 가공하여 적재하고자 한다.
생성 & 삽입 쿼리 🔮
CREATE TABLE IF NOT EXISTS brand (
id INT AUTO_INCREMENT PRIMARY KEY,
brand_name VARCHAR(255),
name VARCHAR(255),
caffeine INT,
url VARCHAR(255)
);
위 쿼리문을 해석 해 보면,
먼저 고유한 id
값을 가지며 1씩 증가하는 옵션이 추가되어있다. 👉 AUTO_INCREMENT
다음으로는 문자열인 커피 브랜드, 메뉴 정보가 있고,
커피 메뉴에 따른 카페인 함량에 대한 정보가 정수형태로 저장될 테이블을 생성 해 준다.
다음으로는 생성한 테이블에 데이터를 삽입하기 위해 쿼리문을 날려주어야 하는데,
아래와 같이 작성 해 주면 될 것이다.
INSERT INTO brand (brand_name, name, caffeine) VALUES
('엔제리너스', '돌체라떼', 317),
('엔제리너스', '카페 연유다', 176),
('엔제리너스', '아메리치노 라떼', 317);
문제는 삽입할 데이터의 양이 너무 많다는것이다 🤦♂️
이를 일일히 수기로 작성하는것은 소위
미련한
짓이다.
때문에,
아래의 방법을 사용하여 쿼리문에 사용할 수 있도록 적절하게 가공하고자 한다.
Python 으로 추출하기 🤓
위 사이트는 Python
을 활용한 코드를 실행시킬 수 있는 IDE
환경이다.
먼저,
1 차 가공 을 마친 객체 형태의 데이터를 변수에 담아 할당 해 준다.
그리고 이를 파싱하여 튜플로 변환하고,
주어진 형식으로 튜플을 출력하고자 한다.
formatted_data = []
for brand, items in coffeeData.items():
for item in items:
formatted_data.append((item['brand'], item['name'], item['caffeine']))
# 튜플 형식으로 출력
output = ',\n'.join([str(item) for item in formatted_data])
print(output)
튜플 형태의 데이터를 저장할 formatted_data
변수에 빈 리스트를 할당하고,
이중 반복문을 통해 coffeeData
의 각 브랜드와 아이템에 접근한다.
외부 루프 (`for brand, items in coffeeData.items(): )
👉 브랜드와 그에 해당하는 아이템을 가져온다.
내부 루프 (
for item in items:
)
👉 각 브랜드의 아이템을 하나씩 가져와 처리한다.
내부 루프 에서는,
아이템의 정보를 추출하여 formatted_data
리스트에 튜플 형식으로 저장한다.
이 때,
각 튜플은 브랜드, 아이템 이름, 카페인
형식으로 구성된다.
다음으로는 리스트 컴프리헨션 문법을 사용하여
formatted_data
리스트의 각 튜플을 문자열로 반환 한 후,
',\n'
을 구분자로 사용하여 하나의 문자열로 결합(join
) 한다.
위 코드를 실행하면 아래와 같이 가공된 데이터를 얻을 수 있다.
JavaScript 로 추출하기 ⚡
크롤링이 아무리 Python
이 쉽다 한들,
이를 JavaScript
에서도 구현 가능해야 옳잖은가 ?
로직은 Python
과 매우 유사하다.
단,
for
문을 사용하지 않고 자바스크립트 내장함수 인 map
을 사용하여 반복할 것이다..
const formattedData =
Object.values(coffeeData).flatMap(items =>
items.map(item => [item['brand'], item['name'], item['price']])
);
const output =
formattedData.map(item =>
`(${item.map(i => JSON.stringify(i)).join(', ')})`).join(',\n');
console.log(output);
주어진 커피 데이터 👉 1 차 가공된 데이터 를 준비하고,
이를 Object.valuse
를 사용하여 객체 형태의 값을 배열로 변환 해 준다.
flatMap
함수를 사용하여 각 브랜드의 아이템들을 하나의 배열로 평탄화(?) 해 준다.
map
함수를 사용하여 각 아이템들을 튜플 형식으로 변환하고
join
메서드를 사용하여 전체 배열을 문자열로 합친다.
평탄화 란 ❔❗
아래와 같이 두개의 동일한 예제가 있을 때map
함수 사용 시 2 차원 배열 이 생성되는 반면,flatMap
함수를 사용하면 이를 1 차원 배열 로return
한다.
즉, 중첩된 이중 구조를 가진 데이터를 단일 수준으로 펼친다 라는 의미를 갖고있다.
const arr = [1, 2, 3];
const mapArr = arr.map((num) => [num, num * 2]);
console.log(mapArr); // [[1, 2], [2, 4], [3, 6]]
const flatMapArr = arr.flatMap((num) => [num, num * 2]);
console.log(flatMapArr); // [1, 2, 2, 4, 3, 6]
데이터 삽입 및 DB 확인 👀
위에 있던 데이터 삽입 쿼리를 Workbench
에서 가공한 데이터를 삽입하고 확인하려 한다.
INSERT INTO brand (brand_name, name, caffeine) VALUES
('엔제리너스', '돌체라떼', 317),
('엔제리너스', '카페 연유다', 176),
('엔제리너스', '아메리치노 라떼', 317);
가공된 데이터를 출력하여 이를 복 붙 하여 가져왔다..
좀 더 단순화 하는 방법이 있을텐데 현재로써는 이게 최선이었다 😭
쿼리문을 실행한 후 생성된 테이블을 조회하면 아래와 같은 레코드를 확인할 수 있다.
Reference 🌊
https://jerryjerryjerry.tistory.com/159
https://dang-dang12.tistory.com/18
https://inpa.tistory.com/entry/MYSQL-%F0%9F%93%9A-%EA%B8%B0%EB%B3%B8-SQL%EB%AC%B8-%EC%A0%95%EB%A6%AC-%ED%85%8C%EC%9D%B4%EB%B8%94-%EC%A1%B0%ED%9A%8C-%EC%83%9D%EC%84%B1-%EC%88%98%EC%A0%95-%EC%82%AD%EC%A0%9C
https://121202.tistory.com/25