파알못 파이썬: 8. 인기있는 파이썬 패키지

Table of Content

파이썬을 공부한 내용을 정리한 글입니다. 파알못이라 이상하거나 틀린 내용이 있을 수 있습니다…

웹 크롤링

웹 페이지를 다운로드하기 위해 requests를, 웹 페이지 내에서 원하는 정보를 추출하는 작업인 파싱을 위해 beautifulsoup를 설치합니다. 이 명령어는 pip3 install requests beautifulsoup4 입니다.

아래 예제는 스택 오버플로우에 올라온 최근 질문 제목을 출력하는 예제입니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://stackoverflow.com/questions")
soup = BeautifulSoup(response.text, "html.parser")

# class="question-summary" 인 태그를 가져옴
# select(): List 객체 반환
questions = soup.select(".question-summary")

for question in questions:
    # select_one(): Tag 객체 반환
    print(question.select_one(".question-hyperlink").getText())
    print(question.select_one(".vote-count-post").getText())

위의 예제는 for 문을 사용하여 List에 들어있는 모든 객체를 꺼내어 보여주는 예제입니다. 특정 객체 값을 보여주려면 List의 인덱스를 사용하면 됩니다.

import requests
from bs4 import BeautifulSoup

response = requests.get("https://stackoverflow.com/questions")
soup = BeautifulSoup(response.text, "html.parser")

# class="question-summary" 인 태그를 List 형태로 가져옴
questions = soup.select(".question-summary")

# List의 0번째 객체만 꺼내어 Dictionary 형태로 출력
print(questions[0].attrs)

# List의 0번째 객체 중 속성이 id인 값 출력
print(questions[0]["id"])
print(questions[0].get("id", 0))

웹 브라우저 자동화: Selenium

Selenium은 웹 사이트에서 다양한 기능을 테스트 할 수 있는 기능을 제공합니다. 여기서는 자동으로 GitHub 사이트에 로그인하여 해당 사용자가 정상적으로 로그인했는지 확인하는 예제를 설명해보겠습니다.

  1. 먼저 https://pypi.org/project/selenium 에서 웹 브라우저를 제어할 드라이버를 다운받습니다. Selenium에서 지원하는 웹 브라우저는 Chrome, Edge, Firefox, Safari 입니다. 여기서는 Chrome을 사용하겠습니다.

  2. 파이썬 코드에서 Chrome 브라우저 객체를 생성합니다.

from selenium import webdriver

# chromedriver 실행 파일을 /usr/local/bin으로 옮겨두면 path를 설정하지 않아도 됨
path = "/Users/ing-yeo/Documents/Study/Python/HelloWorld/chromedriver"
browser = webdriver.Chrome(path)
browser.get("https://github.com")
  1. GitHub 메인 화면에서 로그인을 하려면 Sign in 버튼을 클릭해야 합니다. Selenium에서 Sign in이라는 링크 텍스트를 찾아 클릭합니다.
signin_link = browser.find_element_by_link_text("Sign in")
signin_link.click()
  1. GitHub 로그인 화면에서 페이지 소스를 보면 유저이름(혹은 이메일)과 비밀번호를 입력하는 input 태그의 id는 각각 login_field와 password인 것을 알 수 있습니다.
<input type="text" name="login" id="login_field" class="form-control input-block" tabindex="1" autocapitalize="off" autocorrect="off" autofocus="autofocus" />

<input type="password" name="password" id="password" class="form-control form-control input-block" tabindex="2" />

따라서 이 input 태그에 Selenium으로 값을 입력합니다.

username_box = browser.find_element_by_id("login_field")
username_box.send_keys("abc12345@abc.com")
password_box = browser.find_element_by_id("password")
password_box.send_keys("abc12345")
password_box.submit()
  1. GitHub 로그인 성공 후 페이지 소스를 보면 어떤 계정으로 로그인했는지를 보여주는 태그는 class 속성 값에 user-profile-link가 들어간 a 태그임을 알 수 있습니다.
<a role="menuitem" class="no-underline user-profile-link px-3 pt-2 pb-2 mb-n2 mt-n1 d-block" href="/ing-yeo" data-ga-click="Header, go to profile, text:Signed in as">Signed in as <strong class="css-truncate-target">ing-yeo</strong></a>

따라서 이 값을 Selenium을 통해 가져옵니다.

# 해당 클래스 네임이 포함된 태그 얻어오기
profile_link = browser.find_element_by_class_name("user-profile-link")  
link_label = profile_link.get_attribute("innerHTML")

# link_label에 "ing-yeo"라는 값이 존재하지 않으면 예외를 발생시키지 않음
assert "ing-yeo" in link_label  
  1. 모든 작업이 끝나면 browser 객체를 닫아줍니다.
browser.quit()
  1. 위의 코드를 정리하면 다음과 같습니다.
from selenium import webdriver

# chromedriver 실행 파일을 /usr/local/bin으로 옮겨두면 path를 설정하지 않아도 됨
path = "/Users/ing-yeo/Documents/Study/Python/HelloWorld/chromedriver"
browser = webdriver.Chrome(path)
browser.get("https://github.com")

