IT_developers

Python RPA(업무자동화) 개념 및 실습 - 크롤링(selenium)(7) 본문

Python

Python RPA(업무자동화) 개념 및 실습 - 크롤링(selenium)(7)

developers developing 2022. 10. 9. 12:00
  • RPA(Robotic Process Automation)
  • 웹, 윈도우, 어플리케이션(엑셀 등)을 사전에 설정한 시나리오에 따라 자동적으로 작동하여 수작업을 최소화하는 일련의 프로세스
  • RPA 사용 소프트웨어
    • Uipath, BluePrism, Automation Anywhere, WinAutomation
  • RPA 라이브러리
    • pyautogui, pyperclip, selenium
  • 크롤링 : 웹 사이트, 하이퍼링크, 데이터 정보 자원을 자동화된 방법으로 수집, 분류, 저장하는 것
  • Selenium
  • 브라우저 자동화 개념 적용
  • webdriver 이용해서 브라우저 조작, 자동으로 일을 시킬 수 있음
  • 웹을 테스트하기 위한 프레임워크
  • 자바, 파이썬, C#, 자바 스크립트 등 언어들에서 사용 가능
  • 소스 가져오기 + 파싱도 가능
  • 브라우저도 접근하기 때문에 차단 될 확률도 적어짐
  • 요소
    • find_element() : 하나의 요소를 찾을 때
    • find_elements() : 여러개의 요소를 찾을 때
      • 아이디 값 : find_element(By.ID, "ID 값")
      • CSS 선택자 : find_element(By.CSS_SELECTOR, "#선택자 값")
      • 클래스 : find_element(By.CLASS_NAME, "NAME 값")
      • Xpath : find_element(By.XPATH, '//*[@Xpath 값"]')
      • By.NAME, By.CLASS_NAME, By.CSS_SELECTOR, By.ID, By.LINK_TEXT, By.PARTIAL_LINK_TEXT, By.TAG_NAME, By.XPATH
    • ActionChain() : 여러 개의 액션을 수행할 경우 차례대로 저장한 후 수행
      • 마우스 이동, 마우스 버튼 클릭, key press  등등
    • WebDriverWait()
      • WebDriverWait(페이지,초) : 주어진 초 동안 페이지를 기다림
      • WebDriverWait().until(EC.presence_of_element_located((By.~~, "요소 값")) : 원하는 요소가 나올때까지
    • webdriver.ChromeOptions()
      • headless = True : 브라우저 창을 띄우지 않고 작업 가능함

 

RPAbasic\crawl\selenium1 폴더 - 23_newsletter.py

네이버에서 뉴스 링크 추출 후 다음 메일로 전송

  • 최신순으로 조회해서 뉴스가 총 몇건인지 확인 - 오픈 API사용
  • 시간이 지난 후 같은 주제로 검색했을 때 똑같은 뉴스는 제외하고 보내기
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException

import requests

import pyperclip


browser = webdriver.Chrome()
browser.get("https://www.naver.com")
browser.maximize_window()
time.sleep(1)

# 새창으로 다음 띄우기
browser.execute_script("window.open('http://www.daum.net')")

# 브라우저 2개 리스트로 다루기
tabs = browser.window_handles  # tabs[0] : naver, tabs[1] : daum

# 첫번째 탭 선택
browser.switch_to.window(tabs[0])

# 검색어 넣기
keyword = "RPA 파이썬"
browser.find_element(By.NAME, "query").send_keys(keyword)

# 검색버튼 클릭
browser.find_element(By.ID, "search_btn").click()

# 검색 결과 기다리기
time.sleep(2)

# 뉴스 메뉴 클릭
browser.find_element(By.XPATH, '//*[@id="lnb"]/div[1]/div/ul/li[8]/a').click()
time.sleep(1)

# 최신순 클릭
browser.find_element(By.XPATH, '//*[@id="snb"]/div[1]/div/div[1]/a[2]').click()

# 뉴스 조회일 기준으로 뉴스 총 건수 가져오기 - 오픈 API
client_id = "ITricAb_moCNCZRXqDKt"
client_secret = "i1dMkiMcjU"


headers = {"X-Naver-Client-Id": client_id, "X-Naver-Client-Secret": client_secret}

# 검색어
param = {"query": keyword}
 
# json으로 받아옴
res = requests.get(url, headers=headers, params=param)
result = res.json()
print(result)

# 뉴스 총 건수
new_total_cnt = result.get("total")  # result['total']

# 뉴스 총 건수를 파일 저장 - 23_totalCnt.txt
# 1) 기존 뉴스 건수를 읽어와서 변수에 담기
path = "./RPAbasic/crawl/selenium1/23_totalCnt.txt"
with open(path, "r") as f:
    old_total_cnt = int(f.readline())

# 2) new_total_cnt 와 기존 뉴스 건수 비교 ==> 지난 뉴스 기사 건수의 차이 구하기(new_add_cnt)
# 147-0
if new_total_cnt > old_total_cnt:
    new_add_cnt = new_total_cnt - old_total_cnt
    # 3) new_total_cnt를 텍스트에 기록
    with open(path, "w") as f:
        f.write(str(new_total_cnt))
else:
    new_add_cnt = 0

# 페이지 수 지정
if new_add_cnt == 0:
    page_cnt = 0
else:
    page_cnt = new_add_cnt // 10 + 1

start, num = 1, 1
# 결과값을 메일로 전송
result = ""

if page_cnt > 0:
    for i in range(3):  # page_cnt

        # 페이지 수 계산
        # 2페이지 == start=11, 3페이지 == start=21 ,...
        start = start + (i * 10)

        url += "&sm=tab_opt&sort=1&photo=0&field=0&pd=0&ds=&de=&docid=&related=0"
        url += "&mynews=0&office_type=0&office_section_code=0&news_office_checked="
        url += "&nso=so%3Add%2Cp%3Aall&is_sug_officeid=0&start=" + str(start)
        # start = 페이지 시작값

        browser.get(url)

        # 뉴스 크롤링
        # 뉴스제목, 매체(신문사), 등록일, 원문 주소
        # 뉴스 전 영역
        news_area = browser.find_elements(By.CLASS_NAME, "news_area")

        for idx, news in enumerate(news_area):
            # 뉴스 제목 news_area 안에 a
            title = news.find_element(By.CLASS_NAME, "news_tit")
            # 매체
            press = news.find_element(By.CLASS_NAME, "press")
            # 등록일
            reg_date = news.find_element(
                By.CSS_SELECTOR, "div.news_info > div.info_group > span"
            )
            # 원문 주소
            href = title.get_attribute("href")

           
            print(
                "{},{},{},{},{}".format(
                    idx, title.text, press.text, reg_date.text, href
                )
            )

            result += "<div><p><a href='" + href + "'>" + title.text + "</a> "
            result += press.text + " " + reg_date.text + "</p></div>"

print(result) # 뉴스 검색 결과 확인

# 다음에서 이메일 보내기
# 두번째 탭인 Daum으로 이동
browser.switch_to.window(tabs[1])

# 다음 로그인 - 카카오계정으로 로그인 클릭
browser.find_element(By.CLASS_NAME, "link_kakaoid").click()
time.sleep(1)

# 아이디 입력
id = browser.find_element(By.ID, "id_email_2")
id.clear()
id.send_keys("로그인할 아이디")
time.sleep(1)


# 비밀번호 입력
pwd = browser.find_element(By.ID, "id_password_3")
pwd.clear()
pwd.send_keys("로그인 할 비밀번호")
time.sleep(1)


# 로그인 클릭
browser.find_element(By.CLASS_NAME, "btn_confirm").click()
time.sleep(2)

# 메일 클릭
browser.find_element(By.XPATH, '//*[@id="mArticle"]/div[1]/div[2]/ul/li[1]/a').click()
time.sleep(5)


# result 내용 copy
pyperclip.copy(result)

# 메일 쓰기 클릭
browser.find_element(By.CLASS_NAME, "btn_write").click()
time.sleep(2)

# 받는사람란에 이메일 입력
toEmail = browser.find_element(By.ID, "toTextarea")
toEmail.send_keys("받는사람 메일")
time.sleep(2)
toEmail.send_keys(Keys.ENTER)

# 제목 입력
mailSubject = browser.find_element(By.ID, "mailSubject")
mailSubject.send_keys("RPA 파이썬 뉴스")
time.sleep(2)
mailSubject.send_keys(Keys.ENTER)

# 하단의 HTML 탭 클릭
browser.find_element(By.CLASS_NAME, "btn_html").click()
time.sleep(3)

# 메일 내용 텍스트 박스 선택 후 복사해 놓은 뉴스 붙여넣기
browser.find_element(By.CSS_SELECTOR, ".tx-canvas textarea").send_keys(
    Keys.CONTROL, "v"
)
time.sleep(2)

# 보내기
browser.find_element(By.CLASS_NAME, "btn_toolbar.btn_write").click()


time.sleep(3)
browser.quit()

 

뉴스 총 건수 확인
다음에서 메일 보내기
결과물

 

RPAbasic\crawl\selenium1 폴더 - 23_totalCnt.txt

 

Comments