[Python] BeautifulSoup, Selenium을 연동한 데이터 수집

박주찬·2024년 5월 12일

python

목록 보기
7/10
post-thumbnail
  1. selenium==4.20.0

    Selenium은 웹 브라우저를 자동화하기 위해 사용되는 도구입니다. 예를 들어, 웹 사이트에서 데이터를 수집하거나, 웹 브라우저를 통해 특정 작업을 자동으로 실행할 때 사용할 수 있습니다. 지정한 버전은 4.20.0입니다.

  1. beautifulsoup4==4.12.2

    Beautiful Soup은 HTML 및 XML 파일로부터 데이터를 추출하기 위해 사용되는 라이브러리입니다. 웹 스크래핑 할 때 유용하며, 웹 페이지의 구조를 파악하고 데이터를 쉽게 추출할 수 있게 도와줍니다. 설치하려는 버전은 4.12.2입니다.

  1. webdriver-manager==4.0.1

    Webdriver Manager는 Selenium을 사용할 때 필요한 웹드라이버(예: ChromeDriver, GeckoDriver)를 자동으로 관리해주는 유틸리티입니다. 이를 사용하면 웹드라이버의 설치 및 경로 설정 등의 번거로움을 줄일 수 있습니다. 여기서는 버전 4.0.1을 설치하고 있습니다.

  1. typing_extensions==4.11.0

    typing_extensions는 Python의 타이핑 시스템을 확장하는 라이브러리입니다. 예를 들어, 타입 힌트(Type hints)를 사용하여 코드의 가독성과 유지 보수성을 높이는데 도움을 줍니다. 버전 4.11.0을 설치하고 있습니다.

  2. pip install openpyxl
    pip install openpyxl 명령어는 openpyxl 라이브러리를 설치하는 것입니다. openpyxl은 파이썬에서 Excel 파일을 읽고, 쓰고, 수정할 수 있게 해주는 도구입니다. 특히 .xlsx 형식의 파일, 즉 Microsoft Excel 2010 이상 버전에서 사용하는 파일 형식을 다룰 때 사용됩니다.
    예를 들어, Excel 파일에 있는 데이터를 파이썬으로 가져와서 데이터 분석을 하거나, 파이썬으로 데이터를 처리한 후 Excel 파일로 결과를 저장하고 싶을 때 openpyxl을 사용할 수 있습니다. 이 라이브러리는 표, 그래프, 수식 등을 포함한 복잡한 Excel 기능들도 지원합니다.

  1. pip install xlrd

    pip install xlrd 명령어는 xlrd 라이브러리를 설치하는 것입니다. xlrd는 주로 Excel 파일, 특히 구 버전의 .xls 파일을 읽기 위해 사용되는 파이썬 라이브러리입니다. 이 라이브러리를 사용하면 Excel 파일에서 데이터를 추출하여 파이썬에서 처리할 수 있습니다.

하지만 xlrd 라이브러리는 최신 업데이트에서 .xlsx 파일 포맷의 지원을 중단하였기 때문에, .xlsx 파일을 다루려면 openpyxl과 같은 다른 라이브러리를 사용해야 합니다. xlrd는 오래된 .xls 포맷의 Excel 파일을 읽을 때 주로 사용됩니다.

  1. conda install cx_oracle
    conda install cx_oracle 명령어는 cx_Oracle 라이브러리를 설치하는 것입니다. cx_Oracle은 파이썬에서 Oracle 데이터베이스에 접속하고, SQL 쿼리를 실행하며, 데이터베이스 관리 작업을 수행할 수 있게 해주는 라이브러리입니다.

이 라이브러리는 Oracle Database와의 통신을 위해 Oracle Client Libraries와 함께 작동하며, 다음과 같은 작업들을 가능하게 해줍니다:

데이터베이스에 쿼리를 보내고 결과를 받아올 수 있습니다.
데이터베이스 스키마의 생성, 수정, 삭제 등의 관리 작업을 할 수 있습니다.
트랜잭션 관리 및 성능 최적화를 위한 고급 기능을 제공합니다.
conda를 사용하는 경우, 일반적인 파이썬 패키지 관리자인 pip 대신 Anaconda나 Miniconda 환경에서 라이브러리를 설치하고 관리할 때 사용됩니다. 이는 특히 데이터 과학, 머신러닝, 대규모 데이터 처리를 위한 복잡한 환경을 구축할 때 유용합니다. cx_Oracle를 설치함으로써 파이썬을 사용하여 Oracle 데이터베이스와의 상호 작용을 용이하게 할 수 있습니다.

  1. conda install sqlalchemy

conda install sqlalchemy 명령어는 SQLAlchemy 라이브러리를 설치하는 것입니다. SQLAlchemy는 파이썬에서 사용되는 가장 인기 있는 데이터베이스 도구 중 하나로, 데이터베이스와의 상호작용을 추상화하고 간소화하는 ORM (Object-Relational Mapping) 도구입니다.

