http://newspaper.readthedocs.io/en/latest/


각 언론사의 url을 GET하여 부동산뉴스를 보아보고 있습니다.

url만 바꿔서 아주 간단하게 뉴스기사를 가져오고

>>> from newspaper import Article >>> url = 'http://fox13now.com/2013/12/30/new-year-new-laws-obamacare-pot-guns-and-drones/' >>> article = Article(url)
>>> article.download()
>>> article.parse()

 자연어 처리 실행시키고

>>> article.nlp()

키워드를 뽑아주고 요약도 해줍니다.

>>> article.keywords
['New Years', 'resolution', ...]

>>> article.summary
'The study shows that 93% of people ...'

한글도 그럭저럭 해줍니다. (네이버 뉴스 요약해주는 서비스랑 비슷하거나 조금 떨어지는 수준)


12개 정도의 언론사의 오피니언, 부동산을
오늘의 주요 키워드 뽑아서 보는데 일부 키워드 예외처리만 하면 볼만합니다.






반응형

Herokuapp을 이용해서 시험삼아 제가 만든 시험 서비스 사이트가 있었습니다.

Django와 웹 스크랩핑을 기법을 이용해서 만들었는데

한동안 잊고 있다가 오랜만에 들어가서 로그인을 시도하니 에러가 발생합니다.

참고로 제가 만든 사이트의 로그인 방식은 로그인 하려는 사용자의 이메일 주소를 입력 받아서

1회용 로그인 URL 링크를 회신해서 보내줍니다.

이 과정에서 일단은 무료로 하려다보니 Gmail을 사용하고 있습니다.


SMTP Authentication Error

딱 봐도 메일 접근 권한 문제 같아 보입니다.

권한 해결하려고 보니 간단합니다.



아래 링크에가서 엑세스 허용만 해주면 문제 해결됩니다.
https://accounts.google.com/DisplayUnlockCaptcha


반응형

url 정보를 세팅하고 이에 대해서 request 요청하면 응답 정보를 주는데

http://openapi.molit.go.kr:8081/OpenAPI_ToolInstallPackage/service/rest/RTMSOBJSvc/getRTMSDataSvcAptTrade?LAWD_CD=11440&DEAL_YMD=201801&serviceKey=###SERVICE_KEY###



얼마전에 수정이 있었는지
응답되는 정보가 변경되었습니다.

    req = urllib.request.Request(request_url)
    try:
        res = urllib.request.urlopen(req)
    except UnicodeEncodeError:
        print('[OpenAPI] UnicodeEncodeError')
        return


    data = res.read().decode('utf-8')
    soup = BeautifulSoup(data, 'html.parser')
    if (soup.resultcode.string != '00'):
        print('[OpenAPI] ',  soup.resultmsg.string)
        return

    items = soup.findAll('item')
    print(items)


가져온 정보를 보니 주석과 <, > 정보들이 섞여 있었습니다.

<item>&lt;거래금액&gt;    83,000<!--거래금액-->&lt;
건축년도&gt;2005<!--건축년도-->&lt;년&gt;2018<!--년-->&lt;
법정동&gt; 상암동<!--법정동-->&lt;아파트&gt;상암월드컵파크6단지<!--아파트-->&lt;
월&gt;1<!--월-->&lt;일&gt;11~20<!--일-->&lt;전용면적&gt;104.32<!--전용면적-->&lt;
지번&gt;1689<!--지번-->&lt;지역코드&gt;11440<!--지역코드-->&lt;층&gt;6<!--층--></item>


기존 코드를 수정해서 text 정보만 가져왔습니다.

item = item.text

HTML 태그들이 없어졌습니다.

<거래금액>    83,000<건축년도>2005<년>2018<법정동> 상암동<아파트>상암월드컵파크6단지<월>1<일>11~20<전용면적>104.32<지번>1689<지역코드>11440<층>6


이걸 다시 파싱하려니 정규표현식을 사용해야 했습니다.
결과만 보면 간단합니다.

split_item = re.split('<.*?>', item)


이렇게 하고나니 List형으로 잘 분리합니다.

['', '    83,000', '2005', '2018', ' 상암동', '상암월드컵파크6단지',
'1', '11~20', '104.32', '1689', '11440', '6']


반응형

네이버에서 제공해주는 openapi를 이용해서 카페에 글쓰기를 할 수 있다.

관련예제는 여기링크를 클릭하면 볼 수는 있다.

글쓰는 순서

1. login api를 이용해서 접근 토큰 정보를 가져온다.

