반응형
파이썬으로 투명 배경의 이미지로 만드는 방법

아래 코드에서 pixel 배열에 R,G,B 값이 들어있으므로 원하는 컬러를 투명하게 처리할 수 있다.

색깔 범위를 +- 5~10정도 주면 좀 더 배경을 잘 제거 할 수 도 있을 것이다. 

from PIL import Image

# 이미지 파일 열기
image = Image.open("image.png")

# 새로운 alpha channel 생성
alpha_data = []
for pixel in image.getdata():
    if pixel[0] == 255 \
        and pixel[1] == 255 \
        and pixel[2] == 255:
        alpha_data.append(0)
    else:  # 그 외의 경우 alpha 값을 255로 설정
        alpha_data.append(255)
alpha_channel = Image.new("L", image.size)
alpha_channel.putdata(alpha_data)

# alpha channel을 이용하여 이미지의 배경을 투명하게 만듦
new_image = image.convert("RGBA")
new_image.putalpha(alpha_channel)

# 이미지 파일 저장
new_image.save("transparent_image.png")

색상 범위를 쉽게 주려면?  아래 코드 참고

# 색상 범위 설정
lower_color = (245, 245, 245)  # 검색할 색상 범위의 최소값
upper_color = (255, 255, 255)  # 검색할 색상 범위의 최대값


    if lower_color <= pixel <= upper_color:
        alpha_data.append(0)
    else:  # 그 외의 경우 alpha 값을 255로 설정
        alpha_data.append(255)

'Python' 카테고리의 다른 글

Drawing Plot, 투명 이미지 datauri 생성  (0) 2023.03.20
set에 set 추가? frozenset  (0) 2021.02.24
Jupyter Notebook 소스 복구  (0) 2020.06.16
Docker python venv 패키지 유지  (0) 2020.06.07
딕셔너리에서 키삭제  (0) 2019.12.07
반응형
포인트 리스트를 가지고 그림을 드로잉하고, 이것을 원하는 크기로 Resize 하고, 투명 이미지 datauri 만들기...
pointlist = '[(10,10)(20,20)(40,50)(60,80)][(10,80)(24,70)(40,60)(60,40)]'

# image 필드에 데이터가 없는 목록만 뽑아서 배치 작업을 수행한다.
def to_datauri(sn):
    sn = sn.strip()
    # 정규표현식으로 포맷 문자열에서 점 정보 추출
    point_regex = r"\(([-+]?\d+),([-+]?\d+)\)"
    strokes = sn.replace('[', '')
    strokes = strokes.split(']')
    strokes = [ s for s in strokes if s!='' ]

    # 그래프 그리기
    plt.figure()
    fig, ax = plt.subplots(figsize=(3, 2))
    ax.set_facecolor('none') # 배경 투명
    fig.patch.set_alpha(0) # 배경 투명
    # 축과 눈금 숨기기
    ax.axis('off')

    # 각 획별로 분리하여 그리기
    for stroke in strokes:
        points = re.findall(point_regex, stroke)
        if len(points)==0:
            continue
        x_list = [int(point[0]) for point in points]
        y_list = [int(point[1]) for point in points]
        ax.plot(x_list, y_list, color='black', lw=2)

    plt.gca().invert_yaxis()  # y축 뒤집기

    # 그래프 저장
    buf = io.BytesIO()
    plt.savefig(buf, format='png', bbox_inches='tight')
    buf_resized = buf

    ## resize 작업
    buf.seek(0)
    img = Image.open(buf)
    img_resized = img.resize((150,100), Image.Resampling.LANCZOS)  
    # img_resized = img.resize((150,100), Image.ANTIALIAS)  
    # sampling=Image.ANTIALIAS deprecated 되었다. 버전에 따라 위 둘 중 하나를 사용.
    buf_resized = io.BytesIO()
    img_resized.save(buf_resized, format=img.format)

    # buf대신 buf_resized를 변환
    buf_resized.seek(0)
    data_uri = 'data:image/png;base64,'+base64.b64encode(buf_resized.read()).decode('utf-8')
    plt.close()
    plt.clf()
    plt.close('all')
    img.close()
    img_resized.close()
    buf.close()
    buf_resized.close()

    return data_uri