SQLAlchemy의 주요 기능은 다음과 같습니다:

ORM (Object-Relational Mapper): 파이썬 객체를 데이터베이스 테이블에 매핑하고, 이 객체들을 사용하여 데이터베이스 작업을 수행할 수 있게 해줍니다. 이를 통해 복잡한 SQL 쿼리 없이 데이터베이스를 쉽게 조작할 수 있습니다.
SQL 표현 언어: 직접 SQL 쿼리를 작성할 수 있는 기능을 제공합니다. 이는 데이터베이스 작업에 더 세밀한 제어가 필요할 때 유용합니다.
데이터베이스 연결 풀과 트랜잭션 관리: 여러 데이터베이스 연결을 효율적으로 관리하고, 트랜잭션을 안전하게 처리할 수 있습니다.
SQLAlchemy는 여러 종류의 데이터베이스 시스템(예: MySQL, PostgreSQL, Oracle, Microsoft SQL Server 등)을 지원하며, 데이터베이스에 독립적인 코드를 작성할 수 있게 해줍니다. 이로 인해 애플리케이션을 다른 데이터베이스 시스템으로 이식할 때 유연성을 제공합니다.

conda를 사용하여 SQLAlchemy를 설치하면, Anaconda나 Miniconda 환경에 쉽게 통합할 수 있어, 데이터베이스를 다루는 데이터 과학이나 애플리케이션 개발에 매우 유용합니다.

다음단계 -> Jupyter notebook 재부팅


[01] Selenium 이벤트 처리

  • Selenium 4.x (현재 4.x)
   driver.find_element(By.ID, "element_id")
   driver.find_element(By.NAME, "element_name")
   driver.find_element(By.LINK_TEXT, "element_link_text")
   driver.find_element(By.PARTIAL_LINK_TEXT, "element_partial_link_text")
   driver.find_element(By.TAG_NAME, "element_tag_name")
   driver.find_element(By.CSS_SELECTOR, "element_css_selector")
   driver.find_element(By.XPATH, "element_xpath")

  • 마우스 Click event
    웹 자동화 도구인 Selenium을 사용하여 특정 웹 페이지 요소를 찾고 클릭하는 기능을 수행합니다.

    .click():
         find_element_by_css_selector()나 find_element_by_link_text()      등에 의해 반환된 요소(즉, 선택된 웹 페이지 요소)에 클릭      이벤트를 발생시킵니다. 이는 사용자가 해당 요소를 마우스로      클릭하는 것과 같은 효과를 나타내며, 이를 통해 버튼을      누르거나 링크를 따라가는 등의 동작을 자동화할 수 있습니다.

   driver.find_element_by_css_selector('#css>div.style1.style2') .click()
   driver.find_element_by_link_text("1").click()
   
   예시):
     try:
         driver.find_element_by_css_selector('#sa-campaign__v2 > div > div > div > div._sa_bottom-group > button:nth-child(1)').click()
      except Exception as e:
         print(e)
         print('태그가 없습니다.')

  • 키보드 입력 event
    Selenium을 사용해 웹 페이지의 특정 입력 필드를 찾고, 그곳에 텍스트를 입력한 다음, 엔터 키를 누르는 작업을 수행합니다.

   element = driver.find_element_by_css_selector('#inp_search')
   print(type(element)) # <class 'selenium.webdriver.remote.webelement.WebElement'>
   element.send_keys(word)
   element.send_keys('\n') # Enter key
   

<코드 설명>
1) element = driver.find_element_by_css_selector('#inp_search')

find_element_by_css_selector(): 이 메소드는 CSS 선택자를 사용하여 웹 페이지의 특정 요소를 찾습니다. CSS 선택자는 HTML 요소를 스타일링 할 때 사용되는 표현식이며, 여기서는 웹 페이지에서 요소를 식별하는 데에도 사용됩니다.

2) print(type(element)):

이 줄은 element 객체의 타입을 콘솔에 출력합니다. 출력 결과는 <class 'selenium.webdriver.remote.webelement.WebElement'>로, element가 Selenium의 WebElement 클래스의 인스턴스임을 나타냅니다.

3) element.send_keys(word):
send_keys() 메소드를 사용하여 element (여기서는 입력 필드)에 word라는 변수의 값을 입력합니다. word에는 입력하고자 하는 텍스트가 저장되어 있어야 합니다. 예를 들어, 사용자가 검색어를 입력하는 필드에 특정 검색어를 프로그램적으로 입력할 때 사용합니다.

4) element.send_keys('\n'):

