반응형
flask

Simple Python Web API Server

쉽고 빠르게 웹 API 서버를 만드는 방법.
언어는 Python
아래 방식을 참고하면 아주 빠르고 간단하고 쉽게 API 서버를 만들 수 있다. 여기에 서비스에 필요한 작업들을 추가만 해 주면 된다.
POST 방식으로 JSON 포맷을 사용하여 통신하는 것을 추천한다.

개발툴로 PyCharm을 사용
패키지 설치

# pip install flask
# pip install flask_restful

아래 코드를 작성한다.

  • testsvr . py
'''
test api server
'''

from flask import Flask, request
from flask_restful import Resource, Api
from flask.views import MethodView

import logging
import json,base64

import os, sys
import datetime
import threading, time

app = Flask(__name__)
api = Api(app)

log = logging.basicConfig(filename='testsvr.log', level=logging.INFO)

# 로깅을 전부 끄기
# logging.getLogger('werkzeug')
# log = logging.get
# log.disabled = True
# app.logger.disabled = True

'''
/apitest1
'''
class apitest1(MethodView):
    def get(self):
        data = request.args
        print('recv:', data)  # dictionary
        abc = data.get('abc')
        if abc :
            result = 'This is GET method!'+str(abc)
        else:
            result = 'Hello World! input abc'
        return result

    def post(self):
        # get과 동일하게 작동
        return self.get()


'''
/sum
'''
class sum(MethodView):
    def get(self):
        data = request.args
        print('recv:', data)  # dictionary
        return 'Hello.'

    def post(self):
        '''
        JSON으로 받아서 작업 후 JSON으로 결과 반환
        '''
        logging.info('sum test')
        # print('request.data=', request.data)  # binary data read all
        data=request.get_json(force=True) # parse json string
        print('request.json=', data)
        a = data['a']
        b = data['b']
        now = datetime.datetime.now()
        print(now)
        timestr = now.strftime('%Y%m%d %H:%M:%S')
        result = {
            'sum':int(a+b),
            'time':timestr
        }
        logging.info('result='+json.dumps(result))
        return result


api.add_resource(apitest1, '/apitest1')
api.add_resource(sum, '/sum')

port = 18899

if __name__=='__main__':
    print('Start Server... port=', port)
    logging.info('start server')
    app.run(host='0.0.0.0', port=port, debug=True)
    # 디버그 모드로 하면 소스 수정시 자동으로 서버 재시작이 된다.


서버 구동 스크립트는 다음을 참고

---testsvr.bat---
c:\python37\scripts\python testsvr.py

---testsvr.sh---
#!/bin/bash  
  
# [python env path...]/bin/python testsvr.py  
# linux ex)  
/opt/anaconda3/envs/tensorflow/bin/python testsvr.py  
# windows command ex)  
# c:\python37\scripts\python testsvr.py

테스트 화면 : GET 방식
주소: http://localhost:18899/apitest1?abc=123&def=456
image

테스트 화면 : POST 방식, 덧셈 API
주소: http://localhost:18899/sum
POST 데이터: {“a”:5, “b”:6}
image

Written with StackEdit.

반응형
graphsetting_reset

그래프 설정 리셋

가끔가다 그래프 설정의 변경으로 잘 나오던 그래프가 깨지는 경우가 종종 나온다. matplotlib과 seaborn 등 여러가지를 막 섞어 쓰다보면 가끔 발생한다.

다음과 같이 잘 나오던 그래프가
image

어느 순간 다시 똑같은 코드를 실행했는데, 이런 결과가…
(위와 아래는 똑같은 코드다.)
image

Jupyter Lab에서 커널을 다시 기동해야지만 다시 원래대로 나오는데, 마찬가지로 중간에 어떤 작업으로 인해 그래프 설정이 변경되면 위와 같이 다시 이상하게 출력되었다. 나중에 원인을 찾아보니… 아래의 sns.set() 코드였다.
image
이후 부터는 이상한 그래프가 출력된 것이다. 원상 복구를 하는 것을 찾아보다가 reset해 주는 코드를 찾았다.
또한 설정값 변경된 것을 확인해 주는 코드도 있다.

image
위와 같이 pltconfig_default() 함수를 만들어 사용하면 원래 설정대로 복원된다.

참고로 다음은 plot 설정값이 디폴트에서 변경된 내역을 찾아주는 코드다.

