안경잡이개발자

728x90
반응형

셀레니움(Selenium)을 활용해 네이버 자동 로그인 및 메일 정보 가져오기

나동빈


※ 셀레니움 개요 ※


  셀레니움(Selenium)자동화 웹 사이트 분석 프레임워크로 크롤링(Crawling)을 수행함에 있어서 매우 효과적인 기능을 제공합니다.  특히 구글 크롬(Chrome)과 같은 웹 브라우저와 연동되어 다양한 디버깅을 할 수 있어 편리합니다.


※ 셀레니움 설치 ※


  셀레니움은 PIP 명령어를 이용해 파이썬(Python) 개발환경에 쉽게 설치할 수 있습니다.


  pip install selenium: 파이썬(Python)에서 셀레니움(Selenium)을 설치하는 명령어입니다.



※ 크롬 웹 드라이버 ※


  우리가 개발한 파이썬 크롤링 소프트웨어에서 크롬(Chrome) 브라우저의 기능을 이용하도록 하기 위해서 웹 드라이버(Web Driver)를 설치해야 합니다.


  크롬 드라이버 URL: http://chromedriver.chromium.org/downloads



  위와 같이 드라이버 다운로드 링크를 눌러서 다운로드를 수행할 수 있습니다.



  자신의 운영체제에 맞는 웹 드라이버를 다운로드 해줍니다.



  저는 위와 같이 C 드라이브에 압축을 풀어주었습니다.


※ 셀레니움을 이용해 네이버 자동 로그인 하기 ※



  먼저 위와 같이 네이버 로그인 페이지의 주소를 확인하고 소스코드를 작성합니다.


# 자동화 테스트를 위해 셀레니움(Selenium)을 불러옵니다.

from selenium import webdriver


# 크롬 웹 드라이버의 경로를 설정합니다.

driver = webdriver.Chrome('C:\Chrome Driver\Chrome Driver.exe')


# 크롬을 통해 네이버 로그인 화면에 접속합니다.

driver.get('https://nid.naver.com/nidlogin.login')



  위와 같이 자동으로 크롬(Chrome) 브라우저가 실행되어 네이버에 접속한 것을 알 수 있습니다.



  이후에 위와 같이 '페이지 소스 보기'에서 아이디 및 비밀번호 입력 <input> 태그의 name 속성을 확인합니다.


# 아이디와 비밀번호를 입력합니다. (0.5초씩 기다리기)

time.sleep(0.5)

driver.find_element_by_name('id').send_keys('아이디')

time.sleep(0.5)

driver.find_element_by_name('pw').send_keys('비밀번호')

time.sleep(0.5)


  기본적으로 대형 포털 서비스는 너무 빠르게 다수의 로그인을 시도하면 트래픽 공격으로 판단할 수 있으므로 0.5초씩 대기하는 등의 작업을 별도로 처리해주어야 합니다.



  이제 네이버에 접속한 이후에 자동으로 아이디 및 비밀번호까지 입력된 것을 알 수 있습니다.



  이후에 자동으로 로그인 버튼까지 누를 수 있도록 개발자 도구(F12)에서 로그인 버튼 부분의 XPath를 복사(Copy)합니다.


# XPath를 이용해 로그인을 시도합니다.

driver.find_element_by_xpath('//*[@id="frmNIDLogin"]/fieldset/input').click()



  이제 위와 같이 성공적으로 로그인까지 이루어진 것을 알 수 있습니다. 이후에 메일함으로 이동해 봅시다.


  네이버 메일함 주소: https://mail.naver.com/



  이후에 개발자 도구로 소스코드를 확인한 결과 메일함의 제목 부분은 <strong> 태그의 mail_title 클래스인 것을 확인할 수 있었습니다. 따라서 이를 파싱하여 출력하는 소스코드를 작성하면 됩니다.


# 웹 페이지의 소스코드를 파싱하기 위해 Beautiful Soup 라이브러리를 불러옵니다.

from bs4 import BeautifulSoup


driver.get("https://mail.naver.com/")

html = driver.page_source

soup = BeautifulSoup(html, 'lxml')


# 메일 제목을 하나씩 파싱합니다.

title_list = soup.find_all('strong', 'mail_title')


# 모든 메일 제목을 출력합니다.

for title in title_list:

    print(title.text)



  위와 같이 정상적으로 최근 도착한 메일 제목들을 출력하는 것을 알 수 있습니다.

728x90
반응형

Comment +1

728x90
반응형

웹 크롤러(Web Crawler)로 자동 로그인 및 주요 정보 추출하기