이 줄에서도 send_keys() 메소드를 사용하는데, 인자로 준 '\n'은 줄바꿈 문자로, 여기서는 엔터(Enter) 키의 기능을 합니다. 이를 입력 필드에 보내면, 마치 사용자가 엔터 키를 누른 것처럼 동작하여, 예를 들어 검색을 실행하거나, 폼을 제출하는 등의 행동을 유발합니다.


import warnings
warnings.filterwarnings(action='ignore')

import os    # 폴더등 처리
import time  # sleep 지연

import pandas as pd # Excel과 비슷한 구조를 지원하는 데이터 분석 패키지
import cx_Oracle    # Oracle 입출력
from sqlalchemy import create_engine # Pandas -> Oracle

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager

from bs4 import BeautifulSoup
from urllib.request import urlopen
from urllib.parse import quote
from urllib.error import HTTPError

# Options 클래스의 인스턴스를 생성합니다.
options = Options()
# Chrome 브라우저 창이 즉시 닫히는 것을 방지합니다.
options.add_experimental_option('detach', True)
# 불필요한 콘솔 메시지를 제거합니다.
options.add_experimental_option('excludeSwitches', ['enable-logging'])

# Service 객체를 생성하고 ChromeDriverManager를 통해 드라이버를 설치합니다.
service = Service(ChromeDriverManager().install())

# Chrome 브라우저를 실행하는 ChromeDriver 객체를 생성합니다.
driver = webdriver.Chrome(service=service, options=options)
driver.set_window_size(1600, 900) # width, height



# 웹페이지 로딩을 완료시까지 기다림. 기본값: 0.5초
def load(url, second=0.5): # Selenium으로 태그 검색
    try:
        driver.get(url) # url 접속
        time.sleep(second) # 웹페이지 로딩을 완료시까지 기다림. 0.5: 0.5초
    except HTTPError as e:
        print(e)
        return None

def loadbs(url, second=0.5): # url load후 BeautifulSoup으로 태그 검색
    try:
        driver.get(url) # url 접속
        time.sleep(second) # 웹페이지 로딩을 완료시까지 기다림. 0.5: 0.5초
        bs = BeautifulSoup(driver.page_source, 'html.parser')
    except HTTPError as e:
        print(e)
        return None
    else:
        return bs # 정상 처리  
    
def getbs(): # BeautifulSoup으로 태그 검색
    try:
        bs = BeautifulSoup(driver.page_source, 'html.parser')
    except HTTPError as e:
        print(e)
        return None
    else:
        return bs # 정상 처리  





nos=[]
titles=[]
areas=[]
search_words=[]

load('https://korean.visitkorea.or.kr/main/main.do', 1)

# #inp_search
driver.find_element(By.CSS_SELECTOR, '#inp_search').click()

# #inp_search_index
word = '강화도'
search_tag = driver.find_element(By.CSS_SELECTOR, '#inp_search_index')
search_tag.clear()         # 기존에 입력된 내용 삭제
search_tag.send_keys(word) # 문자 입력
search_tag.send_keys('\n') # Enter key

time.sleep(3) # 검색 진행으로 지연

# 더보기: #s_attraction > div.more_view > a
driver.find_element(By.CSS_SELECTOR, '#s_attraction > div.more_view > a').click()

bs = getbs()   # BeautifulSoup

# 상품 목록: #search_result > ul > li > div.cont
tags = bs.select('#search_result > ul > li > div.cont')

for i, tag in enumerate(tags):  # 인덱스 튜플 형태 (i , tag)  i -> 0부터 시작
    title = tag.select_one('div.cont > div.tit > a').text
    print(f'{i+1}. {title}')
    area = tag.select_one('div.cont > span.area').text
    print(f'{" " * 3}{area}')
    search_word = tag.select_one('div.cont > div.tag').text
    print(f'{" " * 3}{search_word}')
    print()
    
    nos.append(i+1)
    titles.append(title.strip())
    areas.append(area.strip())
    search_words.append(search_word.strip())

################################# 결과 ##################################
1. 강화도 자연체험농장
   인천 강화군
   #관광지#강화도자연체험농장#강화도자연농장#강화도체험농장#인천자연농장#인천농촌체험#인천승마체험

2. 강화도동부해안도로
   인천 강화군
   #관광지#강화#용당돈대#용진진#용두돈대#강화동부해안도로#오두돈대#초지진#강화도 유적#화도돈대#덕진진#갑곶돈대#광성보

3. 강화도제적봉 평화전망대
   인천 강화군
   #강화도제적봉평화전망대#수도권#아이와함께#전망좋은곳#안보여행#역사#관광지#안보관광#한국전쟁#역사공부#한국역사#교육여행#평화여행#평화전망대#강화평화전망대#강화도평화전망대#인천평화전망대#2024_여행가는달과함께하는_발도장여행지