이 함수를 사용하여 드로잉 데이터를 넣으면, datauri 텍스트가 출력된다.

시작,끝 따옴표를 제거한 텍스트를 복사해서 브라우저 URL창에 넣으면 드로잉된 투명이미지가 나온다.. (드래그해 보면, 선만 움직이는 것을 확인할 수 있다. 배경투명)

y축을 뒤집은 이유는? 모니터 스크린 좌표계에서 보통 좌상단이 (0,0) 이다.  plot에서는 좌하단이 (0,0)이다. 따라서 스크린 좌표계로 보이게 하려고 하였다. 

datauri가 아니라 파일로 저장하려면 plt.close() 전에  plt.savefig('test.png') 로 저장하면 된다.

 

'Python' 카테고리의 다른 글

투명 배경 이미지 만들기  (0) 2023.03.22
set에 set 추가? frozenset  (0) 2021.02.24
Jupyter Notebook 소스 복구  (0) 2020.06.16
Docker python venv 패키지 유지  (0) 2020.06.07
딕셔너리에서 키삭제  (0) 2019.12.07
반응형

파이썬으로 알고리즘 프로그래밍을 하다가 우연히 set에 set을 추가할 일이 있었다.

리스트에 리스트가 추가가 가능한 것 처럼, set도 되지 않을까??

생각해서 해보니, 안 되었다. set에는 immutable 즉, 변경불가한 데이터만 원소로 추가가 가능하였다. 

따라서 set에는 set, list 등 변화가 가능한 것들이 추가가 안 된다.

정말 안되나 하다가...  set을 추가할 방법을 찾았다. 그것은 frozenset.

한 줄 요약: 원소가 되는 set을 frozenset으로 캐스팅하여 사용한다!

더 이상 수정불가능한 immutable 타입으로 캐스팅하면 원소로 넣을 수 있다.

a = set()

# 리스트 추가 안됨.
a.add([1,2,3]) # TypeError: unhashable type: 'list'

# SET 도 추가 안됨.
b = set()
a.add(b) # TypeError: unhashable type: 'set'

# SET을 추가할 수 있는 방법??? FROZENSET!
a.add(frozenset(b)) # ok

 

'Python' 카테고리의 다른 글

투명 배경 이미지 만들기  (0) 2023.03.22
Drawing Plot, 투명 이미지 datauri 생성  (0) 2023.03.20
Jupyter Notebook 소스 복구  (0) 2020.06.16
Docker python venv 패키지 유지  (0) 2020.06.07
딕셔너리에서 키삭제  (0) 2019.12.07
반응형
jupyter_notebook_recover

jupyter notebook source recover

python 노트북 소스파일 복구

jupyter notebook 작업시 주의사항!!!
동일한 소스 코드 창을 여러 개 띄운 경우.
잘못하여 구 버전 창을 보고 저장을 했다면??? OverWrite!!!

신 버전 소스가 날아가는 경험을 하게 된다!!!
이제까지 작업한 것을 날리게 되는 것이다.
실수라고 생각할땐 이미 늦었다… 한숨이 나온다…

혹시나 하여 백업한게 없을까 찾아본다.

방금 작업한 디렉터리에 보니,

.ipynb_checkpoints 폴더가 있다. 
들어가서 동일한 소스코드명을 찾아보았다.
같은 이름의 파일이 있었다.
일단, 복사하여 사본을 만들어 놓고, 열어보았다.

오호… 럭키~~~
다행히도 수동 저장(덮어쓰기) 전에 자동 세이브된 파일이 남아 있었다.
알아두면 긴급시 이렇게 복구할 수 도 있습니다.
^^;

Author: crazyj7@gmail.com

'Python' 카테고리의 다른 글

Drawing Plot, 투명 이미지 datauri 생성  (0) 2023.03.20
set에 set 추가? frozenset  (0) 2021.02.24
Docker python venv 패키지 유지  (0) 2020.06.07
딕셔너리에서 키삭제  (0) 2019.12.07
파이썬 충돌해결 module conflict  (0) 2019.12.01
반응형
Docker_python3.7

