2018년 8월 26일 일요일

Python에서 웹사이트 다루기


★ 크롬드라이버 설치가 필요
  • selenium이 크롬을 직접 실행하여 사용하므로 드라이버가 필요
  • https://chromedriver.storage.googleapis.com/index.html?path=2.32/에서 받을 것 (최신 버전에서 일부 웹사이트를 정상적으로 제어 안됨)
  • chromedriver.exe 또는 crhomedriver를 코드와 동일한 폴더에 넣어 사용


from selenium import webdriver

driver = webdriver.Chrome('./chromedriver')     :     크롬드라이버가 실행됨

driver.get('https://news.naver.com')                :      해당 페이지로 이동

웹브라우져의 F12 분석툴을 이용하여,
가장 사용가능한 최소의 unique한 id > name > class 속성 (unique 여부 확인 필요) 사용하고 unique한 것이 없으면 상위의 id, name 등을 이용하여 가져온 element내에서 다시 좁혀 들어감.

elements = driver.find_element_by_id('right.ranking_contents')
childs = elements.find_elements_by_tag_name('li')

driver.quit()                                             : python 종료전 종료를 시켜주어야 함.



import os
from selenium import webdriver
driver = webdriver.Chrome('./chromedriver')
try:
    driver.get('https://news.naver.com')
    elements = driver.find_element_by_id('right.ranking_contents')
    childs = elements.find_elements_by_tag_name('li')
    for c in childs:
        print(c.text)
except Exception as e:
    print(e)
finally:
    driver.quit()


입력하기


elem = driver.find_element_by_id('query')
elem.send_keys(keyword)
elem.sendkeys(Keys.RETURN)



from selenium import webdriver
driver = webdriver.Chrome('./chromedriver')
try:
    driver.get('http://www.naver.com')
    k = input('Enter keywords : ')
    e = driver.find_element_by_id('query')
    e.send_keys(k)
    e.send_keys(Keys.RETURN)
except Exception as er:
    print('Error occurs !!! : %s' % er)
finally:
    input('enter to quit')
    driver.quit()


이전에 잘 실행되던 코드가
webdriverexception message unknown error call function result missing 'value' 이란 에러가 뜬다.

구글 검색을 시도 했더니 크롬 브라우저가 업데이트 되어 생긴 이슈라고 한다.

해결방법은 2가지로
1. 크롬 브라우저를 (downgrade)낮춘다.
2. Chromedriver를 최신버전으로 변경한다.
|작성자 hamusj

출처 : https://blog.naver.com/hamusj/221230439095




※ find_elements_by_xpath()도 기억해 둘 것 !
   div.find_elements_by_xpath('./ul/li') 와 같이 현재 elemement에서의 상대적 위치를 지정, 정확하게 필요한 요소에만 접근 가능함.

※ 최종 element에서 text는 항상 있지만 title은 없을 수 있음

※ 최종 element에서 attribute는 get_attribute(attr_name) 으로 얻어 올 수 있다.


from selenium import webdriver
driver = webdriver.Chrome('./chromedriver')
try:
    driver.get('http://www.naver.com')
    k = input('Enter keywords : ')
    e = driver.find_element_by_id('query')
    e.send_keys(k)
    e.send_keys(Keys.RETURN)
    # other : _kinBase, _sp_kindic, sp_website
    div = driver.find_element_by_class_name('_blogBase')
    blogs = div.find_elements_by_xpath('./ul/li')
    for blog in blogs:
        title_tag = blog.find_element_by_class_name('sh_blog_title')
        text = title_tag.text
        href = title_tag.get_attribute('href')
        date = blog.find_element_by_class_name('txt_inline')
        print('TITLE : %s' % text)
        print('DATE  : %s' % date.text)
        print('        %s' % href)
except Exception as er:
    print('Error occurs !!! : %s' % er)
finally:

    driver.quit()


Python에서 email 다루기


email과 smtplib를 이용