# plot 환경설정 기본값과 달라진 점
class DictDiffer(object):
    """
    Calculate the difference between two dictionaries as:
    (1) items added
    (2) items removed
    (3) keys same in both but changed values
    (4) keys same in both and unchanged values
    """
    def __init__(self, current_dict, past_dict):
        self.current_dict, self.past_dict = current_dict, past_dict
        self.set_current, self.set_past = set(current_dict.keys()), set(past_dict.keys())
        self.intersect = self.set_current.intersection(self.set_past)
    def added(self):
        return self.set_current - self.intersect 
    def removed(self):
        return self.set_past - self.intersect 
    def changed(self):
        return set(o for o in self.intersect if self.past_dict[o] != self.current_dict[o])
    def unchanged(self):
        return set(o for o in self.intersect if self.past_dict[o] == self.current_dict[o])
    
def pltconfig_check():
    d=DictDiffer(plt.rcParams, plt.rcParamsDefault)
    for it in d.changed():
        print(it, plt.rcParamsDefault[it], plt.rcParams[it])

위에서 sns 환경설정 변경으로 기존의 세팅과 변경된 내역을 확인해 보자.
image
상당히 많은 설정값들이 변경된 것을 확인하였다.

image

다시 원래 디폴트로 돌아온 것이다. 위에서 나온 변경내역은 matplotlib inline으로 인해 변경된 내역이므로 신경쓰지 않아도 된다.

Author: crazyj7@gmail.com
Written with StackEdit.

'Python' 카테고리의 다른 글

초간단 python 서버만들기2  (0) 2019.09.25
초간단 웹API서버만들기  (0) 2019.09.25
JupyterLab에서 Python Script(.py)실행하기  (0) 2019.09.19
Jupyter Notebook 멀티라인출력  (0) 2019.09.19
진행(progress)바/ tqdm  (2) 2019.08.28
반응형
jupyterlabrunscript

JupyterLab에서 Python Script 실행

Jupyter Lab에서 노트북 ipynb 파일을 지원하는데 가끔은 python script (.py) 파일을 실행하고 싶을 때가 있다. 편리하게 실행할 방법은??

  • 일단 Jupyter Lab에서 python script 파일을 연다. (더블클릭)
  • 에디터 창에서 마우스 우클릭하여 콘솔 실행
    image
    -아래에 IPython 콘솔창이 화면분할되어 실행될 것이다. 파이썬 코드에서 plot 출력이 있다면 %matplotlib inline을 실행해 줘야 plot이 출력된다. (스크립트에 이미 이 코드가 포함되어 있으면 이 과정은 생략한다.)
    image
    -마지막으로 스크립트 에디터 창에서 컨트롤A (전체선택), 쉬프트엔터(실행) 하면 끝이다.
    image

Author: crazyj7@gmail.com

'Python' 카테고리의 다른 글

초간단 웹API서버만들기  (0) 2019.09.25
그래프 리셋(seaborn plot graph reset)  (0) 2019.09.20
Jupyter Notebook 멀티라인출력  (0) 2019.09.19
진행(progress)바/ tqdm  (2) 2019.08.28
Google Drive file upload/download  (0) 2019.08.20
반응형
multilineoutput

Jupyter Notebook에서 멀티라인 출력

Jupyter Notebook에서 변수값을 출력하기 위해서는 한 셀내에 변수명이나 함수명을 주면 해당 값(변수값, 리턴값)이 출력된다. 그러나 한 셀내에 여러 개의 변수명을 출력하고자 하게 되면 마지막 변수 한 개 값만 출력된다.
한 셀내의 여러 명령줄의 모든 출력을 하려면 각각의 변수 앞에 별도로 print 문을 사용해야 하는데 이쁘게 출력되지도 않고 매우 번거로운 작업이다.
이것을 한 번에 해결 할 수 있다.

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
  • Before: 한 셀에 복수개 출력 시도시 마지막값만 나온다.
    numpy_before

  • After:
    한 셀에 멀티 출력 지원
    numpy_after_multiline

Author: crazyj7@gmail.com
Written with StackEdit.

'Python' 카테고리의 다른 글

그래프 리셋(seaborn plot graph reset)  (0) 2019.09.20
JupyterLab에서 Python Script(.py)실행하기  (0) 2019.09.19
진행(progress)바/ tqdm  (2) 2019.08.28
Google Drive file upload/download  (0) 2019.08.20
Fourier Transform Python  (2) 2019.08.02
반응형
progressbar_tqdm

