Python

Python: 웹 크롤링

작심반복하기 2025. 6. 14. 15:25

* 크롤링 하기 전에 주의할 점 

1.  사이트 링크에 /robots.txt를 추가해 user =  allow 가 떠 있는 지 확인하기!   

(가장 좋은 것은 크롤링 페이지 이용약관 읽어보기) 

* 크롤링 시 주의할 점

1. 너무 많은 양을 크롤링하면 서버 과부하가 걸릴 수 있으니, 조금씩 나눠서 텀을 두고 하기 

2. 단계 설정 상세히 하기 
예: 메인페이지 -> 검색창 클릭 -> 검색어 입력 및 Enter -> 광고제거 -> 상세페이지 이동 

 

======================================================

[1] 필요한 라이브러리 불러오기 

import pandas as pd  # 표 형태 데이터를 다루기 위함 (excel, csv dataframe 작업용) 
from selenium import webdriver # 크롬 웹 브라우저 자동 제어용 
from selenium.webdriver.common.by import By # HTML 요소 검색 기준 설정 
from selenium.webdriver.chrome.service import Service # 크롬 드라이버의 서비스 객체 생성 
from selenium.webdriver.support.ui import WebDriverWait # 웹페이지 완전 로드까지 기다려주는 용도
from selenium.webdriver.support import expected_conditions as EC # 웹페이지 완전 로드까지 기다려주는 용도
from webdriver_manager.chrome import ChromeDriverManager # 크롬 버전 충돌 방지 
import logging # 코드 실행 과정의 메시지 기록해주는 로깅 기능 
import os # 운영체제 관련 작업
import time # 일정 시간 쉬거나 지연할 수 있도록 도와주는 기능

 

[2] 로깅 설정 

* 로깅 : 프로그램의 "일기장" 역할 

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

 

  • logging.basicConfig( )
    => 로깅의 기본 설정 함수 
  • level=logging.INFO  
    => 로그에는 여러 중요도 레벨이 있다. 
    예: DEBUG(디버깅용), INFO(정보), WARNING(경고), ERROR(에러), CRITICAL(치명적 에러)
    INFO로 설정하면, INFO 이상의 레벨(INFO, WARNING, ERROR, CRITICAL)만 기록 (DEBUG는 무시)
  • format='%(asctime)s - %(levelname)s - %(message)s'
    % : 특정 값을 넣어달라는 기호 
    s : 문자열 
    : 그냥 구분 기호 
  • logger
    => 로그 실제 기록 도구 
    __name__ : Python 파일 이름을 자동으로 가져오는 변수 

 

[3] 엑셀 파일에서 company_names 불러오기 

excel_file = pd.read_excel(r"파일경로")
company_names = excel_file['company_names'].dropna().tolist() #company_names 내의 빈칸 제거 후, 리스트로 저장
logger.info(f"총 {len(company_names)}개의 열 이름 로드 성공") #불러온 company_names 수 로그로 출력

 

* company_names를 불러온 이유 : 크롤링 할 페이지를 검색할 때 사용하기 위함 

 

[4] 크롭 드라이버 설정 

service = Service(ChromeDriverManager().install()) #크롬 드라이버 설치 후 서비스 객체로 만들기 
options = webdriver.ChromeOptions() # 크롬 브라우저에 적용할 옵션 설정 

options.add_argument("--no-sandbox") # 샌드박스 모드 비활성화 
options.add_argument("--disable-dev-shm-usage") # 공유 메모리 사용 X 
options.add_argument("user-agent=...")  # 사용자 브라우저처럼 가장
options.add_argument("--disable-notifications") # 크롬 알림 기능 비활성화
options.add_argument("--disable-popup-blocking") #팝업 차단 기능 비활성화 
options.add_argument("--block-new-web-contents") # 새 창 열림 방지  
options.add_argument("--disable-features=PrivacySandboxAdsAPIs") # 광고추적 기능 비활성화 

driver = webdriver.Chrome(service=service, options=options) #설정한 옵션을 바탕으로 크롬 브라우저 실행

wait = WebDriverWait(driver, 30) #요소가 나타날 때까지 최대 30초 기다리는 기능 설정

 

[5] 결과 담을 리스트 준비 

results = []

 

[6] company_names 하나씩 처리 

for idx, company_name in enumerate(company_names, 1): #업체 리스트에서 하나씩 꺼내보기 반복 

logger.info(f"[{idx}/{len(company_names)}] company_names 처리 중: {company_name}")
first_result = None

# 현재 처리 중인 company_names 로그에 기록 
# 검색 결과(사업자 번호) 임시 저장변수 초기화

 

[7] 웹사이트 접속 및 검색 

driver.get("크롤링할 사이트 링크")
search_box = wait.until(EC.presence_of_element_located((By.NAME, "query")))
search_box.clear()
search_box.send_keys(company_name)
search_box.submit()

 

  • get()은 사이트 열기.
  • wait.until(...)은 검색창이 나올 때까지 기다림.
  • 검색창에 업체명을 입력하고 엔터 클릭 기능 

 

[8] 검색 결과 중 첫 번째 기업 클릭 

possible_link_selectors = [...]  # 다양한 CSS 선택자 리스트
first_link = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, selector)))
first_link.click() #첫 번째 검색 결과 클릭

 

 

[9] 상세 페이지에서 사업자 등록 번호 추출 

rows = driver.find_elements(By.CSS_SELECTOR, "table.table_guide01 tr") #표 안의 각 행 가져오기 

for row in rows:
    th = row.find_element(By.CSS_SELECTOR, "th")
    if th.text.strip() == "사업자등록번호":
        td = row.find_element(By.CSS_SELECTOR, "td")
        first_result = td.text.strip()
        break   # '사업자 등록 번호'가 있는 행을 찾아 값 가져오기

 

[10] 광고 제거 

driver.execute_script("...광고 제거 JS...")
time.sleep(0.5)

 

[11] 오류 발생 시 HTML 저장  (문제 발생한 부분 체크) 

html = driver.page_source
with open(f"detail_page_{company_name}.html", "w", encoding="utf-8") as f:
    f.write(html)

 

[12] 결과 저장  및 브라우저 종료 

results.append({"company_names": company_name, "사업자등록번호": first_result})
print(f"company_names: {company_name}, 사업자등록번호: {first_result}")

#엑셀로 결과 저장 
result_df = pd.DataFrame(results)
result_df.to_excel(output_file, index=False)

#드라이버 종료 
driver.quit()

logger.info("웹드라이버 종료")