웹크롤링(web crawling) 클라우드 플레어 우회하기

웹 크롤링을 할 때 클라우드 플레어를 사용하는 사이트의 경우 봇 확인을 하게되는데요. web crawling 방법은 여러가지가 있는데요.

이 경우에는 정상적으로 크롤링이 되지 않습니다. 그래서 오늘은 봇 확인을 우회해서 크롤링하는 방법을 알아보겠습니다.

클라우드플레어 우회해서 크롤링하기

먼저 크롬웹사이트를 디버그로 열 필요가 있습니다. 주요 사이트는 Cloudflare 같은 보안 솔루션을 사용하는 경우가 많아서 봇으로 인식되면 크롤링이 안되는데요. 그래서 셀레니움에서 바로 실행하는 것보다 이미 띄워져 있는 크롬 페이지를 활용해서 크롤링하면 우회가 가능합니다

그래서 먼저 크롬을 디버그 모드로 실행하는 것인데요.

achrm01
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="C:/selenium/AutomationProfile"

이후 웹사이트를 크롤링하면 됩니다.

pip install selenium webdriver-manager

아래의 경우 예시로 크롬에서 모든 P태그를 불러오는 형태의 코드를 작성한 것입니다.

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import os

def crawl_by_p_tags():
    chrome_options = Options()
    # 디버깅 모드로 실행 중인 크롬에 연결
    chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")

    driver = webdriver.Chrome(options=chrome_options)
    wait = WebDriverWait(driver, 20)

    try:
        # 1. 게시물 목록 분석
        print("게시물 목록 수집 중...")
        select_element = wait.until(EC.presence_of_element_located((By.NAME, "wr")))
        options = select_element.find_elements(By.TAG_NAME, "option")
        
        episode_list = []
        for opt in options:
            episode_list.append({
                'id': opt.get_attribute('value'),
                'title': opt.text.strip()
            })
        
        episode_list.reverse() # 처음부터
        
        if not os.path.exists('저장'):
            os.makedirs('저장')

        # 2. 각 게시물 접속 및 p 태그 복사
        for ep in episode_list:
            target_url = f"https://site.com/test/{ep['id']}"
            driver.get(target_url)
            
            try:
                # 본문 영역이 로딩될 때까지 대기
                wait.until(EC.presence_of_element_located((By.ID, "content")))
                
                # 본문(#content) 내부에 있는 모든 <p> 태그 찾기
                p_tags = driver.find_elements(By.CSS_SELECTOR, "#content p")
                
                # 각 p 태그의 텍스트를 추출하여 줄바꿈으로 연결
                content_list = [p.text.strip() for p in p_tags if p.text.strip()]
                full_text = "\n".join(content_list)
                
                if len(full_text) < 100: # 본문이 너무 짧으면 로딩 실패로 간주
                    print(f"경고: {ep['title']} 본문이 너무 짧습니다. 확인이 필요합니다.")
                
                # 파일 저장
                safe_title = "".join([c for c in ep['title'] if c.isalnum() or c in (' ', '_')]).strip()
                with open(f"저장/{safe_title}.txt", "w", encoding="utf-8") as f:
                    f.write(full_text)
                
                print(f"저장 성공: {ep['title']} (총 {len(content_list)} 문단)")
                
            except Exception as e:
                print(f"오류 발생 ({ep['title']}): {e}")
                # 봇 탐지 창이 떴는지 확인하기 위해 수동 확인 시간 부여
                time.sleep(10) 
            
            time.sleep(2) # 간격 유지

    except Exception as e:
        print(f"프로그램 중단: {e}")

if __name__ == "__main__":
    crawl_by_p_tags()

이런 형태로 전체 불러오면 클라우드 플레어를 우회해서 크롤링이 가능합니다.

기본적으로 크롤링할때 셀레니움을 많이 사용하였는데요. 셀레니움 역시 봇으로 판단하는 사이트 등이 있을 경우 이런 방법으로 우회가 가능합니다.

혹시 웹 크롤링을 개발한다면 이런 방법도 있으니 참고해보시기 바랍니다.

  이 사이트는 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

Leave a Comment