진행상황 tqdm

패키지 설치를 할 때 보면 나오는 텍스트 타입의 진행바 모양이 있다. 작업이 어느 정도 진행되었고 남았는지 알 수 있어서 없는 것보다는 답답함이 해결되는 효과가 있다.

이것을 구현하기 위해서는 tqdm 패키지를 사용하면 된다. tqdm의 파라미터로 iterable 객체를 넣어주면 알아서 전체 반복 횟수 중 진행반복횟수를 표시해 준다.

from tqdm import tqdm
import time
for i in tqdm(range(100)):
   time.sleep(0.01)

콘솔 출력문을 추가했을 경우 아래와 같이 된다. (없으면 한 줄로 업데이트 진행됨)
progress1

  • range(30, 100) 으로 파라미터를 줄 경우, 전체 반복량은 70이므로 0/70부터 시작하여 70/70까지 진행 표시된다.

progress2

파라미터 설명

  • iterable : 반복자 객체
  • desc : 진행바 앞에 텍스트 출력
  • total : int, 전체 반복량
  • leave : bool, default로 True. (진행상태 잔상이 남음)
  • ncols : 진행바 컬럼길이. width 값으로 pixel 단위로 보임.
  • mininterval, maxinterval : 업데이트 주기. 기본은 mininterval=0.1 sec, maxinterval=10 sec
  • miniters : Minimum progress display update interval, in iterations.
  • ascii : True로 하면 '#'문자로 진행바가 표시됨.
  • initial : 진행 시작값. 기본은 0
  • bar_format : str
  • 전체 작업량을 알고 있고, 처리된 량으로 진행바를 표시할 경우. (update에 진행량을 파라미터로 추가). 파일 읽기 같은 경우 활용가능하다.
t = tqdm(total=500)
for i in range(250):
    time.sleep(0.01)
    t.update( 2 )
t.close()
  • clear() : 삭제

  • refresh() : 강제 갱신

  • 중간부터 진행되는 경우. 전체 작업량이 500인데, 100은 이밎 처리되서 100부터 시작하는 경우.

t = tqdm(total=500, initial=100, ascii=True)
for i in range(200):
    time.sleep(0.01)
    t.update( 400/200 )
t.close()

Written with StackEdit.

'Python' 카테고리의 다른 글

JupyterLab에서 Python Script(.py)실행하기  (0) 2019.09.19
Jupyter Notebook 멀티라인출력  (0) 2019.09.19
Google Drive file upload/download  (0) 2019.08.20
Fourier Transform Python  (2) 2019.08.02
[UI] Qt5  (0) 2019.05.17
반응형

두 선분이 교차하는지 검사하려면?


이차원상에서 직선이라면 기울기가 다르기만 하면 즉, 평행하지만 않으면 언젠가는 만나게 된다.

그러나 직선이 아니라 선분이면 길이가 정해져 있다.


선분1과 선분2가 있을 때, 각각 직선으로 확장한 것을 직선1, 직선2라고 하자.


직선1로 선분2의 양 끝점을 양분한다면 선분2와 직선1이 만나게 된다. (이 조건만 만족한다면, 직선1 대신 선분1로 했을때 선분1이 확장되지 않아 선분2와 만나지 않을 수도 있다. 즉 선분2이 직선2로 봤을 때 한쪽에 존재하는 경우이다.)

반대로 직선2로 선분1의 양 끝점을 양분한다면 선분1과 직선2가 만나게 된다. ( 이 조건도 만족한다면, 선분1이 직선2의 한쪽에 있지 않아서 위 걱정이 사라지게 된다.)


위 두 조건을 만족한다면, 선분1과 선분2가 만나게 된다.

모든 경우의 수를 따져보면 위 가정이 맞다는 것을 확인 할 수 있다.


먼저, 직선이 두 점을 양분하는지 검사하려면?

f(x)=0라는 직선이 있을 때, 두 점을 각각 넣어서 부호가 반대인 것을 의미한다.

y=mx+b 라는 직선이라고 본다면, 검사할 점(x1,y1)의 x좌표를 넣어서 나온 y값(mx1+b. 직선위의 점)이 검사할 점의 y좌표(y1)보다 크냐 작냐에 따라 직선 아래 또는 위에 있을지 결정된다.  따라서 y1-(mx1+b)를 하게 된 부호가 중요하다.  다른 점 (x2,y2)도 마찬가지로 넣으면

