[세션] 웹크롤링

yeji·2025년 1월 3일
0

Python

목록 보기
34/36

클롤링과 스크래핑

웹크롤링

  • 웹상에 존재하는 모든 웹 페이지를 방문하여 데이터를 수집하는 방법
  • 웹사이트에 대한 정보를 색인화하고 저장하는 데 사용

웹스크래핑

  • 특정 웹 사이트나 페이지에서 필요한 데이터를 자동으로 추출해 내는 것
  • 분석 및 기타 목적을 위해 웹사이트에서 데이터를 추출하는 데 사용

주의사항

  • 합법 이슈가 있기에 사전에 확인 필요
  • 스크래핑/크롤링을 수행하기 전, 해당 웹 사이트의 robots.txt 파일을 반드시 확인하고 로봇 배제 표준을 준수하는지 확인하는 과정 필요
https://www.youtube.com/robots.txt

웹(WEB) 구성요소

  • HTML(Hyper Text Markup Language) : 웹 사이트의 뼈대
  • CSS(Cascading Style Sheets) : 예쁘게 꾸며서 표현
  • javascript : 동작하게 만듦

HTML 의 구조

  • 루트 요소(html) : HTML 문서의 최상위 요소이며, 다른 HTML 요소들을 포함하는 부모 요소
  • 헤드(Head) : HTML 문서의 메타데이터와 외부 리소스에 대한 정보를 포함하는 부분으로 화면에 직접적으로 보이지 않지만 웹 브라우저가 문서를 처리하고 표시하는 데 중요한 역할을 함
  • 본문(Body) : HTML 문서의 실제 내용을 담고 있는 부분으로 웹 페이지를 구성하는 모든 텍스트, 이미지, 링크, 테이블, 폼 등의 콘텐츠 포함
  • F12 버튼을 누르면 HTML 구조를 확인할 수 있음

XPATH

  • 'XML Path Language'의 줄임말로, XML 문서의 특정 요소 또는 속성에 접근하기 위한 경로를 지정하는 언어
  • div 태그 : Division의 준말로 HTML문서 내에서 한 개의 가로 공간(Block)을 만드는 태그
  • p 태그 : 단락, 절이라는 뜻의 Paragraph의 준말로 주로 문장에 대해서 사용하는 태그이며 한 개의 가로 공간(Block)을 만드는 태그
  • 모든 태그에는 id 속성과 class 속성을 지정해 줄 수 있는데, 이를 이용하면 CSS나 JavaScript에서 태그를 좀더 쉽게 다룰 수 있음
    • class : java에서 객체를 만들어내기 위한 틀
      → div class : ‘하나의 공간(클래스)를 만들겠다’는 뜻

라이브러리

BeautifulSoup

  • 웹데이터 크롤링을 위한 기초 라이브러리
  • HTML 태그(<>)를 기반으로 크롤링 진행
  • request 라이브러리를 통해 웹페이지를 호출하고 BeautifulSoup 라이브러리를 통해 웹에 접근된 상태에서 데이터 추출(파싱)
    • 웹 파싱 : 웹 상의 자연어, 컴퓨터 언어 등의 일련의 문자열들을 분석하는 프로세스
# 최초 1회 설치
pip install beautifulsoup4
pip install requests

import requests
from bs4 import BeautifulSoup as bs

url = "크롤링하려는 웹페이지의 주소"

# url에 담겨있는 http페이지 주소를 요청하여 그 주소의 요소들을 가져올 수 있도록 연결
response = requests.get(url)

# response라는 변수에 연결의 결과를 담고 
# response.content 으로 받아온 결과의 내용을 html.parser라는 html해석기로 내용을 html tag 구조로 해석
soup = bs(response.content,"html.parser")
# 처음 1회 설치
pip install beautifulsoup4
pip install requests

import requests
from bs4 import BeautifulSoup as bs

# request 라이브러리를 통한 http 통신호출
page = requests.get("https://library.gabia.com/")

# beautifulsoup 라이브러리를 이용한 page의 text 데이터 파싱(문자열 분석)
soup = bs(page.text, "html.parser")

# select 문법을 이용하여 html 내 필요한 부분을 모두 선택 
# div.esg-entry-content 에서 a 를 타고 그 아래로 span 을 타고 내려가서 text 를 불러옴
elements = soup.select('div.esg-entry-content a > span')

# for 구문을 통해 반복 수행
for index, element in enumerate(elements, 1):
    print("{} 번째 게시글의 제목: {}".format(index, element.text))

//*[@id="eg-55-post-id-13672"]/div/div[3]/div[3]/a/span

Selenium

  • 웹개발자들이 동적 웹이 제대로 작동하는지 테스트하기 위해 만들어진 모듈
  • '동적 크롤링'이 가능함(스크롤, 화면이동, 버튼 클링 등)
  • 크롬 등의 브라우저를 자동으로 열어 컨트롤하는 프레임워크
# pip install selenium
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
import time
import pandas as pd


import warnings # 경고창 무시
warnings.filterwarnings('ignore')

# 드라이버 설정 및 페이지넘버 설정(12로 설정함)
# 함수 구현
def get_movie_reviews(url, page_num=12):
    chrome_driver =  'C:/Users/user-pc/Downloads/chromedriver_win32/chromedriver.exe'
    wd = webdriver.Chrome(chrome_driver)

    wd.get(url)
    # 빈 리스트 생성
    writer_list=[]
    review_list=[]
    date_list=[]
    like_list=[]
    for page_no in range(1,page_num+1): # 1페이지에서 page_num까지의 리뷰 추출
        try:
            page_ul = wd.find_element_by_id('paging_point') # 페이지 포인트 코드 추출
            page_a = page_ul.find_element_by_link_text(str(page_no))
            page_a.click()
            time.sleep(2) # 페이지 로딩까지의 시간 두기

            writers = wd.find_elements_by_class_name('writer-name')
            writer_list += [writer.text for writer in writers]
            
            reviews = wd.find_elements_by_class_name('box-comment')
            review_list += [ review.text for review in reviews ]
            
            dates = wd.find_elements_by_class_name('day')
            date_list += [date.text for date in dates]
            
            likes = wd.find_elements_by_id('idLikeValue')
            like_list += [like.text for like in likes]            
                    
            if page_no%10==0: # 10이상의 값을 만났을 때 다음 페이지로 넘기기 버튼
                    if page_no==10:
                        next_button = page_ul.find_element_by_class_name("paging-side")
                        #next_button = page_ul.find_element_by_class_name('btn-paging next')
                        next_button.click()
                        time.sleep(2)
                    else:
                        next_button = page_ul.find_element_by_xpath('//*[@id="paging_point"]/li[13]/button').click()
                        time.sleep(2)
        except NoSuchElementException:
                break
    movie_review_df = pd.DataFrame({"Writer" : writer_list,
                                   "Review" : review_list,
                                   "Date" : date_list,
                                   "Like" : like_list})
    wd.close()
    return movie_review_df


# url 과 pagenum 을 입력하여 작성자, 리뷰내용, 작성날짜, 좋아요 수 요청 및 dataframe 반환
#범죄도시4 movie_review_df = get_movie_reviews("http://www.cgv.co.kr/movies/detail-view/?midx=88104#", page_num=3905)
movie_review_df = get_movie_reviews("http://www.cgv.co.kr/movies/detail-view/?midx=85813", page_num=12)

# dataframe 저장 
movie_review_df.to_csv('범죄도시2크롤링.csv', index=False, encoding="utf-8-sig")
profile
👋🏻

0개의 댓글