Jupyter Notebook & Selenium & Crawling

현서·2025년 2월 3일

파이썬 웹서비스

목록 보기
2/7
post-thumbnail

1. Jupyter Notebook

1. 모드(mode)

  • 일반 모드(Command mode): 셀을 선택하고 이동하거나, 셀을 추가, 삭제 등의 작업을 수행(Enter)
  • 편집 모드(Edit mode): 셀의 내용을 편집하거나 코드를 작성할 수 있음(Esc)

2. 일반 모드 단축키

A: 셀 위에 새로운 셀 추가
B: 셀 아래 새로운 셀 추가
D, D: 선택된 셀 삭제
y: 선택된 셀 코드 셀로 변경
m: 선택된 셀 마크다운 셀로 변경
z: 셀 삭제를 취소

3. 편집 모드 단축키

컨트롤 + Z : 되돌리기
컨트롤 + Y : 되돌리기 취소
컨트롤 + A : 셀 내용 전체 선택
컨트롤 + X : 선택한 내용 잘라내기
컨트롤 + C : 선택한 내용 복사하기
컨트롤 + V : 선택한 내용 붙여넣기
컨트롤 + Home: 셀 맨 위로 이동
컨트롤 + End: 셀 맨 아래로 이동
컨트롤 + D: 현재 줄 삭제
쉬프트 + 탭: 도움말 툴팁 표시
탭: 자동 완성 기능

다음 내용 부터는 Jupyter Notebook에서 실행한 것이다.
명령 프롬프트 창에서 pip install jupyter notebook 을 입력하여 jupyter notebook을 설치한다.
Jupyter Notebook을 설치한 뒤, 명령 프롬프트 창에서 jupyter notebook 을 입력하고 엔터를 누르면 웹이 열리게 된다.

2. 셀레니움

Selenium : 웹 애플리케이션을 자동화하기 위한 오픈 소스 툴.
브라우저를 프로그래밍적으로 제어하여 사람처럼 웹을 탐색하거나 상호작용할 수 있게 한다.
주로 웹 테스트 자동화와 크롤링에 사용되며, 동적인 콘텐츠나 자바스크립트 렌더링이 필요한 웹 페이지에서도 효과적으로 동작한다.
Selenium WebDriver를 사용하면 Python, Java, C# 등 다양한 프로그래밍 언어로 브라우저를 제어할 수 있으며, Chrome, Firefox, Edge 등 여러 브라우저에서 작업이 가능하다.
이를 통해 로그인, 폼 제출, 버튼 클릭, 데이터 스크랩과 같은 작업을 자동화할 수 있다.

!pip install selenium
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.get('https://www.google.com')
search = driver.find_element('name','q')
search.send_keys('크리스마스')
search.send_keys(Keys.RETURN)
# pip install bs4
from bs4 import BeautifulSoup
driver = webdriver.Chrome()
driver.get('https://www.google.com')
html = driver.page_source
soup = BeautifulSoup(html)
search = soup.select('#APjFqb')

3. 네이버 웹툰 크롤링

import time
driver = webdriver.Chrome()
driver.get('네이버 웹툰 중 맘에 드는 만화 주소')
soup = BeautifulSoup(driver.page_source)
comment_area = soup.find_all('span',{'class','u_cbox_contents'})

print('********** 베스트 댓글 **********')
for i in range(len(comment_area)):
    comment = comment_area[i].text.strip()
    print(comment)
********** 베스트 댓글 **********
자까님 이런거로 하미티콘 만들어주시면 안 될까요.......
입이... 말도 안되게 귀여워
수십년뒤에도 고기만 먹습니다 등등 베스트 댓글들이 출력되었다...!
driver.find_element('xpath','/html/body/div[1]/div[5]/div/div/div[5]/div[1]/div[3]/div/div/div[4]/div[1]/div/ul/li[2]/a/span[2]').click()
time.sleep(2)
soup = BeautifulSoup(driver.page_source)
comment_area = soup.find_all('span',{'class','u_cbox_contents'})

print('********** 전체 댓글 **********')
for i in range(len(comment_area)):
    comment = comment_area[i].text.strip()
    print(comment)
********** 전체 댓글 **********
하미 업고 튀어
녀러분 이번에 자까님이 테런에 등장했습니다 🙃 엄청 귀엽게 나왔어요😁 등등 출력되었다.

4. 야놀자 리뷰 크롤링

def crawl_yanolja_reviews(name, url):
    review_list = []
    driver = webdriver.Chrome()
    driver.get(url)
    time.sleep(3)

    scroll_count = 3
    for i in range(scroll_count):
        driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
        time.sleep(2)

    html = driver.page_source
    soup = BeautifulSoup(html)

    review_containers = soup.select('#__next > section > div > div.css-1js0bc8 > div > div > div')
    review_date = soup.select('#__next > section > div > div.css-1js0bc8 > div > div > div > div.css-1toaz2b > div > div.css-1ivchjf > p')
    #print(len(review_containers))
    #print(review_date)
    for i in range(len(review_containers)):
        review_text = review_containers[i].find('p', class_='content-text').text
        review_stars = review_containers[i].find_all('path',{'fill':'#FDBD00'})
        #print(review_text)
        star_cnt = len(review_stars)
        #print(star_cnt)
        date = review_date[i].text
        #print(date)
        #print('******')
        review_dict = {
            'review': review_text,
            'stars' : star_cnt,
            'date' : date
        }
        review_list.append(review_dict)
    print(review_list)