y1-(mx1+b)

y2-(mx2+b)

위 두 값의 부호가 다르면 양분된다. (y=mx+b 직선이 두 점을 양분한다.)

즉, 위 두 값을 곱하여 0보다 작으면 위 조건을 만족하게 된다


직선 1의 기울기를 구하고 방정식을 구하면

y = m1 (x-x11) + y11


직선2의 기울기를 구하고 방정식을 구하면

y=m2(x-x21)+y21


조건1 ;직선1이 두점(x21, y21), (x22, y22)를 양분하는지 검사

f1=y21- (m1 x21 - m1 x11 + y11 )

f2=y22 - (m1 x22 - m1 x11 + y11 )

f1*f2 < 0 이면 양분 된다.

좀 더 정리하면 


f1=y21 - ( x21 (y12-y11)/(x12-x11)  - x11 (y12-y11)/(x12-x11) + y11)

 = { 1/(x12-x11) }  * {  y21(x12-x11) - x21(y12-y11) +x11(y12-y11) -y11(x12-x11) }

=  { 1/(x12-x11) }  * { (y21-y11)(x12-x11) - (x21-x11)(y12-y11) }

이렇게 된다.

f2=위와 동일하다 (y21대신 y22, x21대신 x22를 대입)

f2={1/(x12-x11)} * { (y22-y11)(x12-x11) - (x22-x11)(y12-y11) }


f1*f2의 부호만 관심있으므로 분수 부분을 없애기 위해 (x12-x11)^2을 곱해도 부호는 변함없다.

따라서 분수를 없애면


f1 = (y21-y11)(x12-x11) - (x21-x11)(y12-y11) 

f2 = (y22-y11)(x12-x11) - (x22-x11)(y12-y11) 

if f1*f2 <0 then 양분됨.


이를 파이썬 모듈로 작성하면 간단하다.

def is_divide_pt(x11,y11, x12,y12, x21,y21, x22,y22):

    '''input: 4 points
output: True/False
'''
# // line1 extension이 line2의 두 점을 양분하는지 검사..
# 직선의 양분 판단
f1= (x12-x11)*(y21-y11) - (y12-y11)*(x21-x11)
f2= (x12-x11)*(y22-y11) - (y12-y11)*(x22-x11)
if f1*f2 < 0 :
return True
else:
return False

두 선분이 교차하는지 검사하려면 이것을 바꿔서 두 번하면 된다.


def is_cross_pt(x11,y11, x12,y12, x21,y21, x22,y22):
b1 = is_divide_pt(x11,y11, x12,y12, x21,y21, x22,y22)
b2 = is_divide_pt(x21,y21, x22,y22, x11,y11, x12,y12)
if b1 and b2:
return True

    return False


랜덤하게 점을 찍어서 그리고, 위 조건 모듈을 써서 판정해 본 그래프

잘 판정되었다. 위 모듈에서 주의해야 할 것은 수평이나 수직인 경우는 별도로 처리해 주어야 한다. divide by zero등도 신경써서 에러 처리를 해 주어야 할 것이다. 테스트해보니 수직, 수평에서도 잘 작동하였다. ( divide 부분을 미리 처리해 두어서 그런지 별 이상없음.)





'Python' 카테고리의 다른 글

Fourier Transform Python  (2) 2019.08.02
[UI] Qt5  (0) 2019.05.17
두 선분의 교점 찾기  (0) 2019.04.11
모든 성분에 따옴표붙여서 컴마 리스트로 출력하기  (0) 2019.04.11
[Python] enum  (0) 2019.03.28
반응형

두 선분의 교점 찾기 /intersection


선분1 ; (x11,y11) to (x12, y12)

선분2 ; (x21,y21) to (x22, y22)

위 두 선분이 주어졌을 때  교점의 좌표를 파이썬 함수로 만들어 보자.


선분 1의 기울기 ; m1


선분2의 기울기 ; m2


따라서 선분1의 직선은 기울기가 m1이고 (x11, y11)점을 지난다.

y = m1 (x-x11) + y11

선분2의 직선은 기울기가 m2이고 (x21,y21)점을 지난다.

y=m2(x-x21)+y21

위 두 직선의 교차점은 x, y가 같게 되므로 위 연립 방정식의 해가 된다.

