본문 바로가기
개발자모드/혼자공부하는파이썬

[파이썬#21][고급] 외부 모듈 (모듈 설치 pip install, BeautifulSoup, Flask)

by 요니L 2022. 7. 22.

 

 


외부 모듈

파이썬이 기본적으로 제공해 주는 것이 아니라, 다른 사람들이 만들어 배포하는 모듈을 외부 모듈(External Module)이라고 부른다. 외부 모듈 중 BeautifulSoup과 Flask를 설치한 후 활용하는 방법을 알아보겠다.

 

파이썬 도서를 둘러보면 사이킷-런, 텐서플로우, 장고, 플라스크, 넘파이 등이라고 적혀 있는 책을 볼 수 있는데 이러한 책들은 모두 다른 사람들이 만들어서 제공해 주는 외부 모듈에 관한 책이다. 이번에 살펴보는 BeautifulSoup과 Flask 모듈은 이 모듈만으로도 책  한 권이 나오는 모듈들이다. 여기서는 기본적인 방법만 알아보겠다.

 


모듈 설치하기

다음과 같이 입력해서 외부 모듈을 설치한다. 외부 모듈은 [window]+[r] 키를 눌러 프로그램 실행창을 띄우고 [cmd]를 입력하면 나타나는 명령 프롬프트 창에서 실행해야 한다.

 

pip install 모듈 이름

BeautifulSoup 모듈을 설치한다면 다음과 같이 입력해서 설치하면 된다. 

>> pip install beautifulsoup4

D:\app\python>pip install beautifulsoup4
Collecting beautifulsoup4
  Downloading beautifulsoup4-4.11.1-py3-none-any.whl (128 kB)
     ---------------------------------------- 128.2/128.2 KB 2.5 MB/s eta 0:00:00
Collecting soupsieve>1.2
  Downloading soupsieve-2.3.2.post1-py3-none-any.whl (37 kB)
Installing collected packages: soupsieve, beautifulsoup4
Successfully installed beautifulsoup4-4.11.1 soupsieve-2.3.2.post1
WARNING: You are using pip version 22.0.4; however, version 22.1.2 is available.
You should consider upgrading via the 'C:\Users\이현민\AppData\Local\Programs\Python\Python310\python.exe -m pip install --upgrade pip' command.

D:\app\python>

 

pip는 정말 많은 기능을 가지고 있다. 특정 버전의 모듈을 설치하고나 설치한 모듈을 제거하는 기능 모두 지원하는데 이와 같은 내용은 pip 문서를 참고하면 된다.

 

[pip 패키지 설치 문서]

https://pip.pypa.io/en/stable/user_guide/#installing-packages

 

User Guide - pip documentation v22.1.2

python -m pip python -m pip executes pip using the Python interpreter you specified as python. So /usr/bin/python3.7 -m pip means you are executing pip for your interpreter located at /usr/bin/python3.7. py -m pip py -m pip executes pip using the latest Py

pip.pypa.io

 


모듈 찾아보기

방금 설치한 BeautifulSoup 모듈은 웹 페이지를 분석할 때 사용하는 모듈이다. 

 

그렇다면 필요한 모듈은 어떻게 찾을 수 있을까?

 

방법1) 파이썬 책 구매

방법2) 파이썬 커뮤니티에 가입 (예, 페이스북 파이썬 그룹)

방법3) 구글에서 검색 (예, Python Beautiful Soup → Python + 내가 원하는 것 )

 

↘웹 프로그래밍: Django 또는 Flask

↘기계 학습: scikit-learn(사이킷-런) 또는 keras

스크레이핑: requests 또는 Beautiful Soup

↘영상 분석: cv2 또는 pillow

 


BeautifulSoup 모듈 (라이브러리)

BeautifulSoup 모듈은 굉장히 유명한 파이썬의 웹 페이지 분석 모듈이다. 구글에서 'Python Beautiful Soup'으로 검색하면 가장 위에 BeautifulSoup 모듈의 공식 홈페이지가 나온다. 여기에 접속하면 관련된 문서를 살펴볼 수 있다.

 

[BeautifulSoup 문서]