from email.mime.multipart import MIMEMultipart
from smtplib import SMTP_SSL

SMTP_SERVER = "smtp.naver.com"
SMTP_PORT = "465"
SMTP_USER = ""
SMTP_PASSWORD = ""

def send_mail(name, addr, subject, contents, attachment=False):
    msg = MIMEMultipart("alternative")
    text = MIMEText(contents)
    msg.attach(text)
    if attachment:
        from email.mime.base import MIMEBase
        from email import encoders
        msg = MIMEMultipart('mixed')
        try:
            file_data = MIMEBase('application', 'octet-steam')
            with oepn(attachment, 'rb') as f:
                file_contents = f.read()
                file_data.set_payload(file_contents)
                encoders.encode_base64(file_data)
                from os.path import basename
                filename = basename(attachment)
                fild_data.add_header('Content-Disposition', 'attachment', filename=filename)
                msg.attach(file_data)
        except e:
            print("Somthing wrong while attach a file")
    smtp = SMTP_SSL(SMTP_SERVER, SMTP_PORT)
    smtp.login(SMTP_USER, SMTP_PASSWORD)
    msg['From'] = name
    msg['To'] = addr
    msg['Subject'] = subject
    smtp.sendmail('chinst@naver.com', addr, msg.as_string())
    smtp.close()

def main():
    global SMTP_USER, SMTP_PASSWORD
    SMTP_USER = str(input('Enter User ID : '))
    SMTP_PASSWORD = str(input('Enter Password : '))
    send_mail('TEST MAIL', 'chinst@naver.com', 'TEST mail from Python', 'This is a test mail.\nIs this OK?')



if __name__ == '__main__':
    main()

180826.다시 무릎 부상


더위도 주춤하고
밤에는 선선하기도 해서 오랜만에 재활 라이딩을 나갔는데...
간만에 그것도 밤에 나가는거라 후미등 전지도 교체해주고...
나름 기본적인 준비는 잘 해서 나갔다고 생각했다.


분당서울대병원까지 타고보니 무릎도 괜찮고
간만에 밤바람도 상쾌하고...
조금만 더 가자...

성남입구에서 돌아오는데...
무릎이 뻑뻑하다...
조금 뻑뻑하니 조심해야겠다라고 생각하고
아주 아주 가볍게 페달을 돌리고 왔는데...

무릎이 점점 아퍼오기 시작한다... ㅠㅠ
지난 번 너무 많이 아파 택시타고 오고
2~3일간 제대로 걷지도 못해서
오른발로만 페달링 하다가...
잠시 같이 돌리다가를 반복하면서 겨우 복귀했는데...

아무래도 안장 등 피팅이 뭔가 틀어진게 아닌가도 싶다.
멀쩡한 다리로 한 발로 페달링하는데에도
스무스하게 돌리기가 어렵다...










광교 호수공원도 오랜만에 밤에 지나왔는데...








예전에 자주 왔었던 곳에 멈춰
아픈 무릎도 쉬고

한참 전에 찍었던 곳에서 자전거도 한번 다시 휴대폰 카메라에 담아본다.











그러고보니 원천호수의 야경은 다소 바뀐거 같다.
요란하게 다양한 색의 불빛으로 현란하게 빛나던 목재로 만든 호수가 산책로도 심플하게 흰 색으로 길을 비추고 있고








호수가에는 아름다운 색으로 하트 장식물이 놓여있어 지나는 사람들을 멈추게 한다.


꼭 자전거가 아니더라도 가끔씩 바람쏘이러 나와도 좋을 것 같은데 광교 호수공원 나와본지도 꽤 오래된 것 같다. 더위에 부상에 또 게으름에...





피팅부터 다시 점검하고...
로라로 천천히 재활을 하고 난 다음
집 주변에서 거리를 늘리고 ... 그러고 나서 복귀해야 할 것 같다.

이번 시즌은 재활시즌으로 ... ㅠㅠ