m1x - m1 x11 + y11 = m2x - m2x21 + y21

(m1-m2)x = m1x11-y11-m2x21+y21

x = (m1x11-y11-m2x21+y21) / (m1-m2)


x를 구했으면 위 아무 방정식에 넣으면 y가 나온다.

y = m1(x-x11)+y11



import numpy as np
import matplotlib.pyplot as plt


def get_crosspt(x11,y11, x12,y12, x21,y21, x22,y22):
if x12==x11 or x22==x21:
print('delta x=0')
return None
m1 = (y12 - y11) / (x12 - x11)
m2 = (y22 - y21) / (x22 - x21)
if m1==m2:
print('parallel')
return None
print(x11,y11, x12, y12, x21, y21, x22, y22, m1, m2)
cx = (x11 * m1 - y11 - x21 * m2 + y21) / (m1 - m2)
cy = m1 * (cx - x11) + y11

return cx, cy


x11 =np.random.randint(1,50)
y11 =np.random.randint(1,50)
x12 =np.random.randint(50,100)
y12 =np.random.randint(50,100)
x21 =np.random.randint(1,50)
y21 =np.random.randint(50,100)
x22 =np.random.randint(50,100)
y22 =np.random.randint(1,50)

plt.figure()
plt.plot([x11,x12], [y11,y12], c='r')
plt.plot([x21,x22], [y21,y22], c='b')

cx, cy = get_crosspt(x11, y11, x12, y12, x21, y21, x22, y22)
plt.plot(cx, cy, 'ro')
plt.show()



선분이 수직, 수평인 경우는 기울기가 0가 되어 문제가 될 수 있다.

이 경우는 따로 처리한다.

# line1:(x11,y11)-(x12,y12) , line2:(x21,y21)-(x22,y22)

def get_crosspt(x11,y11, x12,y12, x21,y21, x22,y22):
if x12==x11 or x22==x21:
print('delta x=0')
if x12==x11:
cx = x12
m2 = (y22 - y21) / (x22 - x21)
cy = m2 * (cx - x21) + y21
return cx, cy
if x22==x21:
cx = x22
m1 = (y12 - y11) / (x12 - x11)
cy = m1 * (cx - x11) + y11
return cx, cy

m1 = (y12 - y11) / (x12 - x11)
m2 = (y22 - y21) / (x22 - x21)
if m1==m2:
print('parallel')
return None
print(x11,y11, x12, y12, x21, y21, x22, y22, m1, m2)
cx = (x11 * m1 - y11 - x21 * m2 + y21) / (m1 - m2)
cy = m1 * (cx - x11) + y11

return cx, cy


나중에 필요에 따라 겹치거나 평행한 경우도 검사해 주어야 한다. 이것은 다음에 직선이 두 점을 양분하는지 체크하면 된다.




'Python' 카테고리의 다른 글

[UI] Qt5  (0) 2019.05.17
두 선분의 교차여부 체크  (0) 2019.04.11
모든 성분에 따옴표붙여서 컴마 리스트로 출력하기  (0) 2019.04.11
[Python] enum  (0) 2019.03.28
랜덤스트링 만들기  (0) 2019.03.22
반응형


+ Python에서 Enum 사용하기


C나 C++에서 편하게 쓰던 enum이 python에서는 기본으로 없고 쓰기가 좀 불편합니다.

열거형(enum)은 상수와 같이 지정된 값을 이름을 부여하여 코드내에 가독성이 좋게 사용하기 위해 씁니다.

C로 예를 들면 상수타입을 그대로 쓸수도 있지만, 아래와 같이 불편합니다.

const int APPLE=1

const int BANANA=2

const int GRAPE=3

각각 값을 지정해 줘서 써도 되지만 번거롭습니다. 그래서 enum을 쓰죠.

enum Fruit {

APPLE=0,BANANA, GRAPE } ;

각 항마다 =1, =2 이렇게 값을 지정할수도 있고, 생략하면 순차적으로 이전 항보다 1씩 증가합니다. 

#include <stdio.h>


enum _fruit {

APPLE=0,

BANANA, GRAPE

};


int main()

{

enum _fruit a,b ;

a=APPLE ;

b=BANANA;

printf("a=%d\n", a) ;

printf("b=%d\n", b) ;

return 0 ;

}


C에서 보통은 좀 더 쓰기 편하기 typedef로 정의해서 사용하죠.

