가상환경이란?

우리는 파이썬을 배울 때, 기본적으로 파이썬을 설치하여 하나의 파이썬 버전만 설치하여 사용하였다. 특정 프로젝트 진행시에 파이썬 3.5버전에 A 1.3버전 라이브러리 B 1.5 라이브러리를 사용해야할 수 있다. 이런 경우 파이썬의 버전이나 정보들을 여러개로 분리하여, 각각을 독립적으로 가상환경으로 만들어 선택하여 사용 가능하다.

 

step 1.

visual studio code 접속한다.

 

step 2.

python3 -m venv tutorial-env를 입력한다.

 

step 3.

* 윈도우의 경우

tutorial-env\Scripts\activate.bat 입력 

* Unix 또는 Mac OS의 경우 

source tutorial-env/bin/activate 입력

 

이렇게 되면 turoial-env라는 독립적인 가상환경이 만들어 진 것이다. 다른 프로젝트와 독립적인 공간에서 패키지를 설치하고 사용할 수 있다.

 

파이썬 가상환경에 대해서 더 자세히 알고자 한다면,

https://docs.python.org/ko/3/tutorial/venv.html

 

12. 가상 환경 및 패키지 — Python 3.9.4 문서

12.1. 소개 파이썬 응용 프로그램은 종종 표준 라이브러리의 일부로 제공되지 않는 패키지와 모듈을 사용합니다. 응용 프로그램에 특정 버전의 라이브러리가 필요할 수 있는데, 응용 프로그램에

docs.python.org

파이썬 공식 홈페이지 문서를 살펴보도록 하자!! 

 

* 아래의 다른 가상환경도 있으니 참고 하도록 하자.

  • 파이썬에서는 한 라이브러리에 대해 하나의 버전만 설치가 가능합니다.
  • 여러개의 프로젝트를 진행하게 되면 이는 문제가 됩니다. 작업을 바꿀때마다 다른 버전의 라이브러리를 설치해야합니다.
  • 이를 방지하기 위한 격리된 독립적인 가상환경을 제공합니다.
  • 일반적으로 프로젝트마다 다른 하나의 가상환경을 생성한 후 작업을 시작하게 됩니다.
  • 가상환경의 대표적인 모듈은 3가지가 있습니다.
    • venv : Python 3.3 버전 이후 부터 기본모듈에 포함됨
    • virtualenv : Python 2 버전부터 사용해오던 가상환경 라이브러리, Python 3에서도 사용가능
    • conda : Anaconda Python을 설치했을 시 사용할 수있는 모듈
    • pyenv : pyenv의 경우 Python Version Manger임과 동시에 가상환경 기능을 플러그인 형태로 제공

 

웹 스크롤링이란?

- 웹페이지의 소스코드를 가져올 수 있는 기능. 소스코드 분석 및 웹페이지를 활용한 자동화를 이용할 시에 유용하다.

Request

- Request는 웹 사이트에 소스코드를 요청하는 라이브러리다.

Mac Terminal

1. pip3 install requests

import requests

res=requests.get("http://google.com")
res.raise_for_status()

print(len(res.text))
print(res.text)

with open("mygoogle.html", "w", encoding="utf-8") as f:
	f.write(res.text)

request를 통해서 구글.com을 스크래핑한다.

res.text를 mygoogle.html이라는 파일로 만들고 "w" 쓰기모드로 저장한다. 

User-Agent

import requests
url = "http://codingboycc.tistory.com"
headers = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36"}
res = requests.get(url, headers=headers)
res.raise_for_status()
with open("codingboycc.html", "w", encoding="utf8") as f:
    f.write(res.text)

 

티스토리에서는 '우리가 request를 통해서 접속하는 사람이 사람이 아니고 기계일 것이다' 가정하여 정확한 웹스크롤링이 가능하지 않다. 이럴 경우에 이용할 수 있는 것이 User-Agent다. 

1. 구글에 what is my user agent를 검색한다. 

headers = {} 안에 user agent 값을 입력한다. 

이렇게 코드를 실행하고 나면 정확한 웹스크롤링이 가능해진다. 

 

Beautiful Soup

- Beautiful Soup은 웹 페이지의 소스코드를 가져 온 뒤에 특정 소스만을 색인하여 가져올 수 있는 라이브러리이다.

1. pip3 install beautifulsoup4

2. pip3 install lxml

*  XML이란 단순한 문자열을 넘어서서, 내부적으로 트리 구조를 가진 파일을 표현하기 위한 마크업 언어이다. html 및 오피스파일도 XML에 속한다. 파이썬에서도 XML parser로서 주로 이용되는 패키지가 lxml이다.

import requests

from bs4 import BeautifulSoup