4. 강화도
   인천 강화군
   #자연#강화도#수도권#섬여행#역사유적지#관광지

5. 강화 전등사
   인천 강화군
   #전등사#템플스테이#사찰&산사#전통&역사문화체험#서울근교여행#수도권#당일치기여행#아이와함께#친구와함께#가족여행#체험학습#나들이#힐링#드라이브여행#역사#관광지#사찰여행#강화가볼만한곳#강화여행#가족과함께#자연속으로#수도권반려동물여행지#반려동물동반여행지#인천전등사#강화전등사#강화도여행#2024_여행가는달과함께하는_발도장여행지

6. 강화루지(강화씨사이드리조트)
   인천 강화군
   #관광지#당일코스#1박2일#인천가볼만한곳#강화도가볼만한곳#강화도#강화루지#강화도루지#강화여행#강화씨사이드#강화씨사이드리조트#강화리조트#강화도데이트#인천여행#국내여행#이색데이트#인천강화루지#강화도당일치기#루지#이색체험#겨울레포츠#꿀잼_액티비티#강화가볼만한곳#레포츠#2024_여행가는달과함께하는_발도장여행지

7. 강화문학관
   인천 강화군
   #문화시설#인천권#강화문학관#교육프로그램#조경희문학관#문학관#문학전시#문학

8. 강화 화개산 모노레일
   인천 강화군
   #관광지#화개모노레일#인천화개산모노레일#인천모노레일#강화모노레일#강화도여행#인천화개산모노레일

9. 고려천도공원
   인천 강화군
   #관광지#고려천도공원#강화도역사문화유적지#강화도천도#민통선안보관광코스#민통선내부공원#역사체험#역사관광#역사테마공원#강화가볼만한곳#안보관광#고려시대대몽항쟁#아이와함께가볼만한곳

10. 강화오상리고인돌군
   인천 강화군
   #관광지#강화오상리고인돌군#인천시기념물#고인돌#오상리고인돌#강화고인돌#청동기시대유적

#######################################################################



print(nos)
결과:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


df = pd.DataFrame()
df['번호'] = nos
df['제목'] = titles
df['지역'] = areas
df['태그'] = search_words
df

결과:
	번호 제목				지역		  태그
0	1	강화도 자연체험농장	인천 강화군	#관광지#강화도자연체험농장#강화도자연농장#강화도체험농장#인천자연농장#인천농촌체험#인...
1	2	강화도동부해안도로	인천 강화군	#관광지#강화#용당돈대#용진진#용두돈대#강화동부해안도로#오두돈대#초지진#강화도 유적...
2	3	강화도제적봉 평화전망대	인천 강화군	#강화도제적봉평화전망대#수도권#아이와함께#전망좋은곳#안보여행#역사#관광지#안보관광#...
3	4	강화도	인천 강화군	#자연#강화도#수도권#섬여행#역사유적지#관광지
4	5	강화 전등사	인천 강화군	#전등사#템플스테이#사찰&산사#전통&역사문화체험#서울근교여행#수도권#당일치기여행#아...
5	6	강화루지(강화씨사이드리조트)	인천 강화군	#관광지#당일코스#1박2일#인천가볼만한곳#강화도가볼만한곳#강화도#강화루지#강화도루지...
6	7	강화문학관	인천 강화군	#문화시설#인천권#강화문학관#교육프로그램#조경희문학관#문학관#문학전시#문학
7	8	강화 화개산 모노레일	인천 강화군	#관광지#화개모노레일#인천화개산모노레일#인천모노레일#강화모노레일#강화도여행#인천화개...
8	9	고려천도공원	인천 강화군	#관광지#고려천도공원#강화도역사문화유적지#강화도천도#민통선안보관광코스#민통선내부공원...
9	10	강화오상리고인돌군	인천 강화군	#관광지#강화오상리고인돌군#인천시기념물#고인돌#오상리고인돌#강화고인돌#청동기시대유적





os.chdir('C:/kd/ws_python/rpa') 
# os.chdir() 함수는 현재 작업 디렉토리를 지정된 경로로 변경합니다. 
#이 코드에서는 'C:/kd/ws_python/rpa'로 작업 디렉토리를 변경하고 있습니다. 

new_folder = 'data' # data란 파일명 지정
#이 변수에 생성하고자 하는 새 폴더의 이름인 'data'를 할당합니다.

if os.path.exists(new_folder) == False: 
# os.path.exists() 함수는 주어진 경로에 파일 또는 폴더가 존재하는지 확인합니다. 
#이 함수는 경로가 존재하면 True를, 존재하지 않으면 False를 반환합니다.
    os.mkdir(new_folder) 
    # os.mkdir() 함수는 지정된 이름으로 새로운 폴더를 생성합니다. 
profile
Diamond

0개의 댓글