typedef enum _fruit {

APPLE=0,

BANANA, GRAPE

} FRUIT;


int main()

{

FRUIT a,b ;

a=APPLE ;

b=BANANA;

printf("a=%d\n", a) ;

printf("b=%d\n", b) ;

return 0 ;

}



파이썬에서는 enum을 아래와 같이 쓴다. 별도로 모듈을 임포트해줘야 한다. 

import enum


class Fruit(enum.Enum):

APPLE=0 

BANANA=1 

GRAPE=2


print(Fruit.APPLE)

print(Fruit.BANANA.value)

print(Fruit.GRAPE.value)


실행결과

Fruit.APPLE

1

2


값을 가져오려면 별도로 .value 프로퍼티를 써야 한다.

enum 변수값을 모두 각각 지정해 주어야 한다. 불편하다.


모듈 임포트 할 필요없이 별도로 함수를 만들어 enum을 쓰는 것이 편하다. 인덱스는 0부터 시작. 

def enum(*sequential, **named):

    enums = dict(zip(sequential, range(len(sequential))), **named)

    return type('Enum', (), enums)


Fruit = enum('APPLE','BANANA','GRAPE')


print(Fruit.APPLE)

print(Fruit.BANANA)

print(Fruit.GRAPE)


실행결과
0
1
2


반응형

HTML 파싱하여 원하는 부분 추출하기.


+ Beautifulsoup 설치

pip install beautifulsoup4
버전 4


+ URL로 HTML 가져와서파싱하기
from urllib.request import Request, urlopen
from bs4 import BeautifulSoup

url="http://www.naver.com/"
html = urlopen(url).read()

soup = BeautifulSoup(html, 'html.parser')

rank = soup.find("dl", id="ranklist")     # dl tag, id=ranklist search.

for i in rank.find_all("li", value=True, id=False):          # li tag, value exist, id no exist. search
     print( i.get_text(" ", strip=True) )  # 문자열을 가져오는데, 태그는 공백으로 두고, 앞뒤 공백 제거.


+헤더 추가
req = Request(url)
req.add_header('User-Agent', 'Mozilla/5.0')
html = urlopen(req).read()



+BeautifulSoup html 서치.

-모든 태그 검색
html_as=soup.find_all("a")     # 모든 a 태그 검색. 접근시 html_as[0], [1], .. 첫번째가 0인덱스.
soup("a")     # 상동

-스트링이 있는 title 태그 모두 검색
soup.title.find_all(string=True)
soup.title(string=True)

-a태그 두 개만 가져옴.
soup.find_all("a", limit=2)

-스트링 검색
soup.find_all(string="elsie")   해당 스트링 검색
 or검색을 하려면 array 로 입력 ["aa", "bb"]
 정규식을 쓰려면 re.compile("정규식")

-태그와 속성(클래스)값으로 검색
soup.find_all("p", "title")
soup.select('p[class="title"]')
ex) <p class="title"></p>

-태그와 태그 사이 찾기
soup.find_all(["a", "b"])

-속성(클래스)값 가져오기
soup.p['class']
soup.p['id']

-보기 좋게 출력
soup.b.prettify()


-검색
soup.body.b     각 첫번째 노드
soup.a     # 처음으로 나오는 a태그

-태그와 클래스명 검색
soup.find_all("a", class_="sister")     # class_ 를 사용. 예약어라서 _를 사용.

-태그와 ID로 찾기
soup.find("div", id="articlebody")
soup.find("div", { "id":"articlebody" } )
soup.find(id="articlebody")

soup.select("#articlebody") ; id로 검색.
soup.select("div#articlebody") ; 태그와 id로 검색.

-태그와 클래스로 찾기 
soup.select('div ol[class="list1"]')

find_all 이나 select는 array로 리턴. 복수개!
하나만 찾을 때는 find 사용.


-검색결과 없으면 None

-태그의 이름 얻기
soup.find("div").name

-속성 얻기
soup.find("div")['class']          없으면 에러
soup.find("div").get('class')     없으면 None


-태그 사이에 있는 중간의 텍스트 얻기
contents 속성 사용.
<p> aaa
<b> one </b>
cc
</p>

soup.b.string          ==> one
soup.b.contents[0]     ==> one

soup.p.contents     ==> aaa, <b>one</b>, cc
     원하는 원소 인덱스를 사용.

-다음 형제 태그
soup.p.next_sibling