url = "https://comic.naver.com/webtoon/weekday.nhn"
res = requests.get(url)
res.raise_for_status()
soup = BeautifulSoup(res.text, "lxml")
print(soup.title)
print(soup.title.get_text())
print(soup.a) # soup 객체에서 처음 발견되는 a element 반환
print(soup.a.attrs) a element의 속성 정보를 출력
print(soup.a["href"]) #a element의 href 정보 출력

print(soup.find("a", attrs={"class":"Nbtn_upload"}))
print(soup.find(attrs={"class":"Nbtn_upload"}))
print(soup.find("li", attrs={"class":"rank01"}))
rank1 = soup.find("li", attrs={"class":"rank01"})
print(rank1.a)1

위의 해당 url에 페이지 내에서 원하는 정보를 마음대로 빼올 수 있다. class 값을 설정하여 특정 class 소스만 크롤링한다던가 등등... 

 

정규식 

- 예시로 이것은 올바른 주민번호의 형식이야, 이건 올바른 이메일의 형식이야 등, 올바른 정규 표현식에 대해서 알아보자.

Import re를 하는데 re = regular expression(정규 표현식)의 줄임말인 듯 하다. 

import re

p = re.compile("ca.e")
def print_match(m):
    if m :
        print(m.group())
    else:
        print("매칭되지 않음")

m = p.match("careless")
print_match(m)

 위의 함수에 대해서 ca.e를 기준으로 잡아서 careless와 일치하는 지를 판단하는 코드이다. 

# . (ca.e) : 하나의 문자를 의미 > cane, cake, cafe(O) | caffe (x)

# ^ (^de) : 문자열의 시작 > deer, delay (O) | blonde (x)

# $ (se$) : 문자열의 끝 > rose, pose (O) | pace (x)

정규식은 더 공부할 것이 많다고 하니 꾸준히 찾아보고 공부할 필요가 있을 것 같다. 

 

5. Selenium

- 셀레니엄은 실제 브라우저를 코드를 통해 조작하는 방식이다. 웹브라우저로 할 수 있는 모든 것을 자동화할 수 있다고 한다. 아래 코드를 통하여 이미지를 자동으로 다운로드 받는 코드를 확인해보자.

1. pip3 install selenium

2. Chrome Driver 다운로드 

 

1) 구글에서 아이유를 검색하여 아이유의 첫 번째 이미지를 다운로드

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import urllib.request
import time 

driver = webdriver.Chrome('./chromedriver')
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("아이유")
elem.send_keys(Keys.RETURN)
images = driver.find_elements_by_css_selector(".rg_i.Q4LuWd")
count =1 
for image in images : 
    image.click()
    time.sleep(3)
    imgUrl = driver.find_element_by_css_selector(".n3VNCb").get_attribute("src")
    urllib.request.urlretrieve(imgUrl, "IU" + str(count) + ".jpg")
    count = count + 1 

위의 코드를 입력하게 되면 구글에서 아이유를 자동으로 입력하여 첫 번째 아이유 사진을 다운로드 받을 수 있다.

 

2) 구글에서 아이유를 입력하여 구글에 있는 모든 아이유 이미지를 스크롤 다운하고 + 결과 더보기 버튼을 눌러서 다운로드.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import urllib.request
import time 

driver = webdriver.Chrome('./chromedriver')
driver.get("https://www.google.co.kr/imghp?hl=ko&ogbl")
elem = driver.find_element_by_name("q")
elem.send_keys("아이유")
elem.send_keys(Keys.RETURN)

SCROLL_PAUSE_TIME = 2

# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight")

while True:
    # Scroll down to bottom
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # Wait to load page
    time.sleep(SCROLL_PAUSE_TIME)

    # Calculate new scroll height and compare with last scroll height
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        try:
            driver.find_element_by_css_selector(".mye4qd").click()
        except:
            break
    last_height = new_height
images = driver.find_elements_by_css_selector(".rg_i.Q4LuWd")
count =1 
for image in images : 
    try:
        image.click()
        time.sleep(3)
        imgUrl = driver.find_element_by_css_selector(".n3VNCb").get_attribute("src")
        urllib.request.urlretrieve(imgUrl, "IU" + str(count) + ".jpg")
        count = count + 1 
    except: 
        pass
driver.close()

위의 코드는 구글에서 아이유를 검색해서 모든 아이유 사진을 다운로드 받을 수 있다.

 

 

문제

두 정수 A와 B를 입력받은 다음, A-B를 출력하는 프로그램을 작성하시오.

 

입력

첫째 줄에 A와 B가 주어진다.(0<A, B<10)

 

Solution 1.

print((readLine()?.split(separator: " ")
       .map { Int($0)!}.reduce(0, { x, y in -x - y}))!)

Solution 2.

 

import Foundation

let line = readLine() ?? ""
let lineArr = line.characters.split($0 == ""}.map(String.init)
let a = Int(lineArr[0]) ?? 0
let b = Int(lineArr[1]) ?? 0 
print(a-b)