Docker ubuntu16.04 + python3.7 venv 패키지유지 환경

ubuntu16.04 에 python 3.7 을 venv 로 가상 환경으로 만들어서 필요할 때 마다 pip 로 패키지를 추가하고 컨테이너 종료시에 사라지지 않고, 유지할 수 있는 도커 이미지를 만들어 보자.

도커 커맨드를 잘 이용하면 금방 만들 수 있을 것이라 생각했지만 쉽지 않았다. 특히 pip로 패키지를 설치한 것을 계속 유지하는 부분과 venv 환경으로 작동하게 하는 부분.
마지막으로 jupyter notebook을 필요한 경우 작동할 수 있도록 하였다.

결론부터

바로 이미지를 받아 실행하고자 한다면 다음을 참고한다.
아래 커맨드를 실행하면, 위 구성한 도커 이미지를 받아 컨테이너를 구동하게 된다. 현재 디렉터리에 py37 이라는 venv 폴더가 생성되고 패키지를 유지하도록 된다.

C:\hub\docker_ubuntu16.04-python3.7>type b.bat
docker run -it -v /c/hub/docker_ubuntu16.04-python3.7/py37:/root/py37 crazyj7/ubuntu16.04-python3.7

C:\hub\docker_ubuntu16.04-python3.7>type j.bat
docker run -it -v /c/hub/docker_ubuntu16.04-python3.7/py37:/root/py37 -p 8888:8888 crazyj7/ubuntu16.04-python3.7 jupyter notebook --ip=0.0.0.0 --port=8888 --allow-root --NotebookApp.token='' --NotebookApp.password=''
  • b.bat : python3.7 구성환경 구동하여 bash 쉘 구동. python을 실행할 수 있다.

image
위 쉘에서 pip로 패키지를 추가할 수 있다. 나중에 다시 컨테이너 구성시에도 패키지가 항상 유지(보관)된다.

생성된 py37 폴더에 소스코드를 작성하고 작업 디렉터리로 사용해도 되고, 별도 공유 폴더를 만들어 볼륨을 연결해서 사용해도 된다.
image
종료시에는 ^C를 두 번 입력하면 종료된다.

image

만드는 과정

아래 github에 내가 작성한 소스가 있다.
https://github.com/crazyj7/docker_ubuntu16.04-python3.7

먼저 나의 작업 디렉터리 구조이다.
c:\hub\docker_ubuntu16.04-python3.7

Dockerfile을 만들어 보자.

Dockerfile

FROM ubuntu:16.04
MAINTAINER crazyj7@gmail.com

RUN apt-get update -y
RUN apt-get upgrade -y
#RUN apt-get install -y build-essential binutils libtool make gcc g++ openjdk-8-jdk git dos2unix vim wget
RUN apt-get install -y build-essential wget vim dos2unix
RUN apt-get install -y zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget software-properties-common
RUN apt-get install -y ocl-icd-opencl-dev
RUN add-apt-repository -y ppa:deadsnakes/ppa
RUN apt-get update -y
RUN apt-get install -y python3.7
RUN apt-get install -y python3.7-venv

# env
WORKDIR /root
ENV HOME /root
SHELL ["/bin/bash", "-c"]

ENV PATH "/root/py37/bin:$PATH"
RUN echo "source /root/py37/bin/activate" >> .bashrc

COPY ./requirements.txt /root/requirements.txt
COPY ./initvenv.sh /root/initvenv.sh