https://www.crummy.com/software/BeautifulSoup/bs4/doc/

 

Beautiful Soup Documentation — Beautiful Soup 4.9.0 documentation

Non-pretty printing If you just want a string, with no fancy formatting, you can call str() on a BeautifulSoup object, or on a Tag within it: str(soup) # ' I linked to example.com ' str(soup.a) # ' I linked to example.com ' The str() function returns a str

www.crummy.com

 

BeautifulSoup을 사용해서 기상청의 날씨 정보를 가져와 출력해 보자.

 

[기상청의 전국 날씨 정보]

https://www.weather.go.kr/w/index.do

 

기상청 날씨누리

기상청 날씨누리

www.weather.go.kr

 

bs4 모듈의 BeautifulSoup 함수를 매개변수로 HTML 문자열과 "html.parser"라는 문자열을 넣으면 BeautifulSoup이라는 특수한 객체를 리턴한다. 

 

BeautifulSoup 모듈로 날씨 가져오기

# 모듈을 읽어 들인다.
from urllib import request
from bs4 import BeautifulSoup

# urlopen() 함수로 기상청의 전국 날씨를 읽는다

# BeautifulSoup을 사용해 웹페이지를 분석
soup = BeautifulSoup(target, "html.parser")

# location 태그를 찾는다.
for location in soup.select("location"):
    # 내부의 city, wf, tmn, tmx 태그를 찾아 출력한다.
    print("도시: ", location.select_one("city").string)
    print("날씨: ", location.select_one("wf").string)
    print("최저기온: ", location.select_one("tmn").string)
    print("최고기온: ", location.select_one("tmxp").string)


[실행결과]