회사후배에게 물어봐 잔차인 동회회에서 많이 이야기되는 무릎 잘보는 정형외과를 하나 알게 되어 다음 주말에 가봐야겠다. 그냥 통증만 다스려서는 안될듯.....










2018년 8월 14일 화요일

180813.골프연습


백스윙시 허리각을 유지하면 
백스윙시작하면서 몸이 쏠리지 않으면서도 
오른쪽 앞으로 안정되게 지탱하면서 체중이 되는 느낌으로 백스윙이 되고
이때 손의 움직임을 의식하며 궤도를 맞추면 안정된 백스윙에 가까워지는 것 같다.

이렇게 하면 백스윙 탑 이후에도 백스윙탑에서 오른쪽 뒤에서 시작해서 왼쪽 앞으로 자연스런 체중이동이 가능해짐을 느낄 수 있었다.

요즘 연습하는 주요 내용으로
다운스윙은 체중 이동후 그립을 공으로 찍으면서 왼손목을 꺽지 않고 허리회전과 클럽이 같이 돌아가 당기지 않는 스윙을 한다.

180708.무릎 부상 경과


예전에 골프 연습 중 통증이 왔던 무릎부분

한강 근처 언덕에서 다른 근육을 활용 해보고자 안장 앞으로 이동
살짝 통증이 와서 주의헤서 타고 복귀 중 다시 이상한 힘을 사용한 거 같음.

0711 회사 한의원
오늘 침은 많이 아프고 점점 뻐근해짐.
인대가 다시 붙는데 위치에따라 재발가능
 
0710 회사 한의원 다른 선생님
경도 염좌
1주 치료 후 통능 없어지면 2주정도는 재활 기간으로 좀하고 운동량을 조금씩 늘려가도록... 
침 맞고 뒷쪽 댕겨서 뒷쪽 물리치로

0709 회사 한의원
인대 진단
침과 파스 내일 부황 예정



2주차

골프.퍼팅과.웨지
7번 그리고 드라이버도 한번

계단은 지하와 2층만
수영은 발 안쓰기

3주차

계단 14층까지 
7번 아이언 1 ~ 2일

4주차

계단 23층까지

5주차

수요일 스크린, 큰 무리는 없었음.

6주차

아직 드라이버 연습은 하고 있지 않음.
아이언도 열심히 하면 무릎이 살짝 뻑뻑해 오는 것 같음.

7주차

드라이버 연습도 해보자.
자전거도 간단하게 타보자.

2018년 8월 13일 월요일

Python에서 excel 처리 (openpyxl)


openpyxl을 처음 사용해보면서 이것 저것 테스트해 본 코드이다.
실제 워크북을 읽어들인 후에 수정한 이후 저장하였을때
reference가 아닌 해당 cell에 직접 수정을 가하여야 반영되는 것 같은데 조금 더 사용해 봐야 할 것 같다.

Workbook은
1. Workbook()으로 빈 workbook을 생성하거나
2. load_workbook()으로 파일내용을 access 가능하다.

Workbook내에는 여러 sheet들이 있고
이 sheet들의 access는
1. workbook.worksheets로 list들로 받아 올 수 있으며
2. 바로 workbook[sheetname]으로 sheet를 받아 올 수 있다.

sheet에서는 iterator를
1. sheet.iter_rows() 나
2. sheet.rows 를 통하여 row / column의 iterator를 얻어 올 수 있다.
3. sheet['1'] 이나 sheet['A']로도 얻어올 수 있다.

cell을 access하기 위해서는 
1. 각 row나 column에서 cell을 access할 수도 있고
2. sheet['A1']나 sheet['A1:B2'] 형태로 하나 및 그 이상의 cell을 access할 수 있고
3. Cell 함수를 이용할 수도 있다.

cell에 값을 넣을때
1. sheet['A1'] = value 와 같이 바로 assign이 가능하며
2. cell.value = value로 assign도 가능하다.