ENTRYPOINT ["/bin/bash", "-c", "/root/initvenv.sh \"$@\"", "--"]
VOLUME /root/py37
CMD ["/bin/bash"]
  • 앞에 RUN은 기본 ubuntu 16.04를 베이스로 하여 시스템에 필요한 패키지를 설치한다. 그리고 python 3.7을 설치하였다.
  • 환경 설정 부분에서 작업 디렉터리를 /root로 하고, 기본 쉘을 bash로 변경. 환경 설정 파일들을 추가.
  • bash 구동 스크립트에 /root/py37의 venv를 활성화 시키도록 하였다.
  • 최초 구성할 기본 python 패키지들을 requirements.txt에 몰아 넣어 구축시 설치되도록 하였다.
  • 그리고 entry point로 initvenv.sh 스크립트를 추가하여 항상 구동하게 하였다. 뒤에 파라미터는 cmd로 별도로 파라미터로 줄 경우 쉘로 구동할 수 있도록 받게 하였다.
  • 볼륨은 /root/py37로 공유 연동 가능하도록 설정.

initvenv.sh

#!/bin/bash

ENVNAME=/root/py37
if [ "$(ls -A $ENVNAME)" ]; then
#	echo Env $ENVNAME exists. skip init.
	source $ENVNAME/bin/activate
else
	echo Env $ENVNAME not exists. init env.
	python3.7 -m venv $ENVNAME
	source $ENVNAME/bin/activate
	pip install --upgrade pip
	pip install -r requirements.txt
fi