2. 포스팅한다.


아래의 내용을 따라하기전에 우선 Naver openapi를 사용하기 위한

사전 준비사항을 완료해야한다. --> 링크

특히 사용 API에 카페를 반드시 추가해야한다.


순서는 간단하지만 막상 따라해보려는데 첫줄에서 막힌다.

token = "YOUR_ACCESS_TOKEN"

어떻게 받아와야되나 ??

이를 확인하기 위해서 로그인 API 명세를 찾아본다.

 

아... 나는 파이썬으로 다 하려고 했는데 없다.

하지만 뒤져보면 다 나온다.

Selenium을 이용하면 받아올 수 있다.

이와 관련된 기본적인 세팅은 이준범님의 블로그에 가면 잘 나와있으니 따라하면됨
(https://beomi.github.io/2017/02/27/HowToMakeWebCrawler-With-Selenium/)


이 정보들을 바탕으로 로그인을 한다.

아래의 코드에서 로그인 관련, OAUTH관련 중요 정보는 설정에서 가져오거나 직접 입력하거나 알아서 한다.


# Token 정보 가져오는 코드

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import json
import os
import re
import urllib.request

from bs4 import BeautifulSoup
from requests import get
from selenium import webdriver
from urllib.error import HTTPError
from urllib.parse import urlencode


def get_naver_token(): chromedriver_path = os.environ.get('CHROMEDRIVER_PATH') naver_id = os.environ.get('NAVER_ID') naver_pw = os.environ.get('NAVER_PW') naver_cid = os.environ.get('NAVER_CLIENT_ID') naver_csec = os.environ.get('NAVER_CLIENT_SECRET') naver_redirect = os.environ.get('NAVER_BLOG_REDIRECT') driver = webdriver.Chrome(chromedriver_path) # driver = webdriver.PhantomJS() driver.implicitly_wait(3) driver.get('https://nid.naver.com/nidlogin.login') driver.find_element_by_name('id').send_keys(naver_id) driver.find_element_by_name('pw').send_keys(naver_pw) driver.find_element_by_xpath('//*[@id="frmNIDLogin"]/fieldset/input').click() state = "REWERWERTATE" req_url = 'https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=%s&redirect_uri=%s&state=%s' % (naver_cid, naver_redirect, state) driver.get(req_url) ########################## # XXX: 최초 1회만 반드시 필요하고 이후엔 불필요함 driver.find_element_by_xpath('//*[@id="confirm_terms"]/a[2]').click() ########################## redirect_url = driver.current_url temp = re.split('code=', redirect_url) code = re.split('&state=', temp[1])[0] driver.quit()

print(redirect_url)

url = 'https://nid.naver.com/oauth2.0/token?'
data = 'grant_type=authorization_code' + '&client_id=' + naver_cid + '&client_secret=' + naver_csec + '&redirect_uri=' + naver_redirect + '&code=' + code + '&state=' + state

request = urllib.request.Request(url, data=data.encode("utf-8"))
request.add_header('X-Naver-Client-Id', naver_cid)
request.add_header('X-Naver-Client-Secret', naver_redirect)
response = urllib.request.urlopen(request)
rescode = response.getcode()
token = ''
if rescode == 200:
response_body = response.read()
js = json.loads(response_body.decode('utf 8'))
token = js['access_token']
else:
print("Error Code:", rescode)
return None

if len(token) == 0:
return None
print(token)
return token

Access token 정보를 가져왔다.

잠시 숨을 고르고 아래에 이어서 카페 글쓰기를 시도하면 된다. (스크롤을 내려야함)




위의 코드를 이용해서 토큰을 가져왔다면 그 다음에는 카페 글쓰기 api를 사용하면 된다.

반가운 Python 예제 코드다.


그런데 또 막힌다.

    clubid = 'xxxxxx'    
    menuid = 'x'


이건 직접 찾아봐야한다.

Chrome의 검사 기능을 이용해서 찾을 수 있다. (다른 웹브라우저에서도 알아서 찾아볼 수 있음)

아래 같이 카페에 로그인해서 게시판에 들어가고

마우스 우클릭해서 '검사' 기능을 사용하면

오른쪽에 정보를 찾을 수 있다.


샘플코드대로 했는데,,,

한글이 다 깨진다.

그러면 urlencode를 사용한 아래의 코드로 수행하면된다.


def naver_cafe_post(subject, content):
    token = get_naver_token()
    header = "Bearer " + token  # Bearer 다음에 공백 추가
    clubid = 'xxxxxx'    
    menuid = 'x'
    url = "https://openapi.naver.com/v1/cafe/" + clubid + "/menu/" + menuid + "/articles"

    subject = urllib.parse.quote(subject)
    content = urllib.parse.quote(content)
    data = urlencode({'subject': subject, 'content': content}).encode()
    request = urllib.request.Request(url, data=data)
    request.add_header("Authorization", header)
    try:
        response = urllib.request.urlopen(request)
    except HTTPError as e:
        print("url open failed", e, subject, content)
        return
    rescode = response.getcode()
    if rescode == 200:
        response_body = response.read()
        print(response_body.decode('utf-8'))
    else:
        print("Error Code:" + rescode)


그냥 텍스트를 가지고 하면 잘 되는데

기존에 사용했던 방식으로 HTML 태그를 붙이니까 에러가 난다.

대충 형태는 아래와 같은 모양이었다.

<font color="red"> xxxx </font>

이럴 때는 쌍따옴표를 제거하면 된다.

 <font color=red> xxxx </font>


그런데 또 안된다????????

열이 받아서 때려치울라고 하던 찰나 '%' 문자가 눈에 띈다.

content로 사용할 문자열에 그냥 '%'가 있으면 에러가 나서 아래 처럼 역슬래쉬를 추가해줘야 한다.

content = content.replace('%', '\%')


꺠지지도 않고 잘 포스팅 된다.

편리하다.



반응형


예제를 따라하면 제 경우에는 한글이 깨집니다.



data = "subject=" + subject + "&content=" + content
request = urllib.request.Request(url, data=data.en

엄청 삽질하다가 결국 찾았습니다.

위에처럼 하면 안되고

아래처럼 해주면 잘 됩니다.


from urllib.parse import urlencode
 
    data = urlencode({'subject': subject, 'content': content}).encode()
    request = urllib.request.Request(url, data=data)

아래는 naver developers에서 제공하는 샘플코드입니다.


# 네이버 카페 Open API 예제 - 글쓰기
import os
import sys
import urllib.request
token = "YOUR_ACCESS_TOKEN"
header = "Bearer " + token # Bearer 다음에 공백 추가
clubid = "CLUB_ID" # 카페의 고유 ID값
menuid = "MENU_ID" # (상품게시판은 입력 불가)
url = "https://openapi.naver.com/v1/cafe/" + clubid + "/menu/" + menuid + "/articles"
subject = urllib.parse.quote("[subject] 네이버 Cafe api Test Python")
content = urllib.parse.quote("[content] 네이버 Cafe api Test Python")
data = "subject=" + subject + "&content=" + content
request = urllib.request.Request(url, data=data.encode("utf-8"))
request.add_header("Authorization", header)
response = urllib.request.urlopen(request)
rescode = response.getcode()
if(rescode==200):
    response_body = response.read()
    print(response_body.decode('utf-8'))
else:
    print("Error Code:" + rescode)

반응형

조도센서로 값을 잘 받아온다.


https://github.com/pimylifeup/Light_Sensor에서 받아온 코드를 기반으로

내가 필요한 기능들을 추가한다.

참고로 redis에 대한 설정은 구글링하면 금방 찾아볼 수 있다.

서버는 내가 사용하는 노트북이다.


우선 redis key로 사용할 ID가 필요해서 라즈베리파이 cpu의 시리얼 정보를 사용했고,

매일 누적하다보니 년, 월에 대한 정보까지 포함시켰다.

그리고 redis-collections의 List를 이용해서 

redis에 저장되는 정보를 마치 List처럼 사용하였다.

써보니 엄청 편하다.


라즈베리파이에서 구동할 파이썬 코드의 설명이다.

1초 sleep을 주고 계속 루프를 돌면서 체크한다.
동작방식은 0.1초간 라즈베리파이에 전원이 인가되고

이 전원이 LDR(조도센서)를 지나가는데

이때의 조도센서는 어두울수록 저항값이 커지기때문에

GPIO.HIGH가 되기까지 더 오래걸려서 측정 값이 커진다.


라즈베리파이3에서 python2로 구동되는 코드


#!/usr/local/bin/python
from __future__ import print_function
from redislite import StrictRedis
from redis_collections import List

import RPi.GPIO as GPIO
import os
import time
from datetime import datetime

__author__ = 'Byungwoo Jeon'
__license__ = "GPL"
__maintainer__ = "byngwoo"

GPIO.setmode(GPIO.BOARD)

# define the pin that goes to the circuit
pin_to_circuit = 7


def get_rp_serial():
    try:
        f = open('/proc/cpuinfo', 'r')
        for line in f:
            if line[0:6] == 'Serial':
                cpu_serial = line[10:26]
        f.close()
    except:
        cpu_serial = None

    return cpu_serial

def rc_time(pin_to_circuit):
    count = 0

    # Output on the pin for
    GPIO.setup(pin_to_circuit, GPIO.OUT)
    GPIO.output(pin_to_circuit, GPIO.LOW)
    time.sleep(0.1)  # sec

    # Change the pin back to input
    GPIO.setup(pin_to_circuit, GPIO.IN)

    # Light-dependent resistor
    # When light hits the LDR, its resistance is very low,
    # but when it's in the dark its resistance is very high.
    # -> Count until the pin goes high
    while (GPIO.input(pin_to_circuit) == GPIO.LOW):
        count += 1
    return count


def redis_init():
    serial_number = get_rp_serial()  # get cpu serial number
    if serial_number is None:
        serial_number = '00000001'  # temp number

    ip = os.environ.get('RS_HOST')  # RS: raspberry pi
    port = os.environ.get('RS_PORT')
    pw = os.environ.get('RS_PASSWORD')
    now = datetime.now()
    time_str = '%4d%02d%02d' % (now.year, now.month, now.day)

    redis_connection = StrictRedis(host=ip, port=port, db=0, password=pw)
    r = List(redis=redis_connection, key='rp3:'+serial_number+time_str)
    return r


# Catch when script is interupted, cleanup correctly
try:
    r = redis_init()
    # Main loop
    while True:
        current_light = rc_time(pin_to_circuit)
        try:
            r.append(current_light)
            print(current_light)
        except Exception as e:
            print("error: ", e)
            pass
        time.sleep(1)  # sec
except KeyboardInterrupt:
    pass
finally:
    GPIO.cleanup()



이 자체만으로 제대로 측정하려면 라즈베리파이에서 딱 이 스크립트만 돌려야한다.

만약 라즈베리파이에서 웹브라우저 실행과 같이 라즈베리파이의 자원을 많이 필요로 하는 작업을 하면

위의 측정 값은 신뢰할 수 없게 된다.



서버에서 수집한 정보를 조회하는 코드

라즈베리파이가 DB에 List형태로 저장하므로 이를 받아와서 

그래프로 보여주기에 매우 수월하다.


서버는 python3를 사용


#!/usr/local/bin/python3
from redis import StrictRedis
from redis_collections import List

import matplotlib.pyplot as plt
import os


def redis_init():
    ip = os.environ.get('RS_HOST')  # RS: raspberry pi
    port = os.environ.get('RS_PORT')
    pw = os.environ.get('RS_PASSWORD')

    redis_connection = StrictRedis(host=ip, port=port, db=0, password=pw)
    # TODO: support multi keys
    r = List(redis=redis_connection, key='rp3:00000000448f542820170421')
    return r


def main():
    r = redis_init()

    plt.xlabel('Run time(sec)')
    plt.ylabel('LDR resister')
    plt.plot(r)
    plt.show()


if __name__ == '__main__':
    main()


수행한 결과 화면




아직 제대로 조건을 못 찾았지만

아래처럼 조건을 정해서 그래프에 표시할 수도 있다.




def main():
    r = redis_init()
    plt.xlabel('Run time(sec)')
    plt.ylabel('LDR resister')
    for i in range(1, len(r)):
        if r[i-1] - r[i] > 1000 and r[i] < 1000:
            plt.annotate('turn on', xy=(i, 600), xytext=(i, 1200),
                         arrowprops=dict(facecolor='black', shrink=0.05),)
    plt.plot(r)
    plt.show()


아래처럼 형광등이 켜졌다고 판단하는 시점을

아래처럼 알아서 표시해줄수도 있는데

아직 저 값에 대해서는 시험이 좀 더 필요하다.




이것에 대해 최종적으로는

Django를 이용해서 웹에서 보여준다. (개인적으로 Django 공부중)

물론 flask, bottle같이 다른 프레임웍을 사용해도 상관은 없다.


웹쪽은 아는게 너무 없어서 적당히 기본만 구현해뒀는데 

아직 바꿔야 할 곳이 너무 많아서 소스는 못 올리겠다.


이렇게까지 구현하는데 파이썬 라이브러리에서 다 해줘서 내가 한 건 별로 없다.

물론 회의실이 여러개가 되고, 모듈의 개수를 늘리고, 

앞으로 해야할 것과 고려할 것은 훨씬 많이 남아있다.



..








반응형


redis-cli

 -h : host ip address

 -p : port number

 -a : password


redis-cli -h 127.0.0.1 -p 6379 -a mysupersecretpassword


참고로 비밀번호에 $가 있으면 에러가 발생하므로 사용하지 않는다.

반응형

#######################################################

# 원본: http://highthroughput.org/wp/    (Hyeshik Chang 장혜식님) 

# 원본참고: http://pinkwink.kr/1005

#######################################################


2곳의 원본을 참고하여 대한민국 지도에

인구 분포도를 그려주는 코드를 한줄한줄 따라가면서 

numpy, pandas, matplotlib에 대한 사용법을 익혀보았다.

필요한 csv 파일과 소스코드는 핑크윙크에 가면 있다.


각 라인별로 주석을 달아두었다.

drawKorea 함수만 이해해도 왠만한건 할 수 있을것 같다.



#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd


BORDER_LINES = [
    [(3, 2), (5, 2), (5, 3), (9, 3), (9, 1)],  # 인천
    [(2, 5), (3, 5), (3, 4), (8, 4), (8, 7), (7, 7), (7, 9), (4, 9), (4, 7), (1, 7)],  # 서울
    [(1, 6), (1, 9), (3, 9), (3, 10), (8, 10), (8, 9),
     (9, 9), (9, 8), (10, 8), (10, 5), (9, 5), (9, 3)],  # 경기도
    [(9, 12), (9, 10), (8, 10)],  # 강원도
    [(10, 5), (11, 5), (11, 4), (12, 4), (12, 5), (13, 5),
     (13, 4), (14, 4), (14, 2)],  # 충청남도
    [(11, 5), (12, 5), (12, 6), (15, 6), (15, 7), (13, 7),
     (13, 8), (11, 8), (11, 9), (10, 9), (10, 8)],  # 충청북도
    [(14, 4), (15, 4), (15, 6)],  # 대전시
    [(14, 7), (14, 9), (13, 9), (13, 11), (13, 13)],  # 경상북도
    [(14, 8), (16, 8), (16, 10), (15, 10),
     (15, 11), (14, 11), (14, 12), (13, 12)],  # 대구시
    [(15, 11), (16, 11), (16, 13)],  # 울산시
    [(17, 1), (17, 3), (18, 3), (18, 6), (15, 6)],  # 전라북도
    [(19, 2), (19, 4), (21, 4), (21, 3), (22, 3), (22, 2), (19, 2)],  # 광주시
    [(18, 5), (20, 5), (20, 6)],  # 전라남도
    [(16, 9), (18, 9), (18, 8), (19, 8), (19, 9), (20, 9), (20, 10)],  # 부산시
]
"""
# ziped BORDER_LINES 확인
>>>    for path in BORDER_LINES:
>>>        ys, xs = zip(*path)

(3, 5, 5, 9, 9) (2, 2, 3, 3, 1)
(2, 3, 3, 8, 8, 7, 7, 4, 4, 1) (5, 5, 4, 4, 7, 7, 9, 9, 7, 7)
(1, 1, 3, 3, 8, 8, 9, 9, 10, 10, 9, 9) (6, 9, 9, 10, 10, 9, 9, 8, 8, 5, 5, 3)
(9, 9, 8) (12, 10, 10)
(10, 11, 11, 12, 12, 13, 13, 14, 14) (5, 5, 4, 4, 5, 5, 4, 4, 2)
(11, 12, 12, 15, 15, 13, 13, 11, 11, 10, 10) (5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 8)
(14, 15, 15) (4, 4, 6)
(14, 14, 13, 13, 13) (7, 9, 9, 11, 13)
(14, 16, 16, 15, 15, 14, 14, 13) (8, 8, 10, 10, 11, 11, 12, 12)
(15, 16, 16) (11, 11, 13)
(17, 17, 18, 18, 15) (1, 3, 3, 6, 6)
(19, 19, 21, 21, 22, 22, 19) (2, 4, 4, 3, 3, 2, 2)
(18, 20, 20) (5, 5, 6)
(16, 18, 18, 19, 19, 20, 20) (9, 9, 8, 8, 9, 9, 10)

# 읽어들였던 data_draw_korea.csv 엑셀 파일의 일부
,인구수,shortName,x,y,면적,광역시도,행정구역
0,202520,강릉,11,4,1040.07,강원도,강릉시
1,25589,고성(강원),9,0,664.19,강원도,고성군
2,86747,동해,11,5,180.01,강원도,동해시
3,63986,삼척,11,8,1185.8,강원도,삼척시
4,76733,속초,9,1,105.25,강원도,속초시

... 후략...

"""


def drawKorea(target_data, blocked_map, d1, d2, cmapname):

    vmin = min(blocked_map[target_data])  # target_data의 최소값 (인구수가 가장 적은 값)
    vmax = max(blocked_map[target_data])  # target_data의 최대값 (인구수가 가장 많은 값)
    white_label_min = (vmax - vmin) * 0.25 + vmin

    # .csv에서 받아온 정보에서 사용하기 좋게 pivot
    map_data = blocked_map.pivot(index='y', columns='x', values=target_data)

    # np.isnan(map_data)는 Nan이면 True, 나머지는 False 리턴해주고
    # 이것을 바탕으로 마스킹 배열 생성
    masked_mapdata = np.ma.masked_where(condition=np.isnan(map_data), a=map_data, copy=True)  # numpy masked array

    plt.figure(figsize=(8, 13))  # width, height tuple in inches

    # create a pseudocolor plot of a 2-D array.
    # plt.pcolor 대신에 pcolormesh 사용함.
    plt.pcolormesh(masked_mapdata, vmin=vmin, vmax=vmax, cmap=cmapname, edgecolor='#aaaaaa', linewidth=0.5)

    for idx, row in blocked_map.iterrows():  # rows에 대한 반복 처리
        # 인구수: row[target_data]
        annocolor = 'white' if row[target_data] > white_label_min else 'black'

        # 광역시도: row[d1]
        # 행정구역: row[d2]

        # 광역시는 구 이름이 겹치는 경우가 많아서 시단위 이름도 같이 표시한다. (중구, 서구)
        # XX시로 끝나지만 세종시가 아닌 것들만 예외처리
        if row[d1].endswith('시') and not row[d1].startswith('세종'):
            # row[d1] : 서울특별시, 부산광역시...  row[d1][:2] : 서울, 부산...
            # row[d2] : 서대문구, 서초구, 중구 ... row[d2][:-1] : 서대문, 서초, 중 ...
            dispname = '{}\n{}'.format(row[d1][:2], row[d2][:-1])
            if len(row[d2]) <= 2:
                # 중, 서, ... -> 중구, 서구, ...
                dispname += row[d2][-1]
        else:
            # 제주특별자치도, 전라남도, 경상북도, ...
            dispname = row[d2][:-1]

        # 서대문구, 서귀포시 같이 이름이 3자 이상인 경우에 작은 글자로 표시한다.
        if len(dispname.splitlines()[-1]) >= 3:
            fontsize, linespacing = 9.5, 1.5
        else:
            fontsize, linespacing = 11, 1.2

        # dispname '서울/n강남'에 대한 annotating
        plt.annotate(s=dispname,
                     xy=(row['x'] + 0.5, row['y'] + 0.5),
                     fontweight='bold', fontsize=fontsize,
                     horizontalalignment='center',
                     verticalalignment='center',
                     color=annocolor,
                     linespacing=linespacing)

    for path in BORDER_LINES:
        ys, xs = zip(*path)
        # plot xs, ys
        plt.plot(xs, ys, color='black', linewidth=4)

    plt.gca().invert_yaxis()  # x, y 뒤집어야 함
    plt.gca().set_aspect(aspect='equal')

    plt.axis('off')

    # 우측에 컬러바를 통해서 색상에 따라 수치를 파악할 수 있음
    # shirink: 컬러바의 전반적인 크기 조절
    # aspect: 컬러바의 폭 조절
    cb = plt.colorbar(shrink=0.1, aspect=10)
    cb.set_label(label=target_data)

    plt.tight_layout()
    plt.show()

def main():
    plt.rcParams["font.family"] = "AppleGothic"  # font setting

    # http://en.wikipedia.org/wiki/Plus_and_minus_signs#Character_codes
    plt.rcParams['axes.unicode_minus'] = False  # use hypen '-' (True: use unicode minus)

    data_draw_korea = pd.read_csv('./data_draw_korea.csv', index_col=0, encoding='UTF-8')
    data_draw_korea.head()  # return first row

    drawKorea('인구수', data_draw_korea, '광역시도', '행정구역', 'Blues')


if __name__ == '__main__':
    main()

...












...

반응형

+ Recent posts