openpyxl로 xlsx 데이터 수집 예시

일반적으로 Pandas를 이용해 데이터를 정리하지만, openpyxl엑셀 데이터(.xlsx)를 다루는 방법도 있다.

이번 분석에 사용할 데이터는 공공데이터포털에서 다운로드 받을 수 있다.

파일이름을 "pohand_food.xlsx"로 변경하여 사용하였다.


엑셀 행 / 열

엑셀에서의 행은 1, 2, 3 ... 열은 A, B, C ... 와 같이 구성되어 있다. 그리고 "열+행"의 형태로 위치를 나타낸다. 행이 "3", 열이 "B"라면 "B3"과 같이 나타낸다. 

  A B C D E
1 A1 B1 C1 D1 E1
2 A2 B2 C2 D2 E2
3 A3 B3 C3 D3 E3
4 A4 B4 C4 D4 E4
5 A5 B5 C5 D5 E5

 


실습

from openpyxl import load_workbook, Workbook

# https://www.data.go.kr/data/15076682/fileData.do
workbook = load_workbook("pohang_food.xlsx")
selected_sheet = workbook["포항음식점"]

load_workbook을 이용해 xlsx 파일을 불러온다. xlsx 내부에 여러 시트(Sheet)가 존재하는데, 그 중 "포항음식점"이라는 이름의 시트를 불러온다. 

xlsx 시트


print("< 데이터 상위 3개 행 확인 >\n")

for row in selected_sheet.iter_rows(max_row=3):
    for cell in row:
        print(cell.value, end=" | ")
    print("\n")
< 데이터 상위 3개 행 확인 >

순번 | 분류 | 상호명 | 주소 | 특화거리 | 영업시간 | 휴무일 | 좌석수 | 홈페이지 | 업체소개 | 주차정보 | 화장실정보 | 해당여부 | None | None | None | None | None | None | None | None | None | None | None | None | None | 좌표 | None | 대표음식 해당여부 | None | None | None | None | None | None | None | None | None | None | None | None | 주변분류 | 판매 메뉴 | 

None | None | None | None | None | None | None | None | None | None | None | None | 무슬림친화 | 채식여부 | 안심식당 | 모범업소 | 장애인시설 | 외국어가능 | 조식가능 | 예약가능 | 유아시설 | 1인식사 | 포장가능 | 배달가능 | 와이파이사용 | 상품권사용 | 경도 | 위도 | 과메기 | 대게 | 등푸른막회 | 회/물회 | 백숙 | 산채비빔밥 | 삼겹살 | 생선구이 | 아구찜 | 장어 | 조개구이 | 치킨 | 해신탕 | None | None | 

1 | 한식 | 효자착한장어 | 경북 포항시 남구 효성로64번길 12 (효자동) | None | 11:00~22:00 | 무휴 | 72석 | None | 통영산 장어만을 이용한 장어와 더덕이 함께 어울어진 특화된 보양식 | 공용주차장 | 남녀분리 | None | None | None | None | None | None | None | y | None | None | y | None | y | y | 129.340465856113 | 36.0049234785235 | None | None | None | None | None | None | None | None | None | y | None | None | None | None | 장어구이(1kg), 장어회(대), 장어회(중), 더덕구이(한접시), 장어탕, 산꼼장어(대), 산꼼장어(중), 산꼼장어(중), 산꼼장어(소), 카약(해삼,멍게,개불,전복,소라,가리비), 카약(해삼,멍게,개불,전복,소라,가리비,산낙지)), 해물칼국수,  |

현재 선택된 시트는 selected_sheet 객체에 저장되어 있다. iter_rows는 작성한 조건에 맞는 행을 반환한다. 위 코드의 경우, 처음부터 총 3개의 행을 가져와 iterable 객체로 반환한다.

결과를 보면 첫 행과 두번째 행에 걸쳐 인덱스(index)가 작성되어 있는 것으로 추측된다. (아래와 같은 형태)

  A B C D E F ...
1 순번 분류 상호명 주소 특화거리 영업시간 ...
2
3 1 한식 ... ... ... ... ...

그리고 세번째 행부터 구체적인 데이터가 입력되어 있는 것을 알 수 있다.