나동빈


  이번 시간에는 실제 웹 사이트를 대상으로 가장 많이 사용되는 기술 중 하나인 자동 로그인(Auto Login) 및 주요 정보 추출 방법에 대해 소개하고자 합니다. 이번 시간에도 제 개인 웹 사이트를 실습 대상으로 설정하겠습니다.


  웹 사이트 URL: http://dowellcomputer.com/member/memberLoginForm.jsp



  웹 사이트에 접속하면 위와 같이 로그인 화면이 등장합니다.



  바로 '페이지 소스 보기'를 통해 어떠한 서버 URL로 파라미터(Parameter)를 전송하는지 확인합니다.



  일단 직접 수동으로 로그인을 수행해보시면 메인(Main) 페이지로 로그인이 된 상태로 이동하는 것을 알 수 있습니다. 따라서 다음과 같이 두 개의 파라미터를 전달하여 로그인 하는 프로그램을 작성해 봅시다.


from bs4 import BeautifulSoup as bs

import requests


MEMBER_DATA = {

    'memberID': 'a',

    'memberPassword': 'a'

}


# 하나의 세션(Session) 객체를 생성해 일시적으로 유지합니다.

with requests.Session() as s:

    # 로그인 페이지로의 POST 요청(Request) 객체를 생성합니다.

    request = s.post('http://dowellcomputer.com/member/memberLoginAction.jsp', data=MEMBER_DATA)

    

print(request.text)



  위 실행 결과를 보면 성공적으로 로그인 되어 메인 페이지로 리다이렉션(Redirection) 시키는 소스코드가 있는 것을 알 수 있습니다.



  로그인 이후에는 위와 같이 '회원 정보 수정' 링크로 들어간 이후에 자신의 이메일 정보를 확인할 수 있는 것을 알 수 있습니다.


request = s.get('http://dowellcomputer.com/member/memberUpdateForm.jsp?ID=a')

soup = bs(request.text, 'html.parser')


result = soup.findAll('input',{"name": "memberEmail"})

print(result[0].get('value'))


  결과적으로 <input> 태그 중에서 'memberEmail'이라는 이름 속성을 가지는 결과를 찾아서 출력해주었습니다.



  실행 결과를 보면 성공적으로 이메일 값이 추출된 것을 알 수 있습니다.

728x90
반응형

Comment +0

728x90
반응형

웹 크롤러(Web Crawler)로 연속적인 크롤링하기

나동빈


  지난 시간에 이어서 웹 크롤러를 이용해 연속적인 크롤링 방법에 대해 알아보는 시간을 가져보겠습니다.


  이번 시간의 실습 대상은 다양한 영어 대화(English Conversation) 스크립트를 제공하는 웹 사이트입니다.


  웹 사이트: https://basicenglishspeaking.com/daily-english-conversation-topics/



  웹 사이트에 접속하면 위와 같이 75개의 주제(Topic)이 나오는 것을 알 수 있습니다. 일단 전체 주제의 개수가 총 몇 개인지 자동으로 세주도록 해봅시다. '페이지 소스 코드'를 보시면 다음과 같이 클래스명에 따라서 내용이 구분되는 것을 확인할 수 있습니다.



  따라서 먼저 전체 주제의 개수를 찾을 수 있도록 프로그램을 작성해보겠습니다.


from bs4 import BeautifulSoup

import requests


# 한 건의 대화에 대한 정보를 담는 객체입니다.

class Conversation:

    # 질문(Question), 응답(Answer) 두 변수로 구성됩니다.

    def __init__(self, question, answer):

        self.question = question

        self.answer = answer

        

    def __str__(self):

        return "질문: " + self.question + "\n답변: " + self.answer + "\n"


# 모든 영어 대화 주제를 추출하는 함수입니다.

def get_subjects():

    subjects = []


    # 전체 주제 목록을 보여주는 페이지로의 요청(Request) 객체를 생성합니다.

    req  = requests.get('https://basicenglishspeaking.com/daily-english-conversation-topics/')

    html = req.text

    soup = BeautifulSoup(html, 'html.parser')


    divs = soup.findAll('div',{"class": "su-column-inner"})

    for div in divs:

        # 내부에 존재하는 <a> 태그들을 추출합니다.

        links = div.findAll('a')


        # <a> 태그 내부의 텍스트를 리스트에 삽입합니다.

        for link in links:

            subject = link.text

            subjects.append(subject)

    

    return subjects


subjects = get_subjects()


print('총 ', len(subjects), '개의 타입을 찾았습니다.')


print(subjects)



  성공적으로 75개의 주제를 찾아서 출력한 것을 확인할 수 있습니다. 이제 이어서 실질적으로 각각의 주제에 포함되어 있는 영어 대화 스크립트를 추출할 수 있는 소스코드를 작성해봅시다.



예를 들어 'Family'로 요청(Request) URL을 설정하여 들어가면 위와 같이 다양한 영어 대화 스크립트가 존재합니다.



마찬가지로 '페이지 소스 보기'를 통해 소스코드를 확인했을 때 일정한 규칙이 존재하는 것을 확인할 수 있습니다.


위에서 제시한 소스코드에 이어서 다음과 같이 소스코드를 작성하여 모든 주제에 대한 대화 스크립트를 가져 올 수 있도록 합니다.