from os import listdir
import os
from openpyxl import load_workbook, Workbook

def copyexcel(sfn, tfn):

    sx = load_workbook(sfn, read_only=True)
    if(sx == ''):
        return

    ssheet = sx.active

    tx = Workbook()
    tsheet = tx.create_sheet('Sheet')

    '''

    ws = sx.worksheets
    wsn = sx.sheetnames
   
    ssheet = sx["sheetname"]

    row = sheet['1']
    col = sheet['A']
    rows = sheet['1:2']
    cols = sheet['A:B']

    rows = sheet['A2:B3']

    sheet['A1'] = 'my input data'
    sheet.append['A1-data', 'B1-data', 'C1-data']
    sheet.append['A2-data', 'B2-data', 'C2-data']

    cell = sheet['A1']
    cell.data_type = c.TYPE_BOOL, c.TYPE_ERROR, C.TYPE_FORMULA, c.TYPE_FORMULA_CACHE_STRING, c.TYPE_INLINE, c.TYPE_NULL, c.TYPENUMERIC, c.TYPE_STRING

    '''

    for row in ssheet.iter_rows():
        row_data = []
        for cell in row:
            row_data.append(cell.value)

        tsheet.append(row_data)

    tx.save(tfn)
     


def main():

    files = listdir('.')

    for f in files:
        if os.path.isdir(f):
            continue
        if f[-4:] != 'xlsx':
            continue
   
        fn = f[:-5]
        newfn = fn + '_new' + '.xlsx'

        copyexcel(f, newfn)

if __name__ == "__main__":
    main()

Python module - CSV에서 " " 내의 , 처리하기


별 볼일 없는, 또는 이미 있을 수 있는 작은 툴이면서
업무하면서도 사용할 수 있을 것 같아 만들어 보았다.

오랜만에 작성해 보는 프로그램이라 그런지, 아이디어 자체도 대단한게 없고 난이도가 높은 함수도 아니고 python에 좀 친숙해져 보려고 시작한 것인데

본격적으로는 처음 vi로 작성해 보는 것도 있고 아직 디버깅 툴없이 print를 이용해 코딩하느라 (사실 디버깅이라고 할 것도 없고 나의 휴먼에러를 땜빵하기 위한 것임) 생각보다 버벅거리며 작성했다.

gettime
: ','로 분리된 csv file을 읽어들일때 " " 내에 ','가 있어 제대로 항목 분리가 안될 수 있어 이를 처리하는 함수임.

paramter :
- line
  : csv file에서 읽은 하나의 line
- numString (default 값 = False)
  : 숫자 항목은 string이 아닌 숫자로 변환 처리하는 flag

다음에는 docstring도 넣어볼까...



def getitem(line, numString=False):
    lst = []
    flag = False
    newitem = ''
    line = line.strip()

    if len(line):
        rawlist = line.split(',')
        for item in rawlist:

            # print("item = %s, newitem = %s" % (item, newitem))

            if (not flag) and item.isdigit() and numString:
                i = int(item)
                lst.append(i)
                continue

            if item[0] == '"':
                flag = True
                newitem = item
                continue

            if flag:
                newitem += item;
                if item[len(item)-1] == '"':
                    flag = False
                    lst.append(newitem)
                continue

            lst.append(item)

    return lst



if __name__ == "__main__":

    try:
           with open('testcsv.csv') as f:
               for l in f:
                   # print(l)
                   lst = getitem(l, True)
                   print(lst)
    except Exception as e:
        print(e)
    finally:
        print("End of Program")

Python daemon 예제



import time
import logging
import threading

logging.basicConfig(level=logging.DEBUG, format="name: %(threadName)s, argument: %(message)s")

def daemon():
    logging.debug("Start")
    time.sleep(5)
    logging.debug("Exit")

def main():
    t = threading.Thread(name="daemon", target=daemon)
    t.setDaemon(True)

    t.start()
    t.join()