print("< 분류(B*) 데이터 확인 >\n")

# "데이터 상위 3개 행 확인"으로부터 얻은 정보
COL_CLASS ="B"
COL_NAME = "C"
COL_ADDRESS = "D"
COL_DESCRIPTION = "J"

# 분류(B*) 확인하기
col_class = selected_sheet[COL_CLASS]
class_ = set()

for data in col_class:
    class_.add(data.value)

print(f"분류(B*): {class_}")
< 분류(B*) 데이터 확인 >

분류(B*): {'횟집', '양식', '한정식', '분류', '한식', None, '정육식당', '카페', '일식', '분식', '물회', '기타', '중식', '뷔페'}

B열("분류")에 있는 데이터를 가져와 set에 저장한다. set은 중복된 항목이 제거된 결과를 확인할 수 있다. 

결과를 보면 "횟집", "양식", "한정식" 등 항목이 존재하는 것을 확인할 수 있다. 


# 분류 선택 및 데이터 수집
input_class = input("검색할 분류 입력: ").strip()

result = list()
count = 0

for data in selected_sheet[COL_CLASS]:
    if data.value == input_class:
        row = data.coordinate[1:]
        info = list()
        for col in [COL_NAME, COL_ADDRESS, COL_DESCRIPTION]:
            info.append(selected_sheet[col + row].value)
        result.append(info)

        count += 1  

print(f"데이터 수집: {count}회")
검색할 분류 입력: 카페
데이터 수집: 75회

분류를 "카페"로 가지는 데이터를 수집해 보았다. 위 코드의 data는 하나의 cell 객체를 담고 있기 때문에 .value를 통해 세부적인 값을 가져와야한다. coordinate는 "D3"과 같이 cell의 위치를 가져온다. coordinate[1:]을 활용하면 셀의 행 값을 가져올 수 있다. 

해당 데이터는 총 75개의 항목이 검색되었다. 


print(f"< {input_class} 상위 3개 목록 확인 >\n")

for i, info in enumerate(result):

    name = info[0]
    address = info[1]
    description = str(info[2]).replace("_x000D_", "").replace("\n", " ")

    print(f"{i + 1}. {name}")
    print(f"주소: {address}")
    print(description)
    print("-" * 30)

    if i == 2:
        break
< 카페 상위 3개 목록 확인 >

1. 청하엘마론(홍게네식빵)
주소: 경북 포항시 북구 청하면 청하로 165
청하에서 유일한 베이커리 카페입니다. 모든 빵은 주인이 직접 만들며 호두단팥빵이 특히 맛잇습니다.
------------------------------
2. 145(일사오)
주소: 경북 포항시 북구 해안로445번길 13, 1층 (환호동)
저희집은 영일대 해수욕장으로 이어지는 분위기 좋은 여남에 위치하여 있으며 영일만의 뷰가 아름답습니다. 여남은 작은 어촌 마을로 조용하고 공기가 좋습니다. 조식이 가능합니다. 다양한 음료와 케익.브런치가 준비되어 있습니다.  
------------------------------
3. The Clover
주소: 경북 포항시 남구 희망대로 1189, 2층 (송도동)
이색적인 디자인이 눈을자로잡습니다 이태리한 감각적분위기를살렸으며 바로앞은 바다가한눈에보이는전경까지 멋집니다 눈꽃빙수는 이미 맛과눈을사로잡아 여름 인기메뉴입니다
------------------------------

상위 항목 3개를 출력해 데이터가 정상적으로 추출되었는지 확인한다. 처음에 출력했을 때 _x00D_가 문자열에 포함되어 있어서 제거한 상태로 출력해 주었다. 


import os

DIR = os.getcwd()
FILE_PATH = os.path.join(DIR, "result.xlsx")
index = ("상호명", "주소", "소개")

wb = Workbook()
sheet = wb.active

sheet.append(index)
for row in result:
    sheet.append(row)
wb.save(FILE_PATH)

print(f"{FILE_PATH} 저장 성공")
c:\ ... \result.xlsx 저장 성공

Workbook을 생성하고 save 메서드를 사용하면 데이터를 .xlsx 형식으로 저장할 수 있다. 저장된 데이터는 아래와 같이 나타난다. 

result.xlsx