본문 바로가기
Programming/python

파이썬으로 엑셀 파일이 안 불러와질 때 할 수 있는 방법 (리눅스 환경)

by 조창대 2023. 10. 31.
반응형

한 사이트에서 엑셀 파일을 다운받아서 파이썬 내에서 열고 데이터를 가공해야 하는 업무가 있었다.

그래서 pandas 의 read_excel 메서드로 파일을 열려고 했으나..

사이트에서 제공하는 엑셀 파일의 확장자가 '.xls'였고, 왜인지 모르게 파일이 손상되어서 해당 메서드로 열 수가 없었다.

파일은 업무용으로 쓰는거라 공개할 수는 없어요..

 

그냥 엑셀 앱에서 열었을 때에도 이런 경고창이 먼저 뜬다 ..

이런 경우엔 '.xls' 확장자를 취급하는 다른 라이브러리를 쓰면 된다고 생각하고 시도해봤다.

 

- win32com : 이걸로 파일이 열려서 신났다. 근데 이 라이브러리는 윈도우 환경에서만 동작하는데, 내가 솔루션 운영하는 서버는 리눅스였다 .. 나가리

 

- xlrd : 많은 문서에서 '.xls' 형식의 파일을 지원한다고 했으나, 내가 다루려는 엑셀 파일은 열지 못했다.

  지금은 해당 기능을 지원하지 않거나 내가 쓰는 엑셀 파일 자체가 손상되어 열지 못 한 것 같다 .. 나가리

 

- pandas.read_excel : 일반적으로 판다스로 엑셀 파일 읽을 땐 read_excel을 쓰는데, 읽지 못했다. 파일이 손상되어서 그런 것 같다.. 나가리

 

엑셀 파일 확장자가 '.xls'에다가 손상되었고, 내 로컬 서버는 윈도우였으나 배포하는 서버는 리눅스라서 호환되는 라이브러리도 없는 미치겠는 상황 ╰(‵□′)╯

 

! 이럴 때는 pandas 라이브러리의 'read_html' 을 써서 html로 불러오는 걸 시도해보기 !

 

열리지 않던 엑셀 파일을 메모장으로 열어보면

 

이런식으로 테이블이 html 형식으로 쓰여지는 파일이 있다. 아마 엑셀 파일 저장할 때 html 포맷으로 저장해서 그런 것 같다.

이 파일들만 'read_html'으로 열 수 있으니 메모장으로 먼저 확인해 보는 게 좋다.


원본 엑셀 파일

'read_html'로 파일을 열어보자.

ex = pd.read_html('test_file.xls', encoding='utf-8')
ex

 

!!!!!!!!!!! 엑셀 파일이 열렸다!!!!!!!!!!!!!

하지만 내가 원했던 테이블이 안 보이고, 데이터프레임 형식으로도 나타나지 않는 것 같다.

데이터프레임으로 열고자 한 테이블 위의 테이블만 열린 듯하다.

 

 

데이터프레임 형식으로 가공


이럴 땐 당황하지 않고 파일을 txt 파일로 복사해서 파이썬에서 txt 파일 열고 수정한다.

 

excel_name_pc = 'test_file.xls'
text_name_pc = 'test_file.txt'

shutil.copy(excel_name_pc, text_name_pc)

shutil.copy은 파라미터로 넣은 파일 경로대로 파일을 복사하는 기능을 한다.

shutil.copy(원래 파일 경로, 복사 파일 경로)

