카테고리 없음

TIL 2025 04 17 크롤링 / 코드리뷰 내용 정리

200tmdghks 2025. 4. 17. 23:56

목차

1. 삼항 연산자, 줄바꿈, 예외 처리 관련 개선
2. Parser 인스턴스 변수화
3. HTTP 요청 책임 분리
4. JSON 응답 처리 개선 및 범용성 확보
5. 부모 클래스 재활용 및 예외 처리 개선

 

 


 

1. 삼항 연산자, 줄바꿈, 예외 처리 관련 개선

1-1. 리뷰 요지

  • PEP8 기준 한 줄 최대 79자 제한.
  • 삼항 연산자는 간결한 경우에만 사용 권장.
  • try 문은 예외 발생 가능 코드에 한정해야 명확함.

 

1-2. 반영 내용 및 설명

 

기존 코드

self._html = (
    request_html(self.url) if isinstance(parser_instance, RequestParser)
    else download_html(self.url)
)

 

수정 방향

  • 삼항 연산자가 길어지면 가독성 저하 -> 일반 if-else 구문으로 변경 필요.
  • download_html() 에서만 발생하는 DownloadFailed 예외는 해당 호출부만 try-except 처리.
  • request_html() 도 예외 발생 가능 -> 별도 try-except 처리 구조로 분리.

 

1-3. 예시

try:
    if isinstance(parser_instance, RequestParser):
        self._html = request_html(self.url)
    else:
        self._html = download_html(self.url)
except DownloadFailed:
    # 예외 처리 로직

 

 


 

2. Parser 인스턴스 변수화

 

2-1. 리뷰 요지

  • get_parser()에서 ParserNotFound 예외 발생 가능 -> 중복 처리 문제 있음.
  • _scrape() 내 중복된 로직 피하고, 인스턴스 변수로 전환 권장.

 

2-2. 반영 내용 및 설명

  • parser 변수를 JobDescriptionScraper 클래스의 인스턴스 변수로 선언.
  • 중복 제거 및 코드 가독성 향상 가능.
  • 해당 scraper 인스턴스 내에서 parser는 고정되므로, 상태 추적 어렵지 않음.

 

2-3. 예시

class JobDescriptionScraper:
    def __init__(self, ...):
        self.parser = get_parser(self.company_name)

 

 


 

3. HTTP 요청 책임 분리

 

3-1. 리뷰 요지

  • get_title_and_content_from_html() 내부에서 다시 HTTP 요청 발생 → 역할 중복.
  • HTTP 요청은 request_html()에서만 처리하는 구조로 책임 분리 필요.

 

3-2. 반영 내용 및 설명

  • Parser 클래스는 HTML 파싱만 담당.
  • 요청 관련 로직은 JobDescriptionScraper 에서 request_html() 호출 후 html 전달.
  • 다양한 사이트별 요청 조건(headers 등)은 parser의 클래스 변수에서 관리.
  • request_html()이 headers 등을 인자로 받아 유연하게 대응 가능 구조로 변경.

 

3-3. 예시

html = request_html(url, headers=parser.headers)
title, content = parser.get_title_and_content_from_html(html)

 

 


 

4. JSON 응답 처리 개선 및 범용성 확보

 

4-1. 리뷰 요지

  • 응답이 JSON이라고 가정하고 처리하는 것은 범용성 저해.
  • HTML, JSON, 일반 텍스트 등 다양한 응답 타입 처리 가능해야 함.
  • HTML 기반 추출은 _get_title_and_content_el() 로 위임.

 

4-2. 반영 내용 및 설명

  • 응답 타입에 따라 분기 처리 로직 구현:
    • HTML인 경우: 기존 HTML 파싱 방식 유지
    • JSON/text인 경우: 새로운 메소드에서 처리
  • 새로운 메소드 get_title_and_content_from_text() 작성
    • 내부에서 JSON 여부 확인 후 처리
  • get_title_and_content_from_html()은 HTML 문자열만 받도록 유지

 

4-3. 예시

def get_title_and_content_from_text(self, text):
    try:
        data = json.loads(text)
        content_html = data.get('content', '')
        return self.get_title_and_content_from_html(content_html)
    except json.JSONDecodeError:
        return '제목 없음', text

 

 


 

5. 부모 클래스 재활용 및 예외 처리 개선

 

5-1. 리뷰 요지

  • get_title_and_content_from_html() 내에서 중복된 파싱 로직 최소화.
  • 부모 클래스 메서드 호출로 공통 로직 재사용 권장.
  • 단, html 파라미터가 JSON 문자열이면 soup 생성 시 에러 발생 가능.

5-2. 반영 내용 및 설명

  • JSON 형태 문자열의 경우, content만 추출 후 부모 메서드에 전달.
  • html이 튜플로 전달되는 경우 soup에서 에러 발생 → 사전 분기 필요.
  • soup 객체 생성을 명확하게 보장하도록 html 정제 후 전달.

5-3. 예시

def get_title_and_content_from_html(self, html, url=None):
    if isinstance(html, tuple):
        html = html[0]
    soup = BeautifulSoup(html, 'html.parser')
    title_el, content_el = self._get_title_and_content_el(soup, url)
    ...