티스토리 뷰

Web Crawling

Scrapy 구조 알아보기

nickas 2020. 5. 17. 19:38

Scrapy를 잘 사용하기 위해 구조와 작동 순서를 아는것이 필요.

Components

Scrapy는 아래와 같은 component들로 구성되어 있다.

  • Scrapy Engine
    각 component들에 데이터(Request, Response, Item)를 전달(Controller)하고 액션이 발생 했을 때 이벤트를 발생시키는 역활을 함.
  • Scheduler
    엔진으로 부터 Request을 전달 받고 이 Request을 queue에 추가한 후 나중에 엔진이 Request를 요청할 때 다시 엔진에 전달.
  • Downloader
    Request에 포함된 URL에서 웹 페이지를 가져와서 Response 오브젝트를 만들어 엔진에게 전달하는 역활을 한다. 엔진은 전달 받은 이 웹 페이지를 다시 스파이더에게 전달.
  • Spider
    요청할 URL을 사용하여 Request 오브젝트를 만들고, callback 메서드를 사용하여 Response에서 원하는 데이터를 추출하거나 Response에 포함된 URL을 사용하여 새로운 Request를 만드는 역활을 함.
  • Item Pipeline
    스파이더로 부터 추출된 아이템을 처리하는 역활을 함(정확히는 Item 오브젝트가 전달됨). 일반적으로 아이템을 cleansing, 검증 그리고 데이터베이스 같은 곳에 저장하는 일을 함.
  • Downloader middleware
    엔진과 다운로더 사이에 위치한 hook으로 엔진으로 부터 다운로더로 전달되는 Request를 처리하고, 다운로더로 부터 엔진으로 전달 되는 Response를 처리.
    아래와 같은 것이 필요할 경우 다운로더 미들웨어를 사용한다.
    • Request가 다운로더로 전달되기 전에 처리하기 위해. 예를 들어 웹사이트로 request를 보내기 전에 문제가 없는지 확인하기 위해.
    • Response를 스파이더로 전달되기 전에 변경하기 위해.
    • Response를 스파이더로 전달하는 대신 새로운 Request를 요청하기 위해.
    • 웹 페이지를 가져오지 않고 스파이더에 Response를 전달하기 위해.
    • 몇몇 Request를 drop하기 위해.
  • Spider middleware
    엔진과 스파이더 사이에 위치한 hook으로 스파이더의 input(Reponse)와 output(아이템과 Request)를 처리할 수 있다.
    아래와 같은 경우가 필요할 때 사용
    • 스파이더 콜백의 아웃풋인 Request와 아이템를 변경하거나 추가, 삭제.
    • start_requests의 후처리
    • 스파이터의 예외 처리
    • Response을 기반으로 Request들 중 일부에 callback을 호출하는 대신 errback를 호출(예를들어 response가 정상(200)이 아닌 경우 callback을 호출하지 않고 errback를 호출하여 처리)

데이터 흐름

데이터(request, response, item)이 Scrapy 시스템 안에서 어떻게 흘러 가는지 아래 그림이 설명해 주고 있다.

Scrapy Data Flow

Scrapy에서 데이터는 엔진에 의해서 컨트롤 되고 아래와 같이 흘러 간다.

  1. 엔진은 스파이더로 부터 crawl을 하기 위한 초기 Request 오브젝트를 받음.
  2. 엔진은 이 Request를 스케줄러 안에 등록하고 crawl를 진행 할 다음 Request를 요청.
  3. 스케줄러는 엔진에게 다음으로 crawl을 진행 할 Request을 전달.
  4. 엔진은 이 Request를 다운로더에 전달하고, Request는 다운로더로 전달되면서 다운로더 미들웨어를 거쳐 감. 내부적으로는 미들웨어의 process_request()를 실행.
  5. 다운로더는 Request 오브젝트에 포함되어 있는 URL의 페이지를 가져(fetch) 온 후 이 페이지를 이용하여 Response 오브젝트를 생성하고 엔진에게 다시 전달. Response는 엔진으로 전달되면서 다시 다운로더 미들웨어를 거쳐 감. 내부적으로는 미들웨어의 process_response()를 실행.
  6. 엔진은 다운로더로 부터 Response를 전달 받고 이 Response를 스파이더에게 전달. Response는 스파이더로 전달되면서 스파이더 미들웨어를 거쳐 감. 내부적으로는 미들웨어의 process_spider_input()를 실행.
  7. 스파이더는 Response를 처리하고 스크랩한 아이템과 새로운 Request를 엔진에게 전달(Response에 포함된 링크를 따라 Request를 만들 경우). 스크랩과 새로운 Request는 엔진으로 전달되면서 스파이더 미들웨어를 거쳐 감. 내부적으로는 미들웨어의 process_spider_output()를 샐행.
  8. 엔진은 아이템을 Item Pipelines에 전달하고 새로운 Request는 스케쥴러에 전달하면서 다음으로 crawl 해야 하는 Request를 요청.
  9. 이 모든 프로세스는 스케쥴러로 부터 더 이상 Request가 없을 때 까지 1번 부터 반복적으로 진행.

위 절차를 요약 하자면,

  1. 내가 작성한 스파이더에서 Request 오브젝트를 만들어 리턴하면
  2. 다운로더가 페이지를 가져와서 Response 오브젝트를 만들어 스파이더로 전달해 주고
  3. 스파이더는 내가 작성한 callback를 실행해서 내가 원하는 아이템을 추출하고 파이프라인으로 전달.
  4. 내가 작성한 파이프라인이 있으면(데이터베이스로 저장 등) 파이프라인에서 아이템을 다시 처리하고 더 이상 Request가 없을 때 까지 반복.

ReqeustResponse가 전달되는 과정에서 미들웨어들을 거쳐감.

'Web Crawling' 카테고리의 다른 글

Scrapy 간단 사용법  (0) 2020.05.10
최근에 올라온 글
글 보관함