PS D:\app\python\bs> python beautiful_weather.py
C:\Users\XXX\AppData\Local\Programs\Python\Python310\lib\site-packages\bs4\builder\__init__.py:545: XMLParsedAsHTMLWarning: It looks like you're parsing an XML document using an HTML parser. If this 
really is an HTML document (maybe it's XHTML?), you can ignore or filter this warning. If it's XML, you should know that using an XML parser will be more reliable. To parse this document as XML, make sure you have the lxml package installed, and pass the keyword argument `features="xml"` into the BeautifulSoup constructor.
  warnings.warn(
도시:  서울
날씨:  흐림
최저기온:  24
최고기온:  28
...
도시:  제주
날씨:  구름많음
최저기온:  25
최고기온:  32
도시:  서귀포
날씨:  구름많음
최저기온:  24
최고기온:  30
PS D:\app\python\bs> 

 

이를 기반으로 태그를 여러 개 선택할 때 select() 함수, 하나만 선택할 때는 select_one() 함수를  사용해서 원하는 값을 추출한다. 현재 기상청의 xml 파일을 확인하면 다음과 같다. 

https://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp?stnId=108

 

지역이 표기된 location을 찾고, location 내부에 있는 city, wf, tmn, tmx 태그의 내용을 추출한다. 

 

★ BeautifulSoup은 대문자를 사용했다. 왜냐하면 BeautifulSoup()은 단순한 함수가 아니라 클래스의 생성자이기 때문이다. 클래스 편에서 자세히 살펴보자~!

 


Flask 모듈 (프레임워크)

(문서확인) 구글링: Python Flask GitHub

일반적으로 파이썬으로 웹 개발을 할 때는 Django(장고) 또는 Flask(플라스크) 등의 모듈을 사용한다. Django는 매우 다양한 기능을 제공하는 웹 개발 프레임워크이고, Flask는 작은 기능만을 제공하는 웹 개발 프레임워크이다.

 

▷ Flask 모듈 설치

pip install flask

D:\app\python>pip install flask
Collecting flask
  Downloading Flask-2.1.3-py3-none-any.whl (95 kB)
     ---------------------------------------- 95.6/95.6 KB 5.7 MB/s eta 0:00:00
Collecting itsdangerous>=2.0
  Downloading itsdangerous-2.1.2-py3-none-any.whl (15 kB)
Collecting click>=8.0
  Downloading click-8.1.3-py3-none-any.whl (96 kB)
     ---------------------------------------- 96.6/96.6 KB 5.8 MB/s eta 0:00:00
Collecting Werkzeug>=2.0
  Downloading Werkzeug-2.1.2-py3-none-any.whl (224 kB)
     ---------------------------------------- 224.9/224.9 KB 6.9 MB/s eta 0:00:00
Collecting Jinja2>=3.0
  Downloading Jinja2-3.1.2-py3-none-any.whl (133 kB)
     ---------------------------------------- 133.1/133.1 KB 7.7 MB/s eta 0:00:00
Collecting colorama
  Downloading colorama-0.4.5-py2.py3-none-any.whl (16 kB)
Collecting MarkupSafe>=2.0
  Downloading MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl (17 kB)
Installing collected packages: Werkzeug, MarkupSafe, itsdangerous, colorama, Jinja2, click, flask
Successfully installed Jinja2-3.1.2 MarkupSafe-2.1.1 Werkzeug-2.1.2 click-8.1.3 colorama-0.4.5 flask-2.1.3 itsdangerous-2.1.2
WARNING: You are using pip version 22.0.4; however, version 22.1.2 is available.
You should consider upgrading via the 'C:\Users\이현민\AppData\Local\Programs\Python\Python310\python.exe -m pip install --upgrade pip' command.

D:\app\python>

 

<설치 확인 방법>

python을 입력하고 import flask를 입력했을 때 아무 반응도 안 나타나면 설치 성공이다. 확인 후 exit()로 빠져나오면 된다.

PS D:\app\python\exmd> python
Python 3.10.5 (tags/v3.10.5:f377153, Jun  6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import flask
>>> exit()
PS D:\app\python\exmd> 

 

▷ Flask 모듈 사용하기

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1>Hello World!!</h1>"

@app.route() 라고 되어 있는 부분은 데코레이터라고 부른다. 

 

Flask는 코드를 실행하는 방법이 약간 특이한데, 다음과 같이 두 줄을 명령 창 또는 Powershell에 입력해서 실행한다.

set FLASK_APP=파일이름.py # 환경변수 설정(터미널 실행하고 한 번만 실행)
flask run  # flask 명령어

[실행결과1] 오류발생

D:\app\python\exmd>flask run
 * Serving Flask app 'flask_basic.py' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)

"프로덕션 환경에서 개발 서버를 사용하지 마십시오"라는 오류가 발생한다.

 

☆해결방법

FLASK_ENV 환경변수를 development로  설정하여 개발모드를 활성화한다. 

set FLASK_APP=파일이름.py
set FLASK_ENV=development
flask run

[실행결과2]

D:\app\python\exmd>set FLASK_APP=flask_basic.py
D:\app\python\exmd>set FLASK_ENV=development
D:\app\python\exmd>flask run
 * Serving Flask app 'flask_basic.py' (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 486-139-056

 

코드를 실행하고 웹 브라우저에서 http://127.0.0.1:5000 에 접속하면 아래와 같이 출력된다.

웹 브라우저와 통신할 수 있는 웹 서버가 간단하게 만들어진 것이다.

 

Flask 모듈은 @app.route(경로)처럼 <경로>에 들어갈 때 실행할 함수를 지정하는 형태로 사용한다. 이때 함수에서 리턴하는 문자열을 기반으로 HTML 파일을 웹브라우저에 제공해 준다.

 

<경로>에 들어갈 때마다 함수가 실행되므로, 이전에 만들었던 BeautifulSoup 스크래핑을 실행하는 코드를 만든다면 다음과 같다. 단지 이전의 코드를 hello() 함수 내부에 넣고, 문자열을 리턴하도록 바꾸었을 뿐이다.

 

▷ BeautifulSoup 스크레이핑 실행하기

# 모듈을 읽어 들인다
from flask import Flask
from urllib import request
from bs4 import BeautifulSoup


# 웹 서버를 생성한다.
app = Flask(__name__)
@app.route("/")

def hello():
    # urlopen() 함수로 기상청의 전국 날씨를 읽는다. (구글링: 기상청 rss)

    # BeautifulSoup를 사용해 웹 페이지를 분석
    soup = BeautifulSoup(target, "html.parser")

    # location 태그를 찾는다.
    output = ""
    for location in soup.select("location"):
        #내부의 city, wf, tmn, tmx 태그를 찾아 출력
        output += "<h3>{}</h3>".format(location.select_one("city").string)
        output += "날씨: {}<br/>".format(location.select_one("wf").string)
        output += "최저/최고기온: {}/{}".format(\
                location.select_one("tmn").string,\
                location.select_one("tmx").string,\
            )
       
        output += "<hr/>"
        return output


[실행결과] vs code 터미널에서는 안되고, cmd 창에서만 되네 뭐지;;

D:\app\python\exmd>set FLASK_APP=beautiful_flask.py
D:\app\python\exmd>set FLASK_ENV=development
D:\app\python\exmd>flask run
 * Serving Flask app 'beautiful_flask.py' (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 486-139-056
C:\Users\xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\bs4\builder\__init__.py:545: XMLParsedAsHTMLWarning: It looks like you're parsing an XML document using an HTML parser. If this really is an HTML document (maybe it's XHTML?), you can ignore or filter this warning. If it's XML, you should know that using an XML parser will be more reliable. To parse this document as XML, make sure you have the lxml package installed, and pass the keyword argument `features="xml"` into the BeautifulSoup constructor.
  warnings.warn(
127.0.0.1 - - [21/Jul/2022 10:08:00] "GET / HTTP/1.1" 200 -

 

 

 

 

 


라이브러리와 프레임워크

라이브러리와 프레임워크의 구분은 제어 역전(IoC: Inversion of Control) 여부에 따라 달라진다.

구분 설명
라이브러리(library) 정상적인 제어를 하는 모듈
프레임워크(framework) 제어 역전이 발생하는 모듈

 

 

↘ 라이브러리

제어 역전이란 쉽게 말해 제어가 역전되어 있다는 뜻이다. 따라서 '역전되지 않은 정상적인 제어'가 무엇인지 알아야 제어 역전을 이해할 수 있다. 

 

다음 코드는 math 모듈이다. math 모듈은 모듈 내부의 기능을 '개발자'가 직접 호출했다. 개발자가 모듈의 기능을 호출하는 형태의 모듈을 라이브러리라고 한다. 

 

▷ 정상적인 제어 = 라이브러리

# 모듈을 읽어 들인다.
from math import sin, cos, tan, floor, ceil

# sin, cos, tan을 구한다.
print("sin(1): ", sin(1))
print("cos(1): ", cos(1))
print("tan(1): ", tan(1))

# 내림과 올림을 구한다.
print("floor(2.5): ", floor(2.5))
print("ceil(2.5): ", ceil(2.5))

 

 

↘ 프레임워크

Flask 모듈을 사용한 코드를 살펴보면 내부에 함수 정의만 했지 직접적으로 무언가 진행하는 코드는 단 하나도 없다. 

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1>Hello World!! 안녕!!</h1>"
D:\app\python\exmd>flask run
 * Serving Flask app 'beautiful_flask.py' (lazy loading)
 * Environment: development
 * Debug mode: on
 * Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 486-139-056

위의 글자는 우리가 출력했던 적이 없다. 그렇다면 어디에서 출력된 것일까?

바로 Flask 모듈 내부이다. 우리가 작성한 코드를 직접 실행하지 않았다. Flask 모듈이 제공하는 명령어를 실행하면 Flask가 내부적으로 서버를 실행한 뒤 지정한 파일을 읽어 들여 적절한 상환에 스스로 실행하게 된다. 이처럼 모듈이 개발자가 작성한 코드를 실행하는 형태의 모듈을 프레임워크라고 부른다. 

 

 


(좀 더 알아보기) 함수 데코레이터

파이썬에서는 데코레이터라는 기능이 있다. 앞에서 <Flask 모듈>에서 잠깐 언급하면서 @app.route() 형태의 코드를 보았다. 이렇듯 @로 시작하는 구문을 파이썬에서는 데코레이터라고 부른다. 데코레이터는 '꾸며 주는 것'이라는 의미인데, 프로그래밍에서는 무엇을 꾸민다는 것일까?

 

데코레이터는 만드는 방법에 따라 크게

☞ 함수 데코레이터

 클래스 데코레이터

로 나눌 수 있다. 여기서는 함수 데코레이터만 살펴보겠다.

 

 

함수 데코레이터의 기본

함수 데코레이터는 함수에 사용되는 데코레이터이다. 이 말은 대상 함수의 앞뒤에 꾸밀 부가적인 내용을, 혹은 반복할 내용을 데코레이터로 정의해서 손쉽게 사용할 수 있도록 한 것을 말한다. 

 

▷ 함수 데코레이터의 기본

def test(function):
    def wrapper():
        print("인사가 시작되었습니다.")
        function()
        print("인사가 종료되었습니다.")
    return wrapper

# 데코레이터를 붙여 함수를 만든다.
@test
def hello():
    print("hello~!")

# 함수를 호출
hello()

[실행결과]

PS D:\app\python> python func_deco.py
인사가 시작되었습니다.
hello~!
인사가 종료되었습니다.

test() 함수에서 wrapper() 함수를 리턴하므로, 최종적으로 hello에 함수가 들어가 hello() 형태로 호출할 수 있다. 간단한 내용을 굳이 왜 이렇게 복잡하게 작성하냐고 할 수 있겠지만, 데코레이터를 사용하면 functools라는 모듈을 사용할 수 있고, 함수 데코레이터를 사용할 때 매개변수 등을 전달할 수 있어 반복되는 구문이 많아질 때 소스의 가독성도 높이고 매우 유용하게 사용할 수 있다. 

# 모듈을 읽어 들인다.
from functools import wraps

# 함수로 데코레이션을 생성
def test(function):
    @wraps(function)
    def wrapper(*arg, **kwargs):
        print("인시가 시작되었습니다.")
        function(*arg, **kwargs)
        print("인사가 종료되었습니다.")
        return wrapper

 

※ 다른 프로그래밍 언어에서는 @ 기호가 어노테이션(annotation)으로 사용되어 비슷한 것이라고 생각할 수 있는데, 전혀 다른 기능이다.

 


연습문제

(연습문제 347p-1)

Q. 구글 검색으로 "python prime module"이라고 치면 파이썬에서 소수를 구하는 모듈을 찾아보자. prime, primenumbers, pyprimes, pyprimesieve 등 다양한 모듈이 나올 것이다. 적당한 것을 선택하여 100~1000 사이에 있는 소수가 몇 개인지 구해보자.

 

▷ primePy 설치 (>> pip install primePy)

PS D:\app\python> pip install primePy
Collecting primePy
  Downloading primePy-1.3-py3-none-any.whl (4.0 kB)
Installing collected packages: primePy
Successfully installed primePy-1.3
WARNING: You are using pip version 22.0.4; however, version 22.1.2 is available.
You should consider upgrading via the 'C:\Users\이현민\AppData\Local\Programs\Python\Python310\python.exe -m pip install --upgrade pip' command.
PS D:\app\python> 

 

소수의 개념

1과 자기 자신으로만 나누어 떨어지는 숫자를 소수라고 한다. 

 

from primePy import primes

# 10까지의 소수 리스트
primes_to_100 = primes.upto(100)
print("100까지의 소수: ", primes_to_100)

# 100까지의 소스 리스트
prime_to_1000 = primes.upto(1000)
print("1000까지의 소수: ", prime_to_1000)

sum = 0
i = 0
oList = []
for item in prime_to_1000:
    if item >= 100:
        oList.append(item)

print("100~1000사이의 소수: ", oList)
print("100~1000사이의 소수개수: ", len(oList))

[실행결과]

PS D:\app\python> python 347p-1.py
100까지의 소수:  [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
1000까지의 소수:  [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 
569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
100~1000사이의 소수:  [101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 
421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997]
100~1000사이의 소수개수:  143
PS D:\app\python>

 


 

웹 서버 개발

Django, Flask

 

인공지능 개발 - 딥러닝(심층 학습)

scikit-learn, tensorflow, keras

 

데이터 분석

pandas, matplotlib

 

크롤러 개발(외부 데이터 수집)

BeautifulSoup, requests, scrapy

 

 

여기까지.

댓글