-태그 내부 추적 검색
ptag = soup.p
ptag('table')[0]('tr')[0]('td')[0]

-태그 사이 텍스트 전체 
ptag.get_text()




+ HTML 파일에서 읽기
import codecs

page_html = codecs.open('a.html''r''utf-8')
page_soup = soup(page_html, "html.parser")

+태그 추적하기 
예)

// span 태그의 아이디로 먼저 검색하고, 자식중에 2번째 table 태그를 찾음.
testwebsite_container = page_soup.find("span"id="MainContent2_ctl00_lblContent").findAll("table")[1]

skiptrcnt=1 # skip first tr block
for i,record in enumerate(testwebsite_container.findAll('tr')):    # 모든 tr태그를 검색.
    if skiptrcnt>i:
        continue
    # 처음 n개는 스킵한다.
tnum = record('td')[0].text        # 첫 번째 td의 텍스트
desc = record('td')[1].text
doclink = record('td')[2].text    #세번째 td의 텍스트 (a link의 보이는 링크명으로 보이는 부분이 나옴.)
alink = record('td')[2].find("a")       # 세번째  td에서 하위에 a태그를 찾음.
if alink :
    doclinkurl=testwebsite+alink['href'   # 속성! href의 값을 가져온다. 
closingdate = record('td')[3].text

detail = record('td')[4].text            # td태그 내부에 br태그가 있으면 줄바뀜이 생김.
detail = detail.replace('\n''')        # 줄바뀜 제거. 











'Python' 카테고리의 다른 글

File I/O, Directory list, read/write  (0) 2018.07.04
WebAPI thread work status  (0) 2018.07.03
Python 데이터 저장/로딩 Pickle  (0) 2018.04.25
Python 커맨드라인 파싱  (0) 2018.04.17
Python 쉘 커맨드 실행  (0) 2018.04.12
반응형


보간법. interpolate 


몇 개의 샘플 포인트들로 추정하여 인접한 점들 사이를 다항식 함수로 완만한 곡선으로 이어준 것을 스플라인 곡선이라고 한다.

보간법은 이러한 미싱 포인트(추정)들을 계산/추정하는 방법이다.

간단하게는 linear 방식(1차)이 있고, 2차, 3차, 4차 곡선등으로 확장하면서 보다 다양하게 추정할 수 있다.



위 그림은 파란색 점의 샘플 좌표들만을 가지고, 스플라인 곡선을 만들어 그린 추정 그래프이다.

python에서 scipy 라이브러리의 interpolate를 사용하여 구현하였다.

아래 코드에서 splrep에 별다른 옵션이 없으면 3차 스플라인 곡선으로 추정하게 된다. (k=1(선형보간), k=2, k=3(default), k=4 이런식으로 옵션을 준다. )

[python code]


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu May 25 2017
@author: crazyj
"""

# interpolation test

import numpy as np
import scipy.interpolate as ip
from scipy.interpolate import splrep, splev
import matplotlib.pyplot as plt

# 0~10까지 15개로 나누어 점을 찍음.
x0 = np.linspace(0, 10, 15)
print('x0=', x0)
# cosine 값을 계산
y0 = np.cos(x0)

# x, y (샘플)값을 주고 추정하는 스플라인 곡선을 만든다.
spl = splrep(x0, y0)
# 0~10까지 50구간에 대한 모든 점들을 위 스플라인 곡선으로 추정한 y값을 구한다.
x1 = np.linspace(0, 10, 50)
y1 = splev(x1, spl)

# 그린다.
plt.figure(figsize=(16, 5))
plt.subplot(121)
plt.plot(x0, y0, 'o')
plt.plot(x1, y1, 'r')
plt.grid()

# 이번에는 sine 곡선으로 추정해 본다.
plt.subplot(122)
y2=np.sin(x0)
spl2=splrep(x0, y2)
y3=splev(x1, spl2)
plt.plot(x0, y2, 'o')
plt.plot(x1, y3, 'b')
plt.grid()
plt.show()



'Python' 카테고리의 다른 글

Python 강좌4 정규식 regular expression  (0) 2018.03.19
Python 강좌3 자료형. 수/문자열  (1) 2018.03.16
Python 강좌2 if/for/while/function  (0) 2018.03.15
Python 강좌1. 산술연산, range  (0) 2018.03.14
Linear regression  (0) 2018.03.13

+ Recent posts