문제7.

두 정수 A와 B를 입력받은 다음, AxB를 출력하는 프로그램을 작성하시오.

 

입력

첫째 줄에 A와 B가 주어진다.(0<A, B<10)

 

Solution.

import Foundation

let lineArr = readLine()?.components(separatedBy: " ") ?? [""]
let A = Int(lineArr[0]) ?? 0 
let B = Int(lineArr[1]) ?? 0
print(A*B)

Point.

Line이 필요 없다!

 

문제8.

두 정수 A와 B를 입력받은 다음, A/B를 출력하는 프로그램을 작성하시오.

 

입력

첫째 줄에 A와 B가 주어진다. (0 < A, B < 10)

 

출력

첫째 줄에 A/B를 출력한다. 실제 정답과 출력값의 절대오차 또는 상대오차가 10^-9 이하이면 정답이다.

 

Solution.

import Foundation

let lineArr = readLine()?.components(separatedBy: " ") ?? [""]
let A = Double(lineArr[0]) ?? 0
let B = Double(lineArr[1]) ?? 0 
let AB = String(format: "%.9f",A/B)
print(AB)

Point.

format: "%.9f", A/B -> 소수점 n번째 자리까지 출력할 수 있어? 

Float은 8자리 이하 소수점까지, Double은 16자리 이하 소수점까지 사용한다.

 

문제9.

두 자연수 A와 B가 주어진다. 이때, A+B, A-B, A*B, A/B(몫), A%B(나머지)를 출력하는 프로그램을 작성하시오.

 

입력

두 자연수 A와 B가 주어진다.(1 <= A, B <= 10,000)

 

출력

첫째 줄에 A+B, 둘째 줄에 A-B, 셋째 줄에 A*B, 넷째 줄에 A/B, 다섯재 줄에 A%B를 출력한다.

 

Solution.

 

import Foundation

let lineArr = readLine()?.components(separatedBy: " ") ?? [""]
let A = Int(lineArr[0]) ?? 0
let B = Int(lineArr[1]) ?? 0
print("\(A+B)\n\(A-B)\n\(A*B)\n\(A/B)\n\(A%B)")

 

문제 10.

(A+B)%C는 ((A%C) + (B%C)%C와 같을까?

(A+B)%C는 ((A%C) x (B%C)%C와 같을까?

세 수 A, B, C가 주어졌을 때, 위의 네 가지 값을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 A, B, C가 순서대로 주어진다.(2 <= A, B, C <= 10000)

 

출력

첫째 줄에 (A+B)%C, 둘째 줄에 ((A%C) + (B%C)%C, 셋째 줄에 (AxB)%C, 넷째 줄에 ((A%C) x (B%C))%C를 출력한다.

 

Solution.

import Foundation

let lineArr = readLine()?.components(separatedBy: " ") ?? [""] 
let A = Int(lineArr[0]) ?? 0 
let B = Int(lineArr[1]) ?? 0 
let C = Int(lineArr[2]) ?? 0 
print("\((A+B)%C)\n\((A%C+B%C)%C)\n\((A*B)%C)\n\((A%C*B%C)%C)")

 

문제 11.

(세 자리 수) x (세 자리 수)는 다음과 같은 과정을 통하여 이루어진다.

(1)과 (2) 위치에 들어갈 세 자리 자연수가 주어질 때, (3), (4), (5), (6) 위치에 들어갈 값을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 (1)의 위치에 들어갈 세 자리 자연수가, 둘째 줄에 (2)의 위치에 들어갈 세자리 자연수가 주어진다.

 

출력

첫째 줄부터 넷째 줄 까지 차례대로 (3), (4), (5), (6)에 들어갈 값을 출력한다.

 

Solution 1.

 

import Foundation

let A = Int(readLine() ?? "") ?? 0
let B = Int(readLine() ?? "") ?? 0
print("\(A*(B%10))\n\(A*(B%10)%10))\n\(A*(B/100))")

Point.

1의 자리, 10의 자리, 100의 자리를 구분할 수 있는가? 1의 자리 -> n%10, 10의 자리 - > (n/10)%10, 100의 자리 n/100

 

Solution 2.

import Foundation

let strA = readLine() ?? ""
let strB = readLine() ?? "" 
let a = Int(strA) ?? 0 
let b = Int(strB) ?? 0 

var tmpB = b 
while tmpB != 0 {
	print(a*(tmpB%10))
    tmpB /= 10 
    }
print(a*b)

Point. 

n번째 자리수의 숫자 추출 방법 : 추출하고자 하는 자리수의 숫자를 1의 자리에 오도록 10으로 나눈 후, 10 나머지 연산을 계산한다. 

575 % 10 = 5 -> 1의자리 

(575/10) % 10 = 7 -> 10의 자리  

+ Recent posts