crawl_yanolja_reviews(name='야놀자',url='야놀자 리뷰 주소')
[{'review': '객실 너무 좋았어요! 전기그릴이라고 해서 걱정했는데 그냥 숯대신 전기쓰는였어요. 등 리뷰들 출력됨.

5. 요기요 리뷰 크롤링

import re # 정규표현식 처리를 위한 모듈
import time
from bs4 import BeautifulSoup
from selenium import webdriver
# NoSuchElementException: 찾으려는 요소가 없는 경우
# TimeoutException: 특정 시간이 지나도 조건이 충족되지 않을 때
# ElementNotInteractableException: 요소가 상호작용 불가능할 때
from selenium.common.exceptions import NoSuchElementException, TimeoutException, ElementNotInteractableException
from selenium.webdriver.common.by import By
# 특정 조건을 기다릴 때 사용
from selenium.webdriver.support import expected_conditions as EC
# 조건이 충족될 때까지 대기
from selenium.webdriver.support.ui import WebDriverWait

5-1. 정규 표현식

정규 표현식(regular expression) : 문자열에서 특정 패턴을 찾거나 검증하거나 변경할 때 유용하게 사용되는 표현식

# r(row string): 이스케이프 처리되지 않도록 만듦
# f: 문자열 안에 변수를 삽입하거나 표현식을 평가하여 문자열에 포함
# Dr.Go@naver.com
email_pattern = r'^[a-zA-Z0-9]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'

user_input = input('이메일을 입력하세요: ')

if re.match(email_pattern, user_input):
    print('유효한 이메일 주소입니다.')
else:
    print('올바르지 않은 이메일 형식입니다.')

이메일을 입력하세요: apple@email.com
유효한 이메일 주소입니다.

5-2. 전역 변수

BASE_URL = 'https://www.yogiyo.co.kr/mobile/#/'
URL = [
    'https://www.yogiyo.co.kr/mobile/#/숫자/'
    # 'https://www.yogiyo.co.kr/mobile/#/숫자/'
    # 'https://www.yogiyo.co.kr/mobile/#/숫자/'
    # 'https://www.yogiyo.co.kr/mobile/#/숫자/'
]

5-3. 크롤링 함수

def crawl_single_restaurant(url):
    chrome_options = webdriver.ChromeOptions()
    prefs = {'profile.default_content_setting_values.geolocation': 2}
    chrome_options.add_experimental_option('prefs',prefs)

    driver = webdriver.Chrome(options=chrome_options)
    driver.get(BASE_URL)
    time.sleep(3)

    search_box = WebDriverWait(driver, 10).until(
        EC.visibility_of_element_located((By.XPATH, '//*[@id="search"]/div/form/input'
    )))

    my_address = '역삼동'
    search_box.send_keys(my_address)

    search_btn = WebDriverWait(driver, 10).until(
        EC.visibility_of_element_located((By.XPATH, '//*[@id="button_search_address"]/button[2]'
    )))
    search_btn.click()
    time.sleep(2)

    first_address = WebDriverWait(driver, 10).until(
        EC.visibility_of_element_located((By.XPATH, '//*[@id="search"]/div/form/ul/li[3]'
    )))
    first_address.click()
    time.sleep(3)

    driver.get(url)
    time.sleep(5) 

    clean_review_btn = driver.find_element(By.XPATH, '//*[@id="content"]/div[2]/div[1]/ul/li[2]')
    clean_review_btn.click()
    
    while True:
        try:
            more_btn = WebDriverWait(driver, 3).until(
                EC.element_to_be_clickable((By.XPATH, '//*[@id="review"]/li/a'
            )))
            more_btn.click() 
            driver.execute_script('window.scrollTo(0, document.body.scrollHeight);')
            time.sleep(3)
        except (NoSuchElementException, TimeoutException, ElementNotInteractableException):
            break

    soup = BeautifulSoup(driver.page_source, 'html.parser')
    restaurant_name = soup.select_one(
    '#content > div.restaurant-detail.row.ng-scope > div.col-sm-8 > div.restaurant-info > div.restaurant-title > span').get_text(
    strip=True)
    reviews = soup.select('#review > li > p')
    review_texts = [review.get_text(strip=True) for review in reviews][1:]
    # print(review_texts) 
    menus = soup.select('#review > li > div.order-items.ng-binding')
    all_menu = [menu.get_text(strip=True) for menu in menus]
    # print(all_menu)

    document = {
        "restaurant": restaurant_name,
        "url": url,
        "reviews": []
    }

    for menu, text in zip(all_menu, review_texts):
        document['reviews'].append({
            "menus": menu,
            "review_text": text
        })

    print(document)
crawl_single_restaurant('https://www.yogiyo.co.kr/mobile/#/숫자/')
{'restaurant': '파파이스-강남점', 'url': , 'reviews': [{'menus':   'review_text':   }] 등등 출력됨.
profile
The light shines in the darkness.

0개의 댓글