signin_link = browser.find_element_by_link_text("Sign in")
signin_link.click()

username_box = browser.find_element_by_id("login_field")
username_box.send_keys("abc12345@abc.com")
password_box = browser.find_element_by_id("password")
password_box.send_keys("abc12345")
password_box.submit()

# 해당 클래스 네임이 포함된 태그 얻어오기
profile_link = browser.find_element_by_class_name("user-profile-link")  
link_label = profile_link.get_attribute("innerHTML")

# link_label에 "ing-yeo"라는 값이 존재하지 않으면 예외를 발생시키지 않음
assert "ing-yeo" in link_label  

browser.quit()

PDF 작업

pypdf2를 사용하여 PDF 파일을 초 간단하게 편집해보는 예제를 설명해보겠습니다. 먼저 pip3 install pypdf2 명령어를 실행하여 pypdf2를 설치합니다.

아래 코드는 PDF 파일을 읽어온 후 회전시켜 별도의 파일로 저장하는 예제입니다.

import PyPDF2

with open("first.pdf", "rb") as file:  # rb: Read & Binary
    reader = PyPDF2.PdfFileReader(file)
    print(reader.numPages)

    # 0 번째 페이지를 시계 방향으로 90도 회전
    page = reader.getPage(0)
    page.rotateClockwise(90)

    # 회전한 페이지를 별도의 파일로 저장
    writer = PyPDF2.PdfFileWriter()
    writer.addPage(page)
    with open("rotated.pdf", "wb") as output:  # wb: Write & Binary
        writer.write(output)

여러 PDF 파일을 병합하는 코드는 다음과 같습니다.

import PyPDF2

merger = PyPDF2.PdfFileMerger()
file_names = ["first.pdf", "second.pdf"] # 병합할 PDF 파일 목록
for file_name in file_names:
    merger.append(file.name)
merger.write("comnined.pdf")

엑셀 작업

openpyxl을 사용하면 파이썬에서 다양한 엑셀 파일 작업을 수행할 수 있습니다. pip3 install openpyxl 명령어를 실행하여 openpyxl을 설치합니다.

import openpyxl

# 빈 워크북 생성
# wb = openpyxl.Workbook() # 빈 워크북 만들기

# 워크북(엑셀파일) 열기
wb = openpyxl.load_workbook("transactions.xlsx")
print(wb.sheetnames)  # 시트 이름 출력 (여기서는 Sheet1 하나만 출력된다고 가정)

# 시트 객체 생성
sheet = wb["Sheet1"]
print(sheet.max_row)  # 해당 시트의 최대 행 수
print(sheet.max_column)  # 해당 시트의 최대 열 수

# 시트 끝 부분에 데이터 추가
sheet.append([1, "ing-yeo", '=TEXT(TODAY(), "yyyy-mm-dd")'])

# 시트 생성
wb.create_sheet("MySheet", 0)  # 0은 인덱스

# A1셀 객체 생성 방법 1
sheet = wb["Sheet1"]
cell = sheet["a1"]
print(cell.row)
print(cell.column)
print(cell.coordinate)
print(cell.value)

# A1셀 객체 생성 방법 2
sheet = wb["Sheet1"]
cell = sheet.cell(row=1, column=1)
print(cell.row)
print(cell.column)
print(cell.coordinate)
print(cell.value)

# # 시트 내 모든 값 출력
sheet = wb["Sheet1"]
for row in range(1, sheet.max_row + 1):
    for column in range(1, sheet.max_column + 1):
        cell = sheet.cell(row, column)
        print(cell.value)

# # A열 객체 생성
sheet = wb["Sheet1"]
column = sheet["a"]
print(column)  # 튜플 출력
for item in column:  # 모든 값 출력
    print(item.value)

# A~C열 객체 생성
sheet = wb["Sheet1"]
cells = sheet["a:c"]
print(cells)  # 튜플 출력
for cell in cells:  # 모든 값 출력
    for item in cell:
        print(item.value)

# A1~C3 범위 객체 생성
sheet = wb["Sheet1"]
sheet_1 = sheet["a1:c3"]
print(sheet_1)  # 튜플 출력
for sheet in sheet_1:  # 모든 값 출력
    for item in sheet:
        print(item.value)

# 2~3행 범위 객체 생성
sheet = wb["Sheet1"]
sheet_2 = sheet[2:3]
print(sheet_2)  # 튜플 출력
for sheet in sheet_2:  # 모든 값 출력
    for item in sheet:
        print(item.value)

# 행열 삭제
sheet = wb["Sheet1"]
sheet.insert_rows(2)  # 2열에 새로운 열 삽입
sheet.delete_rows(2, 3)  # 2~3열 삭제
sheet.insert_cols(2)  # 2행(B열)에 새로운 열 삽입
sheet.delete_cols(2, 3)  # 2~3행(B~C열) 삭제

# 워크북 저장
wb.save("transactions2.xlsx")

댓글 남기기