상세 컨텐츠

본문 제목

크롤링

인공지능/LLM 서비스 개발

by Ryuzy 2024. 11. 20. 16:06

본문

728x90
반응형

1. 크롤링

크롤링(Crawling)이란 웹 크롤러(Web Crawler) 또는 스크레이퍼(Scraper)라고 불리는 프로그램이나 스크립트를 사용하여 인터넷상의 웹 페이지에서 데이터를 자동으로 수집하는 과정을 말합니다. 주로 검색 엔진이 웹사이트를 탐색하고 색인(Index)에 추가하기 위해 사용하는 기술이며, 특정 주제나 데이터를 수집해 분석하는 데에도 활용됩니다. 크롤링은 HTML, CSS, JavaScript로 구성된 웹페이지 구조를 파싱(Parsing)하여 원하는 정보를 추출하고, 이를 활용 가능한 데이터 형식으로 저장합니다. 크롤링 시에는 웹사이트의 이용 약관과 로봇 배제 표준(Robots.txt)을 준수하여 법적, 윤리적 문제를 방지해야 합니다.

 

 

2. 셀레니움

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

# 구글 검색

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)

 

# 네이버 웹툰 크롤링

import time
from selenium import webdriver
from bs4 import BeautifulSoup

driver = webdriver.Chrome()
driver.get('https://comic.naver.com/webtoon/detail?titleId=783053&no=134&week=tue')
soup = BeautifulSoup(driver.page_source)
comment_area = soup.findAll('span', {'class', 'u_cbox_contents'})
print('********** 베스트 댓글 **********')
for i in range(len(comment_area)):
    comment = comment_area[i].text.strip()
    print(comment)
    print('-' * 30)

driver.find_element('xpath', '//*[@id="cbox_module_wai_u_cbox_sort_option_tab2"]/span[2]').click()
time.sleep(2)

soup = BeautifulSoup(driver.page_source)
comment_area = soup.findAll('span', {'class', 'u_cbox_contents'})

print('********** 전체 댓글 **********')
for i in range(len(comment_area)):
    comment = comment_area[i].text.strip()
    print(comment)
    print('-' * 30)

 

※ xpath

XPath는 XML 또는 HTML 문서 내에서 특정 요소나 속성을 선택하기 위해 사용되는 경로 표현 언어입니다. 웹 크롤링이나 자동화 도구에서 주로 사용되며, 요소를 효율적으로 찾을 수 있도록 도와줍니다. 일반적인 XPath는 특정 위치나 속성을 기준으로 요소를 선택하는 상대적인 경로를 사용합니다. 또한 full xpath는 루트 요소에서 시작하여 대상 요소까지의 절대적인 경로를 나타냅니다. 따라서 문서 구조가 변경되면 경로가 깨질 가능성이 높습니다.

 

# 야놀자 리뷰 크롤링

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

    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')

    for i in range(len(review_containers)):
        review_text = review_containers[i].find('p', class_='content-text').text
        date = review_date[i].text
        review_empty_stars = review_containers[i].find_all('path', {'fill-rule':'evenodd'})
        stars = 5 - len(review_empty_stars)

        review_dict = {
            'review':review_text,
            'star':stars,
            'date':date
        }
        review_list.append(review_dict)
    print(review_list)

crawl_yanolja_reviews('신라스테이 여수', 'https://www.yanolja.com/reviews/domestic/10046614')

 

# 요기요 리뷰 크롤링

import re
import time
from bs4 import BeautifulSoup
from selenium import webdriver
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

BASE_URL = 'https://www.yogiyo.co.kr/mobile/#/'
URL = ['https://www.yogiyo.co.kr/mobile/#/546259/',
       'https://www.yogiyo.co.kr/mobile/#/323347/',
       'https://www.yogiyo.co.kr/mobile/#/1227418/'
]

def crawl_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(2)

    search_box = WebDriverWait(driver, 5).until(
        EC.visibility_of_element_located((By.XPATH, '//*[@id="search"]/div/form/input'
    )))
    search_box.send_keys('역삼동')
    
    search_btn = WebDriverWait(driver, 5).until(
        EC.visibility_of_element_located((By.XPATH, '//*[@id="button_search_address"]/button[2]'
    )))
    search_btn.click()
    time.sleep(2)

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

    driver.get(url)
    time.sleep(2)
    
    clean_review_btn = driver.find_element(By.XPATH, '//*[@id="content"]/div[2]/div[1]/ul/li[2]/a')
    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(1)
        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)
    # print(restaurant_name)
    reviews = soup.select('#review > li')
    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_restaurant('https://www.yogiyo.co.kr/mobile/#/1357527/')
728x90
반응형

'인공지능 > LLM 서비스 개발' 카테고리의 다른 글

프롬프트 엔지니어링  (1) 2024.11.28
파이썬과 몽고DB 연동  (0) 2024.11.22
MongoDb  (1) 2024.11.21
인터넷과 웹서비스  (0) 2024.11.18
생성형 AI  (2) 2024.11.15

관련글 더보기