[카테고리:] 미분류

  • 웹 크롤링에서 파일 저장 문제 해결하기: 크롤러 개선 사례

    문제 상황: 크롤링은 되지만 파일이 저장되지 않는 현상

    많은 크롤링 프로젝트에서 흔히 발생하는 문제 중 하나는 웹페이지 탐색과 데이터 추출은 성공적으로 이루어지지만, 추출한 데이터(JSON)나 이미지 파일이 실제로 저장되지 않는 현상입니다.

    특히 다음과 같은 증상이 나타날 수 있습니다:

    • 코드 실행 중 오류 메시지는 없지만 파일이 생성되지 않음
    • 디렉토리 경로 문제로 인한 파일 저장 실패
    • 권한 문제로 인한 파일 쓰기 실패
    • 상대 경로와 절대 경로의 혼용으로 인한 문제

    문제 해결을 위한 핵심 접근 방법

    1. 디버깅 코드 추가

    파일 저장 문제를 해결하기 위한 첫 번째 단계는 상세한 디버깅 정보를 추가하는 것입니다. 다음과 같은 정보를 로깅하면 문제 진단에 도움이 됩니다:

    # 디렉토리 경로 확인
    print(f"DEBUG - 이미지 저장 디렉토리: {os.path.dirname(filepath)}")
    print(f"DEBUG - 디렉토리 존재 여부: {os.path.exists(os.path.dirname(filepath))}")
    
    # 파일 저장 시도 전후 상태 확인
    print(f"DEBUG - 파일 쓰기 시작: {filepath}")
    # 파일 쓰기 작업
    print(f"DEBUG - 파일 쓰기 완료")
    
    # 파일 생성 확인
    if os.path.exists(filepath):
        print(f"파일 저장 성공: {filepath} (크기: {os.path.getsize(filepath)} 바이트)")
    else:
        print(f"파일이 생성되지 않음: {filepath}")
    

    2. 다중 저장 경로 전략

    단일 경로에만 의존하지 않고, 여러 단계의 대체 경로를 준비하는 것이 좋습니다:

    try:
        # 기본 경로에 저장 시도
        with open(filepath, 'wb') as file:
            file.write(response.content)
        print(f"파일 쓰기 완료: {filepath}")
    except Exception as file_err:
        print(f"파일 쓰기 오류: {file_err}")
        # 대체 경로 시도
        alt_filepath = os.path.join('./images', os.path.basename(filepath))
        try:
            os.makedirs('./images', exist_ok=True)
            with open(alt_filepath, 'wb') as file:
                file.write(response.content)
            print(f"대체 경로에 파일 쓰기 완료: {alt_filepath}")
            filepath = alt_filepath  # 경로 업데이트
        except Exception as alt_err:
            print(f"대체 경로 파일 쓰기 오류: {alt_err}")
    

    3. 디렉토리 생성 확인 강화

    파일을 저장하기 전에 디렉토리가 확실히 존재하는지 확인하고, 권한 테스트를 수행합니다:

    dir_path = os.path.dirname(filepath)
    if not os.path.exists(dir_path):
        print(f"디렉토리 생성 시도: {dir_path}")
        os.makedirs(dir_path, exist_ok=True)
        
        # 폴더 권한 테스트
        test_file = os.path.join(dir_path, 'test_write.txt')
        try:
            with open(test_file, 'w') as f:
                f.write('test')
            os.remove(test_file)
            print(f"쓰기 권한 확인 완료")
        except Exception as e:
            print(f"쓰기 권한 문제 발생: {e}")
    

    실제 적용 사례: 크롤러 개선

    위의 방법론을 적용하여 크롤러의 파일 저장 문제를 해결한 코드 중 핵심 부분을 살펴보겠습니다.

    이미지 다운로드 함수 개선

    def download_image(url, filepath, max_retries=3):
        """이미지 다운로드 함수 - 재시도 로직 추가 및 디버깅 개선"""
        if not url:
            print("이미지 URL이 없습니다.")
            return False
            
        # URL 유효성 검사
        try:
            parsed_url = urlparse(url)
            if not parsed_url.scheme or not parsed_url.netloc:
                print(f"잘못된 URL 형식: {url}")
                return False
        except Exception as e:
            print(f"URL 파싱 오류: {url}, 에러: {e}")
            return False
            
        # 파일 저장 전 디렉토리 명시적 확인
        try:
            dir_path = os.path.dirname(filepath)
            if not os.path.exists(dir_path):
                print(f"디렉토리 생성 시도: {dir_path}")
                os.makedirs(dir_path, exist_ok=True)
        except Exception as dir_err:
            print(f"디렉토리 생성 오류: {dir_err}")
            
        # 재시도 로직
        for attempt in range(max_retries):
            # 다운로드 시도 코드
            # ...
            
            # 파일이 실제로 생성되었는지 확인
            if os.path.exists(filepath) and os.path.getsize(filepath) > 0:
                print(f"이미지 다운로드 성공: {filepath} (크기: {os.path.getsize(filepath)} 바이트)")
                return True
    

    JSON 파일 저장 함수 개선

    def save_json(data, filepath):
        """JSON 파일 저장 함수 - 예외 처리 및 디버깅 개선"""
        try:
            # 디렉토리 확인 및 생성
            dir_path = os.path.dirname(filepath)
            if not os.path.exists(dir_path):
                os.makedirs(dir_path, exist_ok=True)
                
            # 파일 쓰기
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(data, f, ensure_ascii=False, indent=2)
                
            # 파일 생성 확인
            if os.path.exists(filepath):
                print(f"JSON 파일 저장 성공: {filepath} (크기: {os.path.getsize(filepath)} 바이트)")
                return True
            else:
                print(f"JSON 파일이 생성되지 않음: {filepath}")
                return False
        except Exception as e:
            print(f"JSON 파일 저장 중 오류: {filepath}, 에러: {e}")
            
            # 대체 경로 시도
            alt_filepath = f"./backup_{os.path.basename(filepath)}"
            try:
                with open(alt_filepath, 'w', encoding='utf-8') as f:
                    json.dump(data, f, ensure_ascii=False, indent=2)
                return True
            except:
                return False
    

    추가 개선 사항: 크롤링 안정성 향상

    파일 저장 외에도 크롤링의 전반적인 안정성을 높이기 위한 몇 가지 추가 개선 사항을 적용했습니다:

    1. 다양한 선택자 시도

    웹사이트 구조가 변경될 수 있으므로, 여러 가능한 선택자를 순차적으로 시도합니다:

    product_selectors = [
        'div.c_listing > ul > li',  # 기본 리스트 뷰
        'div.c_prd_list > ul > li',  # 대체 리스트 뷰
        'div.search_product_wrap li',  # 다른 가능한 선택자
        # 더 넓은 선택자들...
    ]
    
    for selector in product_selectors:
        products = page.query_selector_all(selector)
        if products:
            used_selector = selector
            print(f"제품 선택자 발견: {selector}, {len(products)}개")
            break
    

    2. 예외 처리 강화

    각 상품 처리 과정을 개별적인 try-except 블록으로 감싸 한 상품의 처리 실패가 전체 프로세스에 영향을 미치지 않도록 합니다:

    for i, product in enumerate(products):
        try:
            # 상품 처리 코드
            # ...
        except Exception as e:
            print(f"상품 #{i + 1} 처리 중 에러: {e}")
            continue
    

    3. 진행 상태 모니터링

    정기적으로 중간 결과를 저장하고 진행 상황을 출력합니다:

    print(f"{page_num} 페이지 수집 완료, 이 페이지에서 {len(page_results)}개 수집됨, 현재까지 총 {len(all_results)}개 수집됨.")
    
    # 중간 저장
    if page_results:
        if save_json(all_results, json_path):
            print(f"중간 저장 완료: {json_path}")
        else:
            print(f"중간 저장 실패. 대체 경로에 저장 시도...")
    

    결론: 견고한 크롤러 설계 원칙

    웹 크롤링 프로젝트에서 파일 저장 문제를 해결하고 안정성을 높이기 위한 핵심 원칙을 정리하면 다음과 같습니다:

    1. 상세한 디버깅 정보 – 각 단계마다 충분한 로그를 남깁니다
    2. 다중 저장 전략 – 여러 경로에 저장을 시도합니다
    3. 명시적 경로 확인 – 모든 파일 작업 전에 경로와 권한을 확인합니다
    4. 다양한 선택자 대응 – 웹사이트 구조 변경에 대비합니다
    5. 강력한 예외 처리 – 부분적 실패가 전체 프로세스를 중단시키지 않도록 합니다
    6. 정기적 중간 저장 – 진행 중인 작업 결과를 안전하게 보존합니다

    이러한 원칙을 적용하면 더 견고하고 신뢰할 수 있는 웹 크롤러를 개발할 수 있습니다. 특히 대규모 데이터 수집 프로젝트에서는 이러한 안정성 확보가 프로젝트 성공의 핵심 요소가 됩니다.