main()

Python Thread / Multiprocessing예제



제공되는 Thread를 이용하기


import logging
import threading

logging.basicConfig(leve=logging.DEBUG, format="name: %(threadName)s, argument: %(message)s")

def worker(count):
    logging.debug(count)

def main():
    for i in range(5):
        t = threading.Thread(target=worker, name="thread %i" % i, args=(i,))
        t.start()

main()



CLASS를 만들어 이용하기


import logging
import threading


logging.basicConfig(level=logging.DEBUG, format="name: %(self.name)s, argument: %(message)s")

class Worker(threading.Thread):
    def __init__(self, args, name=""):
        threading.Thread.__init__(self)
        self.args = args

    def run(self):
        print("name: %s, arg: %i" % (self.name, self.args[0]))
        # logging.debug(self.args)

def main():
    for i in range(5):
        t = Worker(name="Thread %i" % i, args=(i,))
        t.start()

main()



Lock 예제


import time
import logging
import threading


logging.basicConfig(level=logging.DEBUG, format="name: %(threadName)s, argument: %(message)s")

def blocking_lock(lock):
    logging.debug("Start blocking lock")

    while True:
        time.sleep(1)
        lock.acquire()
        try:
            logging.debug("Grab it +++++++++++++++++++++++++++++++++++")
            time.sleep(1)
        finally:
            logging.debug("Release -----------------------------------")
            lock.release()

def nonblocking_lock(lock):
    logging.debug("Start nonblocking lock")

    attempt, grab = 0, 0
    while grab < 3:
        time.sleep(0.7)
        logging.debug("Attempt")
        success = lock.acquire(False)

        try:
            attempt += 1
            if success:
                logging.debug("Grab it")
                grab += 1
        finally:
            if success:
                time.sleep(0.22)
                logging.debug("Release")
                lock.release()

    logging.debug("Attempt : %s, grab : %i" % (attempt, grab))

def main():
    lock = threading.Lock()

    blocking = threading.Thread(target=blocking_lock, name="blocking", args=(lock,))
    blocking.setDaemon(True)
    blocking.start()

    nonblocking = threading.Thread(target=nonblocking_lock, name="nonblocking", args=(lock,))
    nonblocking.start()



main()


Multiprocessing 예제


import os
import multiprocessing

def worker(count):
    print("name: %s, arg: %i" % (multiprocessing.current_process().name, count))
    print("ppid: %i, pid: %i" % (os.getppid(), os.getpid()))

def main():
    for i in range(5):
        p = multiprocessing.Process(target=worker, name="process %i" %i, args=(i,))
        p.start()


if __name__ == "__main__":
    main()


Multiprocessing pool 예제


import time
import multiprocessing

def initmsg():
    print("Start proc %s" % multiprocessing.current_process().name)

def worker(data):
    print("Do calculate on proc %s with data %i" % (multiprocessing.current_process().name, data))
    return data*2

def main():
    p = multiprocessing.Pool(processes=4, initializer=initmsg)
   
    time.sleep(1)
    print("Do work !")

    data_list = range(10)
    result = p.map(worker, data_list)

    p.close()
    p.join()

    print("Result : %s" % result)


if __name__ == "__main__":
    main()

Co-Routine


co-routine은 해당 function의 실행환경을 보관하고 있으며
이를 이용하여 generator를 작성한다.

def coroutine():
    print("A ...")
    while True:
        print("B ...")
        msg = yield
        print("Hello, your input message is '%s'" % msg)

def main():
    print("1 ---")
    c = coroutine()
    print("2 ---")
    next(c)
    print("3 ---")
    next(c)
    print("4 ---")
    c.send("Test")
    print("5 ---")
    c.send("Coroutine")
    print("6 ---")

if __name__ == "__main__":
    main()

VI editor 사용키



VI editor 다시 사용하기 시작한지 얼마 안되었는데
아직 불편함이 편함보다 많다.

