티스토리 뷰
" 이 포스트는 이런 분에게 추천합니다. "
- 파이썬으로 웹페이지 파싱을 하고 싶으신 분
- 파이썬으로 생성된 데이터를 엑셀 파일에 쓰고 싶으신 분
- 회사에서 매일 나라장터에 어떤 용역이 올라왔는지 확인해서 엑셀에 한땀한땀 데이터 작성해서 상사분께 메일보내시는 분
- 이 파일이 악성 파일인지 궁금해서 현존하는 모든 백신에 돌린 결과를 통해 내 PC의 안정성을 보장받고 싶으신 분
- 고객사에 해킹하러 들어갔더니 당신이 사용하는 해킹도구의 virustotal에서 검증한 자료를달라는 고객을 만나는 경우
0. 개발동기
1. 개발 환경
2. 만들고자 하는 프로그램
사진이 작아서 잘 보일지는 모르겠지만 프로그램을 돌리게 되면 위와 같은 엑셀 파일이 생성이 된다.
이 프로그램은 다음과 같은 순서로 동작한다.
1) 자신이 원하는 카테고리를 텍스트 파일에 쓴다. ex) 정보/정보보호/해킹
2) 나라장터에서 용역을 확인할 수 있는 URL 페이지를 파싱한다.
3) 받아온 데이터를 항목별로 잘라서 엑셀 파일을 만들에 데이터를 집어넣는다.
어떻게 보면 간단하나 개발하다보니 넘어야할 산이 많다.
3 이 프로그램을 통해 파이썬 코딩의 어떤 부분을 향상시킬 수 있는가?
(사실 이 개발의 의미를 부여하기 위해 필자는 머리 부여잡았다.).
1. 웹 페이지 파싱
우선 파이썬을 이용해 웹 페이지 파싱해오는 법을 알 수 있다. 물론 여기서는 해킹에 사용하는 Request는 url 파라미터만 변경되는 소스이지만 이를 이용해 blind sql injection 공격을 할 수 있는 코드도 응용해볼수도 있는 노릇이다. 사실 이 코드는 Response의 응답받은 HTML 데이터를 받는것이 주목적이다.
2. 코딩의 기본기(?) & 파이썬 문자열 가지고 놀기.
코딩의 기본기라고 하면 단연 for문이다. (2중, 3중, 4중)
코딩의 기본기만 알면 이 프로그램 제작이 가능하다 (물론 필자는 코딩 고수 절대아님)
for 문이랑 print 문만 가지고 놀줄 알면 된다. 그리고 우리가 원하는 데이터를 정제하기 위해서 문자열 함수를 많이 사용한다.
3. 파이썬을 이용하여 엑셀 문서 만들기
사실 부분이 이 프로그램의 핵심일 수도 있다. 생각보다 파이썬을 이용하여 엑셀 문서를 쉽게 제작이 가능하다는것을 필자도 개발하면서 처음 알았다 특히 양식 부분도 설정이 가능하다. 아직 엑샐 내 함수까지는 손대보지는 않았는데 이것도 가능할 것 같다!
4. 사전 준비
(1) xlwt 모듈 설치
목적 : excel 파일 만들때
다운로드 : https://pypi.python.org/pypi/xlwt
설치 방법 : python setup.py install
(2) beautifulsoup 설치
목적 : html 데이터 파싱
* 리눅스 설치 : apt-get install python-bs4
* 윈도우 설치 : pip install beautifulsoup4 (pip 이용)
(3) py2exe
목적 : py 파일 exe 파일 만들기
다운로드 : https://pypi.python.org/pypi/py2exe/
설치 방법 : exe 설치파일, zip 파일 둘다 제공
(4) 기존 사용 모듈 - urllib2, datetime, time, os
해당 모듈을은 프로그램 개발시 위에 import 시켜줘야 되는 모듈이다.
5. 본격적인 개발
1 2 3 4 5 6 | import os f = open("category.txt") line = f.readline() category_list = line.split('/') f.close | cs |
1 2 3 | #category.txt 정보보호/보호/보안/무선보안 | cs |
1 2 3 4 5 6 7 8 9 10 11 | #### Field Description #### #taskClCds = 업무구분 #bidNm = 공고명 #fromBidDt : 공고일 ~부터 2015%2F09%2F01 #toBidDt : 공고일 ~까지 #fromOpenBidDt=&toOpenBidDt= 개찰일 ~에서 ~까지 #instNm : 공공기관 #radOrgan : 1(공고기관) 2(수요기관) #area : 지역 #bidno : 공고번호 ##################################### | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import datetime, time from time import localtime, strftime from datetime import timedelta #기간 산정하기 d = datetime.date.today() #하루 기준으로 뽑기 td = timedelta(days=1) # 3일치 뽑을거면 days 수정해주면 됨. fromtd = d -td; fromBidDt="20" + str(fromtd.strftime("%y/%m/%d")) toBidDt = "20" + str(d.strftime("%y/%m/%d")) #저장할 파일명 설명 doc_name = str(strftime("%y-%m-%d_%H%M%S", localtime())) + "_나라장터.xls" | cs |
1 2 3 4 5 6 7 8 9 10 11 | import urllib2 for category in category_list: bidNm = category print "[" + bidNm + "]검색중..." bidNm = urllib2.quote(category) instNm = "" radOrgan = 1 fromOpenBidDt = ""; toOpenBidDt = ""; bidno=""; urlString = "http://www.g2b.go.kr:8101/ep/tbid/tbidList.do?taskClCds=&bidNm=" + bidNm + "&searchDtType=1&fromBidDt=" + fromBidDt + "&toBidDt=" + toBidDt + "&fromOpenBidDt=" + fromOpenBidDt + "&toOpenBidDt=" + toOpenBidDt + "&radOrgan=" + str(radOrgan) + "&instNm="+instNm + "®Yn=Y&bidSearchType=1&searchType=1" body = urllib2.urlopen(urlString) | cs |
이제 데이터는 불러온 상태이고 엑셀 문서의 토태를 만들어 보자.
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | import xlwt #excel 설정 workbook = xlwt.Workbook(encoding='utf-8') workbook.default_style.font.heignt = 20*11 #font설정 11pt #사용자 정의 색깔 설정 xlwt.add_palette_colour("lightgray", 0x21) workbook.set_colour_RGB(0x21, 216, 216, 216) xlwt.add_palette_colour("lightgreen", 0x22) workbook.set_colour_RGB(0x22, 216,228,188) #시트 생성 및 cell 가로 길이 설정 worksheet = workbook.add_sheet(u'시트0') col_width_0 = 256*13 col_width_1 = 256*13 col_width_2 = 256*21 col_width_3 = 256*13 col_width_4 = 256*13 col_width_5 = 256*15 col_width_6 = 256*16 col_width_7 = 256*14 col_width_8 = 256*13 col_width_9 = 256*13 col_width_10 = 256*23 col_height_content = 48 worksheet.col(0).width = col_width_0 worksheet.col(1).width = col_width_1 worksheet.col(2).width = col_width_2 worksheet.col(3).width = col_width_3 worksheet.col(4).width = col_width_4 worksheet.col(5).width = col_width_5 worksheet.col(6).width = col_width_6 worksheet.col(7).width = col_width_7 worksheet.col(8).width = col_width_8 worksheet.col(9).width = col_width_9 worksheet.col(10).width = col_width_10 #폰트 스타일 생성 #font_set = "font: name "+u"맑은 고딕" +", height 280;"; #font_style = xlwt.easyxf(font_set) #worksheet.row(0).set_style(font_style) #줄에 폰트 스타일 설정 # 항목 스타일 설정 list_style = "font:height 180,bold on; pattern: pattern solid, fore_color lightgray; align: wrap on, vert centre, horiz center" #content_style_normal = "font:height 180; align:wrap on, vert centre" #content_style_center = "font:height 180; align:wrap on, vert centre, horiz center" # 엑셀에 항목 입력 worksheet.write(0,0,u"Date", xlwt.easyxf(list_style)) worksheet.write(0,1,u"Category", xlwt.easyxf("font:height 180, bold on;pattern: pattern solid, fore_color lightgreen; align:vert centre, horiz center")) worksheet.write(0,2,u"공고명", xlwt.easyxf(list_style)) worksheet.write(0,3,u"발주기관", xlwt.easyxf(list_style)) worksheet.write(0,4,u"입찰방법", xlwt.easyxf(list_style)) worksheet.write(0,5,u"입찰서\n개시일시", xlwt.easyxf(list_style)) worksheet.write(0,6,u"입찰서\n마감일시", xlwt.easyxf(list_style)) worksheet.write(0,7,u"개찰일시", xlwt.easyxf(list_style)) worksheet.write(0,8,u"개찰장소", xlwt.easyxf(list_style)) worksheet.write(0,9,u"추정가격(VAT포함)", xlwt.easyxf(list_style)) worksheet.write(0,10,u"비고(URL)", xlwt.easyxf(list_style)) | cs |
필자는 꼭 사용하는 소스만 붙이지 않았다. 각 항목마다 주석처리를 달아놨기 때문에 구체적인 설명은 생략한다.
파이썬 xlwt와 관련된 포스트는 많으나 엑셀에 양식 설정과 관련 한국 포스트는 없으니 해당 소스를 잘 활용하길 바란다.
참고로 Save 코드를 작성하지 않았으니 이 소스만 가지고 돌릴 경우 엑셀 파일은 안만들어진다. 마무리는 아래에서!
(4) beautifulsoup를 통하여 데이터 잘라 엑셀에 집어넣기 (feat. 시작된 한글 인코딩과 유니코드와의 싸움)
여기서 부터 조금 어렵다. 필자의 필력이 딸릴수도 있으니 이해가 안되시면 덧글로 질문을 부탁한다.
자신이 원하는 데이터를 가져오기 위해서는 urllib에서 가져온 전체 파싱 데이터를 출력하여 어떤 태그 사이에 내가 원하는 데이터가 있는지부터 확인하는 작업이 필요하다.
우리가 가져올 데이터는 아래 그림에 있는 공고명을 가져와서 엑셀에 집어넣을 것이다.
그럼 해당 데이터의 소스도 한번 보자.
그림이 잘 안보일 수도 있는데 공고명이 "국제여객터미널 솰라솰라"라는 공고명을 가져오고 싶다. 그러면 먼저 소스 내에서 태그들이 어떤것을이 살펴보자.
먼저 테이블이기 때문에 <table> </table>이 있을것이고
줄단위로 데이터가 들어가있기 때문에 <table><tr></tr></table>
각 셀마다 데이터는 <table><tr><td>데이터</td></tr></table> 이런식으로 들어갈 것이다.
이를 BeautifulSoup(이하 BS) 활용하면 원하는 태그영역만 자를 수 있다.
(BeautifulSoup에 대해서 이해가 잘되지 않는다면 잘 설명되어 있는 다른 블로그의 포스트를 읽기를 권장한다)
이제 소스를 살펴 보자. (이 소스는 공고명을 파싱하는 전체 소스의 일부 소스다. 나머지는 직접 짜보시길)
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 | # -*- coding: cp949 -*- from bs4 import BeautifulSoup soup = BeautifulSoup(body,'html.parser') parse_a = soup.find_all('a') parse_tr = soup.find_all('tr') ##################################################################### #1 : 공고명 parsing for test in parse_tr: itemstring = test.encode('cp949') start = itemstring.find("<td class=\"tl\"><div><a") if start >0: nlast = itemstring.find("</a></div></td>", start) tmpstring = itemstring[start:nlast] nfirst = tmpstring.rfind("\">")+2 item = tmpstring[nfirst:] try: string = item.decode('cp949') worksheet.write(name_count,2, unicode(string)) except UnicodeDecodeError: ErorCheck =1 worksheet.write(name_count,2, u"오류", xlwt.easyxf("font: bold on;pattern: pattern solid, fore_color pink;")) name_count = name_count+1 |
먼저 (2)에서 url Response데이터가 body 변수에 저장중이다.
2번 줄 : BS를 이용하여 soup 객체 생성
6, 7번 줄 : find_all 함수를 통하여 <a>, <tr>태그 사이에 있는 데이터 파싱, 리스트 형태로 들어감.
11번줄 : 리스트에서 데이터 하나씩 가져오기
12번줄 : 데이터 cp949로 인코딩하기 (가져온 데이터를 자르기 위해서는 한글데이터 변환이 필요)
13번줄 ~ 18번줄 : 문자열 find 함수를 통해서원하는 데이터를 자를 위치를 찾은 후 데이터 자르기
20번줄 : 엑셀에 저장하기 위해서는 다시 cp949로 디코딩
21번줄 : 엑셀에 데이터 저장 ( 이때 unicode 함수를 이용하여 string을 유니코드화 시켜줘야함)
22~24번줄 : 데이터를 어떻게 자르냐에 따라서 한글 변환과정에서 오류가 나는 경우고 있음. 이때 예외처리를 통해 프로그램 사용자가 정상적으로 데이터를 못가져왔다는걸 표시하기 위해 작성된 코드
생각보다 파이썬은 개발하다 보면 한글 인코딩때문에 상당한 애를 먹는다.
한글 인코딩과 관련된 소스는 별도로 다룰 예정이다. 필자도 많이 검색해봤는데 상황에 따라 제대로 적용하는게 쉽지가 않다.
(5) 엑셀 파일 저장해주기.
이제 데이터 저장이 완료되면 엑셀 파일을 저장해 주자.
1 2 3 | import os workbook.save(os.path.join(os.path.abspath("."), doc_name)) | cs |
앞에서 실행한 시간을 나타내는 파일 이름(doc_name)을 프로그램이 실행된 경로에 생성되게끔 저장하였다.
(6) 최종 완성은 exe 파일로 만들기(feat. py2exe)
드디어 마무리 단계다. 모든 PC가 python이 설치되어 있지 않기 때문에 어디서나 실행 가능한 윈도우 실행 파일(exe)로 만드는것이 중요하다.
py2exe.py 파일 소스는 아래 소스를 참고하길 바란다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #-*-coding:utf-8 #setup.py from distutils.core import setup import py2exe, sys sys.argv.append("py2exe") setup(console=["nara_parser.py"], options={ "py2exe":{ "packages" : ["xlwt", "bs4", "urllib2", "hashlib"], "bundle_files":3, "optimize":2, } }, zipfile = None ) | cs |
11번 줄 : 사용했던 패키지를 넣어주면 된다.
python으로 해당 py 파일을 실행하면 최종적으로dist 폴더안에 exe 파일이 생성이 된다.(아래 그림 예시)
6. 응용
파이썬을 이용한 데이터 파싱과 엑셀 활용은 무궁 무진하니 잘 활용하시길
'필요에 의한 개발 > 파이썬활용백서' 카테고리의 다른 글
파이썬에서의 한글 인코딩과의 싸움 (4) | 2016.08.29 |
---|
- Total
- Today
- Yesterday