if [ $# ]; then
	$*
else
	/bin/bash
fi

py37 폴더 존재여부에 따라 최초 초기화 여부를 수행한다. 별도 지정한 cmd가 있으면 cmd를 수행하도록 하였음. (jupyter notebook 등)

도커 빌드
build.bat

docker build -t crazyj7/ubuntu16.04-python3.7 .

Author: crazyj7@gmail.com

'Python' 카테고리의 다른 글

set에 set 추가? frozenset  (0) 2021.02.24
Jupyter Notebook 소스 복구  (0) 2020.06.16
딕셔너리에서 키삭제  (0) 2019.12.07
파이썬 충돌해결 module conflict  (0) 2019.12.01
파이썬 개발환경/가상환경구축  (0) 2019.12.01
반응형
remove dict key

Remove Dict Key

딕셔너리에서 키를 안전하게 삭제하는 방법.
샘플로 다음과 같은 dictionary가 있다고 하자.

dic = dict()
dic['apple']=100
dic['banana']=200
dic['orange']=300
# 간단하게 하면 
dic = {'apple':100, 'banana':200, 'orange':300 }

위에서 apple를 지워보자.

del 로 삭제할때…

만약 키가 없으면 어떻게 될까?
del dic['mango']
KeyError!
안전하게 삭제하려면

# 1안
if 'mango' in dic:
	del dic['mango']

위와 같이 존재하는지 검사한다음, 있으면 삭제하는 것으로 할 수 있다.
매번 이렇게 if를 해 주는게 귀찮긴 한데…
일단 삭제를 시도하고, 에러나면 에러 처리하도록 할 수 있다.

# 2안
try:
	del dic['mango']
except KeyError:
	pass

pop으로 삭제할때…

dict()의 pop()을 사용하면 값을 꺼내올 수 도 있고, 해당 키가 삭제되는 효과도 있다. 이것도 키가 없다면? 에러가 발생할 것 같은데…
del과 마찬가지로 KeyError 예외가 발생한다.
즉, 해결방법은 1안과 2안처럼, 존재체크를 하거나 예외 처리를 할 수 있다.

dic.pop('mango')  # mango not found -> KeyError!!!

다른 방법은???
pop()의 다른 형태로는 파라미터에 값을 추가하면 키가 없을 때 디폴트 값을 리턴하도록 하는 기능이 있다. 이 방식을 사용하면 쉽게 안전한 삭제가 가능하다.

# 3안
dic.pop('mango', None) # if not found -> None. (no error!)

이제 있을지 모르는 키를 삭제하려면 pop( [key], None)을 사용하자.

dic.pop('apple', None)

위와 같이 하면 해당 키가 존재하는지 체크를 하거나 except 처리를 할 필요가 없다.

Author: crazyj7@gmail.com

'Python' 카테고리의 다른 글

Jupyter Notebook 소스 복구  (0) 2020.06.16
Docker python venv 패키지 유지  (0) 2020.06.07
파이썬 충돌해결 module conflict  (0) 2019.12.01
파이썬 개발환경/가상환경구축  (0) 2019.12.01
진법 표현 및 수 스트링 변환  (0) 2019.11.24
반응형
module_conflict

Python module conflict error

파이썬으로 외부의 여러 패키지들을 깔고 테스트하다 보면 가끔씩 충돌이 발생하여 이전에는 잘 되던 것들이 꼬이게 된다.
막상 경험해 보면 복구하는 것이 쉽지 않고 점점 더 꼬이는 악순환이 발생하여 나중에는 파이썬을 다시 설치하게 된다.
어떻게 복구하는 방법이 없을까?

먼저 가끔씩 현상황을 기록해 두자.

pip freeze > requirements.txt

  • 위와 같이 freeze 옵션을 사용하면 현재 설치된 모든 모듈의 버전들이 기록된다. 보통은 requirements.txt 로 많이 기록된 것을 볼 수 있다.
  • 나중에 저 목록을 한 번에 설치가 가능하다. install -r 옵션을 사용한다.

마지막에 설치/변경된 모듈들을 삭제.

  • 마지막에 설치/변경된 모듈들을 하나씩 삭제해 올라간다.
  • 그런데 마지막순으로 설치된 모듈들이 무엇인지 기억이 나지 않는다.

현재 python 환경(env)의 설치 경로들을 확인.
conda env list
python --version
코드로 라이브러리 위치 확인

import os, inspect
inspect.getfile(os)
'opt/anacoda3/lib/python3.7/os.py'

import web3
inspect.getfile(web3)
'/home/crazyj/myvenv/lib/python3.7/site-packages/web3/__init__.py'
  • 위와 같이 패키지 설치 경로를 확인한 다음 디렉터리로 가서 날짜를 확인한다.

ls -ltr : 마지막에 나온것들이 최근 설치/업데이트된 패키지들. (last modified time 기준으로 역순소팅)
위 마지막 패키지들을 pip uninstall로 하나씩 지워나가면서 테스트 한다.

모든 패키지 삭제하기

이것도 저것도 안된다면, 백업받은 패키지 목록대로 돌리기 위해 전부 삭제하고 다시 설치하자.

pip freeze | xargs pip uninstall -y
또는
pip freeze > requirements.txt
pip uninstall -r requirements.txt -y

패키지 목록 한번에 설치하기

pip install -r requirements.txt

Author: crazyj7@gmail.com

'Python' 카테고리의 다른 글

Docker python venv 패키지 유지  (0) 2020.06.07
딕셔너리에서 키삭제  (0) 2019.12.07
파이썬 개발환경/가상환경구축  (0) 2019.12.01
진법 표현 및 수 스트링 변환  (0) 2019.11.24
크롤링 BeautifulSoup 요약  (1) 2019.11.06
반응형
virtualenv

Python Virtual Env / Conda Env

파이썬 가상환경. 여러가지 버전의 파이썬을 동시에 사용할 수도 있고, 목적에 따라 가상환경을 만들어 따로 운영할 수 있다.
딥러닝용, 그래픽용, 서버 개발용 등등

virtual env 환경 생성

  • 설치된 버전 확인

    • pip --version
    • pip3 --version
    • pip install virtualenv
    • pip3 install virtualenv
  • 현재 폴더 아래 가상환경 생성. 주어진 환경이름으로 폴더가 생성된다.

    • virtualenv 이름 --python=pyton버전
    • virtualenv py37 --python=python3.7
    • 윈도우의 경우 안 된다면 --python=[python.exe fullpath]로 한다. 생략하면 현재 연결된 path의 python 버전으로 자동 인식.

가상환경으로 들어가기

  • source ./py37/bin/activate
  • 위 커맨드를 입력하여 실행하면 잘 되는데, shell script로 만들어 실행하면 작동하지 않는다.
  • 리눅스에서는 로그인 계정의 .bashrc에 alias=‘source …’ 으로 만들어 사용하자.
  • 윈도우는 source 대신 call을 사용하여 배치 파일로 만들면 된다.
    • py37.bat
      call c:\devtools\py37\scripts\activate
  • 작업이 끝나면 deactivate 로 빠져나간다.

가상 환경별로 원하는 패키지 설치

  • 가상환경 사용하다가 freeze로 requirements.txt를 생성해 주자. (나중에 한 번에 필요 모듈 설치시 편리하다.)
pip list
pip freeze > requirements.txt
pip install -r requirements.txt
pip install numpy matplotlib ipykernel jupyter requests

Jupyter Notebook/Lab에 venv 등록

  • pip install ipykernel
  • jupyter에 가상 환경 등록
python -m ipykernel install --user --name py37 
       --display-name py37

(–display-name은 생략해도 된다.)

Jupyter Notebook 실행하여 확인

  • jupyter notebook
    파일 목록 오른쪽 메뉴에 New에 환경이름이 추가되었는지 확인한다. 소스 편집기에서 Kernel에서 Change하여 원하는 커널 환경을 선택한다.
  • 모듈 로딩 경로가 맞는지 최종 확인
    • 설치한 패키지명을 import하여 경로를 확인한다.
    • import web3, inspect
    • inspect.getfile(web3)
	'/storage/crazyj/py37/lib/python3.7/site-packages/web3/__init__.py'
  • Jupyter notebook 기본 브라우저를 크롬으로 변경
설정 파일이 없을 경우 최초 생성
jupyter notebook --generate-config

편집
notepad %userprofile%\.jupyter\jupyter_notebook_config.py

수정 내용
c.NotebookApp.browser = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'

  • Jupyter notebook 암호 설정
$ jupyter notebook password
암호 입력

Conda (Anaconda) env

virtualenv 말고 conda로도 만들 수 있다.

가상 환경 전환

  • 현재 존재하는 가상 환경 목록
    conda env list

  • 가상환경 활성화
    conda activate [가상환경명]
    또는
    activate [가상환경명]

  • 가상환경 비활성화
    conda deactivate

가상환경 생성

conda create --name [가상환경명] python=3.7.3 tensorflow keras
파이썬 버전을 명시해 주고, 뒤에 추가할 패키지명들을 옵션으로 적어줄 수 있다.

가상환경 삭제

conda remove --name [가상환경명] --all

Author: crazyj7@gmail.com

'Python' 카테고리의 다른 글

딕셔너리에서 키삭제  (0) 2019.12.07
파이썬 충돌해결 module conflict  (0) 2019.12.01
진법 표현 및 수 스트링 변환  (0) 2019.11.24
크롤링 BeautifulSoup 요약  (1) 2019.11.06
크롤링(Crawl) 2편  (2) 2019.10.27
반응형
int_hex_str_bin

진법 표현 int hex str bin

파이썬에서 진법 표현 방법을 알아보자.

여러가지 진법 수 표현

기본적으로 숫자를 쓰면 10진수이다. 수 앞에 진법표기 접두어를 쓰면 해당 진법의 수로 인식을 한다. (숫자 0 다음에 문자 o/x/b)

  • 8진수 : 0o
  • 16진수 : 0x
  • 2진수 : 0b
i10 = 1234
i8 = 0o1234
i16 = 0x1234
i2 = 0b1010
print(i10, i8, i16, i2)
1234 668 4660 10
  • 그냥 print로 출력하면 10진수로 변환하여 출력해 준다.

여러가지 진법 수를 문자열로 변환

  • str, oct, hex, bin 함수를 사용한다.
i10 = 1234
print( str(i10), oct(i10), hex(i10), bin(i10))
1234 0o2322 0x4d2 0b10011010010

i16 = 0x4d2
print( str(i16), oct(i16), hex(i16), bin(i16))
1234 0o2322 0x4d2 0b10011010010
동일한 출력결과
  • 파라미터는 10진수일 필요없다. 아무거나 결국엔 십진수로 변수에 값이 할당되므로 같은 결과가 나온다.

포맷 스트링을 사용한 문자열 변환

  • format 함수로 사용하여 수를 진법 스트링으로(b, o, x) 변환한다.
  • 소문자면 소문자로 대문자면 대문자로 출력된다.
  • 앞에 #(샵)을 붙이면 prefix 도 출력한다.
print( format(1234, 'x'), format(1234, 'X'), format(1234, '#x'), format(1234, '#X') )
4d2 4D2 0x4d2 0X4D2
  • 출력 포맷 스트링을 사용하면 원하는 형태로 prefix를 줄 수 있다. (단, %방식은 %b를 지원하지 않는다.)
print( '%x %X 0x%x  '%(1234,1234,1234) )
4d2 4D2 0x4d2
print( '%d %o %x' % (1234,1234,1234) )
1234 2322 4d2
print( '{0:d} {0:o} {0:x} {0:b}'.format(1234,1234,1234,1234) )
1234 2322 4d2 10011010010

여러가지 진법 수 문자열을 수로 변환

print( int('0o2322', 8), int('0x4d2', 16), int('0b10011010010', 2) )
1234 1234 1234
  • 간단하게 스트링을 int로 타입 캐스팅하는데 기본이 10진수이고, 다른 진법인 경우는 진법을 명시를 해 주면 된다.

Author: crazyj7@gmail.com

'Python' 카테고리의 다른 글

파이썬 충돌해결 module conflict  (0) 2019.12.01
파이썬 개발환경/가상환경구축  (0) 2019.12.01
크롤링 BeautifulSoup 요약  (1) 2019.11.06
크롤링(Crawl) 2편  (2) 2019.10.27
웹 크롤링 Crawl 1편  (0) 2019.10.24
반응형
BeautifulSoup

BeautifulSoup

HTML, XML 문서를 구조적으로 분석하여 원하는 데이터를 쉽게 추출하게 도와주는 모듈.
bs4 (버전4)를 사용하기를 권장함.

간단하게 요약

  • 설치
    pip install beautifulsoup4
    pip install lxml
from bs4 import BeautifulSoup
soup = BeautifulSoup(html) # html 문서를 파싱한다. (string, network connection 등)
print(soup.prettify())  # HTML을 이쁘게 출력한다.

soup.title # <title>hello</title>
soup.title.string # hello
soup.title.parent.name # head
soup.p # <p class="tt"><b>hi</b></p>
soup.p['class']  # tt
soup.a  # <a class='sister' href='http://abc.com/el' id='link1'>El</a>

soup.find_all('a') # [<a>..</a>, <a>...</a>, <a>..</a> ]

soup.find(id='link3') # <a href="http://abc.com/ea', id='link3'>EA</a>

for link in soup.find_all('a'):
	print(link.get('href')) # http://....

soup.get_text() # hello hi El....
  • BeautifulSoup(markup, parser)
    • markup : html 문서 스트링, html 문서 파일핸들, 네트웍 커넥션 등
    • parser : ‘html.parser’ 또는 ‘lxml’
    • lxml이 더 빠르고 관대함. xml도 지원.
  • 태그 출력은 preffify() : 이쁘게 출력한다. soup.prettify()
  • 그대로 출력하려면 str()로 타입캐스팅. str(soup)
  • 태그는 .태그명으로 접근한다. 기본적으로 이름이 있고 .name 으로 알 수 있으며 name을 변경하면 문서에도 반영된다.
    • soup.p = “div”
  • 태그의 속성은 [속성]으로 접근한다. 또는 get()으로 접근할 수 있다. 속성은 .attrs로 알 수 있다.
    • soup.p.attrs # 속성목록 조회 {‘class’:‘bold’}
    • soup.p[‘class’] : 속성을 구한다. 키가 없으면 KeyError 발생
    • soup.p.get(‘class’) : 위와 같지만 키가 없으면 None리턴으로 존재여부 체크를 할 수 있음.
    • 속성값이 여러개면 리스트로 반환된다.
  • 태그의 속성 수정
    • soup.p[‘class’]=‘verybold’
    • soup.p[‘id’]=1
    • soup.p
      <p class="verybold" id="1">
    • del soup.p[‘class’] # 속성 삭제
  • 스트링 변경
    • soup.p.string.replace_with(“new text”)
  • 스트링 추출 (string vs text)
    • soup.p.string : p태그 내의 스트링. 주의! 내부에 순수하게 스트링만 존재해야함. 아니면 None. (태그가 있어도 안됨.)
    • soup.p.text 또는 soup.p.get_text() : 내부의 텍스트를 전체 가져옴.
  • 태그의 자손. 리스트로 리턴한다.
    • soup.p.contents : 리스트로 가져온다.

find / find_all

태그를 찾는다. 클래스나 아이디로도 검색가능. find는 한 개를 찾고 find_all은 복수개를 찾는다. find_all은 리스트로 리턴한다.

  • find_all(“title”) : title태그를 모두 찾는다.
  • find_all(“p”, “title”) : p태그 중 class가 title인 태그를 모두 찾는다.
  • find_all(id=“link2”) : ID로 찾는다.
  • find_all(class_=re.compile(“itl”)) : 클래스명에 itl이 들어간 태그들 모두 추출
  • find_all(text=“elise”) : 문자열 찾기
  • find_all(“a”, text=“elise”) : 태그내의 문자열로 태그 찾기
  • 정규식 지원
    • soup.find_all( re.compile("^b")) : b로 시작하는 태그 모두 추출. ( b, body 등)
  • 여러 태그 추출도 가능
    • soup.find_all([“a”, “b”]) : 리스트로 주면 리스트내의 태그들을 모두 찾는다.
    • find_all(“a”, limit=2) : 최대 2개만 찾는다.
    • find_all(“title”, recursive=False) : 1뎁스(직계차일드)만 검색함. 예를 들면 soup.html.에서 위와 같이 찾으면 [] 리턴(not found.)
    • find_all() 대신 ()만 사용해도 같다. (함수이름 생략) 예를 들면 soup.title.find_all(text=True)는 soup.title(text=True) 와 동일.
    • find()는 처음 발견된 한 개만 리턴. (find_all에서 limit=1을 주면 동일한데, 리스트가 아닌 스트링(태그객체)으로 리턴.)
    • Not Found인 경우, find()는 None 리턴. find_all()은 [] 리턴.

find_parent/ find_parents

  • find / find_all의 반대. 상위계층으로 올라가면서 찾는다.
  • a_string = soup.find(text=‘top10’) # u’top10’
  • a_string.find_parents(“a”) # [ a태그들을 가져옴 ]
  • a_string.find_parent(“p”) # p태그를 가져옴.

select

  • soup.select(선택자) : css 선택자로 검색한다. 그냥 태그를 쓰면 태그 검색. 항상 리스트로 리턴함.
  • soup.select(‘title’)
  • soup.select(“body a”)
  • soup.select(“html head title”)
  • soup.select(“head > title”) : 헤드내부에 1단계 뎁스에서 title 찾기.
  • 클래스 찾기 : soup.select(".sister") 또는 soup.select("[class~=sister]")
  • ID로 찾기 : soup.select("#link1")
  • 속성으로 찾기
    • soup.select(‘a[href=“http://abc.com/elise”]’)
    • soup.select(‘a[href^=“http://abc.com/”]’) : 이것으로 시작하는 링크들. 끝나는 링크는 href$를 사용.

get_text

  • 텍스트 부분만 모두 추출한다. 하나의 스트링을 만들어 리턴.
  • .text로 해도 된다.

strings/stripped_strings

  • 둘 다 스트링들만 리스트로 추출하는 건데, stripped_strings는 필요없는 것을 제거함.
  • 줄바꿈, 공백 등 필요없는 것들에 제거한 스트링 리스트를 리턴. [text for text in soup.stripped_strings]

Author: crazyj7@gmail.com

'Python' 카테고리의 다른 글

파이썬 개발환경/가상환경구축  (0) 2019.12.01
진법 표현 및 수 스트링 변환  (0) 2019.11.24
크롤링(Crawl) 2편  (2) 2019.10.27
웹 크롤링 Crawl 1편  (0) 2019.10.24
인코딩에러 cp949  (1) 2019.10.02

+ Recent posts