conversations = []

i = 1


# 모든 대화 주제 각각에 접근합니다.

for sub in subjects:

    print('(', i, '/', len(subjects), ') ', sub)

    # 대화 스크립트를 보여주는 페이지로의 요청(Request) 객체를 생성합니다.

    req  = requests.get('http://basicenglishspeaking.com/' + sub)

    html = req.text

    soup = BeautifulSoup(html, 'html.parser')

    

    qnas = soup.findAll('div',{"class": "sc_player_container1"})


    # 각각의 대화 내용에 모두 접근합니다.

    for qna in qnas:

        if qnas.index(qna) % 2 == 0:

            q = qna.next_sibling

        else:

            a = qna.next_sibling

            c = Conversation(q, a)

            conversations.append(c)

            

    i = i + 1

            

print('총 ', len(conversations), '개의 대화를 찾았습니다.')


for c in conversations:

    print(str(c))



728x90
반응형

Comment +1

  • 교육생 2020.01.14 13:00

    태그가 뭔가 지금 바껴있는 것 같아요.. 그대로 안되네요

728x90
반응형

웹 크롤러(Web Crawler)의 개요 및 공지사항 크롤링 해보기

나동빈


※ 웹 크롤러의 개요 ※


  웹 크롤러(Web Crawler)란 자동화된 방법으로 웹(WEB)에서 다양한 정보를 수집하는 소프트웨어를 의미합니다. 예를 들어 특정한 웹 사이트에 주기적으로 올라오는 글을 실시간으로 문자로 알림해주는 서비스 등을 직접 만들고 싶을 때 사용할 수 있습니다.


  웹 크롤러가 매우 유용한 이유는 원하는 서비스로부터 원하는 정보를 편하게 얻어올 수 있기 때문입니다.


  또한 웹 크롤러는 언어를 막론하고 자신이 원하는 언어로 개발할 수 있습니다. 필자는 오래 전부터 Java를 이용해왔으나 최근 Python이 웹 크롤러 기능을 매우 강력하게 지원하는 추세라서 Python으로 강의를 준비해보았습니다.


※ 웹 크롤러 개발환경 구축하기 ※


  웹 크롤러를 개발하기 위해 기본적으로 파이썬(Python) 개발환경을 구축하셔야 합니다. 파이썬 개발환경이 구축되었다면 requests 라이브러리를 이용해 간단히 특정 URL의 HTML 소스코드를 가져오겠습니다. 타겟으로 설정한 사이트는 제 웹 사이트입니다.


  웹 사이트 URL: http://www.dowellcomputer.com/main.jsp


import requests


# 특정 URL에 접속하는 요청(Request) 객체를 생성합니다.

request = requests.get('http://www.dowellcomputer.com/main.jsp')


# 접속한 이후의 웹 사이트 소스코드를 추출합니다.

html = request.text


print(html)



  또한 웹 크롤러 개발을 위해 가장 많이 사용되는 라이브러리는 뷰티풀 수프(Beautiful Soup)입니다. 뷰티풀 수프는 특정 웹 사이트의 소스코드를 가져와 자유자재로 파싱(Parsing)하는 작업에 큰 도움을 줍니다. 저는 '최근 공지사항' 내용을 파싱하는 방법을 소개하고자 합니다.


  한 번 웹 사이트에서 마우스 우클릭 이후에 '페이지 소스 보기(V)'를 눌러서 소스코드를 살펴봅시다.



  이후에 아래와 같이 공지사항의 제목은 <td> 태그 내부의 <a> 태그로 구성되어 있는 것을 알 수 있었습니다.



  따라서 뷰티풀 수프를 이용해서 위에서 작성한 소스코드를 확장해봅시다.


import requests

from bs4 import BeautifulSoup


# 특정 URL에 접속하는 요청(Request) 객체를 생성합니다.

request = requests.get('http://www.dowellcomputer.com/main.jsp')


# 접속한 이후의 웹 사이트 소스코드를 추출합니다.

html = request.text


# HTML 소스코드를 파이썬 객체로 변환합니다.

soup = BeautifulSoup(html, 'html.parser')


# <a> 태그를 포함하는 요소를 추출합니다.

links = soup.select('td > a')


# 모든 링크에 하나씩 접근합니다.

for link in links:

    # 링크가 href 속성을 가지고 있다면

    if link.has_attr('href'):

        # href 속성의 값으로 notice라는 문자가 포함되어 있다면

        if link.get('href').find('notice') != -1:

            print(link.text)



  소스코드 실행 결과 위와 같이 2건의 공지사항 제목이 출력된 것을 알 수 있습니다.



  실제로 웹 사이트에서 보이는 '최근 공지사항' 내용과 정확히 일치합니다. 이상으로 간단한 형태의 웹 크롤러 개발 방법을 알아보았습니다.


728x90
반응형

Comment +0