이렇게 지정하면 된다. 나는 현재 디렉토리 안에 복사 파일을 넣을 것이기 때문에 경로 없이 파일 이름만 써줬다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
try:
    # 데이터 파일 .xls -> .txt -> 테이블 수정 -> .txt를 read_html로 오픈
    edited_lines = []
    text_file_path_pc = path + '/' + text_name_pc
    text_file_path_mo = path + '/' + text_name_mo
    # print(text_file_path)
 
    # 텍스트 파일 열어서 테이블 잘 나오도록 수정
    for d in [text_file_path_pc, text_file_path_mo]:
        with open(d, 'r', encoding='utf-8'as f:
            lines = f.readlines()
            edited_lines = []
            for i, j in enumerate(lines, 1): 
                if j.find('순번'!= -1# 헤드 부분 찾기
                    j = j.split('</tr>')
                    j[0+= '</tr>\n'
                    j[0= j[0].replace('td''th').replace('/td''/th'# 2.헤드 부분의 태그를 <th>로 변경
                    edited_lines.append(j[0])
                    edited_lines.append(j[1+ '\n')
                # 1. 필요없는 테이블 삭제
                elif i in range(225271):
                    j = ''
                else:
                    edited_lines.append(j)
            f.close()
        with open(d, 'w', encoding='utf-8'as f:
            f.writelines(edited_lines)
            f.close()
except Exception as e:
    print('processing_Data : ', e)
cs
반응형

1. 취급하려는 테이블 이외의 테이블 삭제(21 ~ 22 line)

네모박스 표시한 부분도 read_html로 불러와지는 쓸데없는 데이터이기 때문에 txt 파일 내에서 삭제한다.

텍스트 파일을 라인 하나하나 나누어서 가져온 다음 필요없는 테이블의 라인 번호를 range 내에 돌려서 해당 라인을 공백으로 치환한다.

2. 취급하려는 테이블 헤드 부분의 태그를 <th>로 변경(14 ~ 18 line)

테이블 헤더 부분도 열 데이터처럼 <td> 태그로 감싸여있다.

txt 파일을 한 줄씩 읽기 때문에 그 줄에 '순번'이라는 텍스트가 있으면 선택해서 replace로 'td'를 'th' 로 바꾼다.

 

수정한 내용을 'edited_lines' 리스트에 추가해서 기존 텍스트 파일에 덮어쓴다. (26 ~ 28 line)

 

 

데이터프레임 추출


ex = pd.read_html('test_file.txt', encoding='utf-8')[0]
ex

read_html 로 텍스트 파일 가져오면 리스트로 가져오기 때문에 [0] 인덱싱을 붙여서 테이블이 있는 요소 지정했다.

텍스트 파일에서 가공 후 read_html로 뽑으니 깔끔하게 데이터프레임 형식으로 뽑혔다.

 


 

방법론적으론 별 거 없었지만 파이썬에서 html로 쓰여진 손상된 엑셀 파일을 열여야 할 때 / '.xls' 엑셀 파일이 안 열릴 때면 

txt 파일로 변환 --> txt 파일을 보고 싶은대로 수정 --> read_html 로 읽어오기

이 방법으로 시도해보면 좋을 것 같다.

 

* 전체보기 *

try:
	# 같은 경로에 txt 파일로 복사
	excel_name_pc = 'test_file.xls'
	text_name_pc = 'test_file.txt'

	shutil.copy(excel_name_pc, text_name_pc)
    
    
    # 데이터 파일 .xls -> .txt -> 테이블 수정 -> .txt를 read_html로 오픈
    edited_lines = []
    text_file_path_pc = path + '/' + text_name_pc
    text_file_path_mo = path + '/' + text_name_mo
    # print(text_file_path)
    # 텍스트 파일 열어서 테이블 잘 나오도록 수정
    for d in [text_file_path_pc, text_file_path_mo]:
        with open(d, 'r', encoding='utf-8') as f:
            lines = f.readlines()
            edited_lines = []
            for i, j in enumerate(lines, 1): 
                if j.find('순번') != -1: # 헤드 부분 찾기
                    j = j.split('</tr>')
                    j[0] += '</tr>\n'
                    j[0] = j[0].replace('td', 'th').replace('/td', '/th') # 2.헤드 부분의 태그를 <th>로 변경
                    edited_lines.append(j[0])
                    edited_lines.append(j[1] + '\n')
                # 1. 필요없는 테이블 삭제
                elif i in range(225, 271):
                    j = ''
                else:
                    edited_lines.append(j)
            f.close()
        with open(d, 'w', encoding='utf-8') as f:
            f.writelines(edited_lines)
            f.close()
            
    # 데이터프레임 추출
	ex = pd.read_html('test_file.txt', encoding='utf-8')[0]
	ex
except Exception as e:
    print('processing_Data : ', e)
반응형