계속 사용해보고, 키가 익혀지면 좀 더 강력한 기능도 사용해 보도록 해봐야겠다.

아래 d를 보면 대부분 delete로만 생각하는 것 같은데 PC의 ctrl-x처럼 내용을 메모리에 복사하는 기능도 가지고 있으니 참고하면 좋을 듯


기능 Key
Key
기능
PC Key 대응
d
삭제 (및 clipboard에 복사)
ctrl-x
y
복사 (clipboard에)
ctrl-c
c
ctrl-x 및 해당 위치에서 insert

u
마지막 수정 복구

U
현재 라인 모든 수정 복구

ctrl-r
undo를 undo (redo)
ctrl-
a
append (at the current position)

A
append (at the end of line)

i
inserte (at the current position)

I
insert (at the end of the line)

o
insert (make a new line below the line)

O
insert (make a new line above the line)

p
paste
ctrl-v

CMD 적용 범위에 대하여 

※ [횟수] [CMD] [범위] 또는 [CMD] [횟수] [범위] 형태로 사용
범위 key
범위
동일 cmd
공통적으로 같은 alphabet은 해당 라인 전체를 의미
dd : 해당 라인 전체를 ctrl-x
w
word (whitespace 포함)
dw, d3w, 3dw
e
word (whitepace 미포함)
de
$
해당 line 끝까지
d$

Window에 대하여 

Key
cmd line
가로 생성
ctrl-w s
:sp
:split
세로 생성
ctrl-w v
:vs
:vsplit
window 이동
ctrwl-w h / j / k / l




Command line 명령어
cmd line
기능
기타
:open filename파일 오픈
:r filename파일내용 현재 위치에 삽입:r !ls 식으로 shell cmd 실행결과도 삽입 가능

(아래는 다른 사이트에서 복사해 왔는데... 어디서 복사해 왔는지 기억이 나지 않네요...
누군가 코멘트 해주시면 출처를 기재하겠습니다.)

1. 페이지 이동[편집]

  • Ctrl+F : 페이지 앞으로(아래로) ★
  • Ctrl+B : 페이지 뒤로(위로) ★

2. 비주얼 모드[편집]

기능
gg파일 맨 처음으로 ★
G파일 맨 끝으로 ★
123G123행으로
yyp현재 줄을 복사하여 아래에 삽입
dd현재 줄 삭제
dG현재 줄 이하 모두 삭제
i삽입모드(insert) ★★★
o다음 줄에서 삽입모드(insert) ★
u되돌리기(undo) ★
$문장의 끝으로 이동 ★
^문장의 처음으로 이동 ★
.마지막 동작 반복

3. 삽입 모드[편집]

기능
Esc삽입 모드 종료(비주얼 모드로 나감) ★★★
Ctrl+P자동완성★★

4. 명령 모드[편집]

기능
 :w저장
 :q종료
 :q!수정분 저장하지 않고 종료 ★★★
 :wq수정분 저장하고 종료 ★★★
 :se nu[1]행번호 보이기
 :se nonu[2]행번호 숨기기
 :%s/변경전문자열/변경후문자열/g문자열 치환
%는 문서 전체에 해당
#,#은 특정 line 범위
그냥 s를 사용하면 현재 line
g : 해당 범위 전체
c : confirm 적용
 :sp가로 분할(split)
 :vs세로 분할(vertical split)
 :!명령어쉘 명령어 실행
 :shshell로 임시 나가기 ( 되돌아 올때는 exit)

5. 검색[편집]

입력기능
/문자열문자열 찾기
n다음 찾기
N이전 찾기
 :noh하이라이트 제거


200926.가오리코스 라이딩

9/26 골절인지 아닌지 확인 안됨. 이후 미세골절여부 확인 핸드폰을 드는 것도 어려움 9/29 x ray 다시 찍지 않고 이후 재 방문 요청 ...