6. [프로젝트] 11번가 사이트 카테고리별 베스트 상품 크롤링 > 6-3. Request 메서드, callback과 meta 파라미터
Request 메서드, callback과 meta 파라미터
이전(2주차)에는 크롤링을 할 때 spider에서 콜백 함수 parse()를 이용하여 크롤링을 했었죠? 이번에는 그때와는 다른 방법으로, Request 메서드 내 callback 파라미터를 이용하여 크롤링을 해보려 합니다. 구조가 살짝 달라지게 되어서 당황하실 수 있지만 한줄 한줄 뜯어보시면 쉽게 이해하실 수 있을 겁니다 🤪
아래는 Request 메서드에 대한 간단한 설명입니다. 한 번 읽어보면 어려워서 이해가 안 갈 수도 있어요. 그래도 한 번 읽어보고, 예시 코드와 주석을 살펴본 뒤에 다시 읽어보면 이해가 잘 될 겁니다! 그래도 이해가 안 가시면 이전(2주차)에 있었던 클래스와 콜백 함수 파트를 복습한 뒤에 읽어보세요.
🤯 개념잡기: Request 메서드란?
저희가 이용할 Request는 start_urls 대신에 크롤링할 주소를 요청하는 역할을 하는 메서드입니다. scrapy.Request로 주소를 요청(request)하고, 그에 대한 응답(response)을 html 파일로 받습니다.
Request 메서드 내부의 "callback" 파라미터는 이 주소를 가지고 downloader가 전달해 주는 response 객체를 처리할 메서드를 지정하여 호출해 줍니다.
"meta" 파라미터는 callback이 처리 요청한 메서드에, 현재 자신이 속한 메서드에서 정의한 변수를 전달해 줄 수 있습니다. 즉 지역변수를 callback에서 지정해 준 메서드 내에서 재활용할 수 있게 해주는 것이죠.
📖 용어사전
- 파라미터(=매개변수): 함수에 입력으로 전달된 값을 받는 변수
- 메서드(≒함수): 클래스 안에 들어있는 함수
- 지역변수: 함수 내에서 선언되어 함수 내에서만 사용 가능한 변수
#st11_best.py
import scrapy
class St11Spider(scrapy.Spider):
name = 'st11_best'
# 기존에 있던 allowed_domains와 start_urls는 삭제: 따라서 genspider시 주소에 https://를 붙여줘야 함. 아래 코드들 참고.
# 순서: 아래 주소를 Request -> self(= 클래스) 안의 parse_mainpages라는 메서드를 실행(callback) -> 거기서 response 객체 처리!
def start_requests(self): # 첫번째로 선언된 메서드는 기존 parse() 대신 다른 Scrapy 파일들에서 호출됨
coco = 123
yield scrapy.Request(url="https://www.11st.co.kr/browsing/BestSeller.tmall?method=getBestSellerMain&cornerNo=0",
callback=self.parse_mainpages, # self 내의 이 메서드를 불러 response 처리 일을 이어서 실행
meta={'coco123':coco}) # callback 요청한 메서드에 이 데이터를 보내줌. 딕셔너리 형태
def parse_mainpages(self, response): # 위 메서드에서 url의 response에 대해 전달받음.
print("------- parse_mainpages 성공 -------", response.meta['coco123']) # 위에서 정의한 meta 속 데이터(coco=123)를, 지정해준 이름을 가지고 여기로 불러옴
# 메인 카테고리명 크롤링
print(response.css('div.best_category_box li button::text').getall()) # 내려받은 주소로 response 객체 처리 예시
#터미널
scrapy crawl st11_best
실행해보시면 터미널 중간에 성공적으로 문자열, meta로 내려받은 내용, response를 css로 불러온 내용(메인 카테고리명)이 위 사진처럼 보일 겁니다.
이렇게 scrapy.Request의 callback 파라미터를 이용하면 여러 개의 메서드에 걸쳐 유기적인 연결이 가능해집니다. 이런 방식으로, 주소를 반복문으로 요청하면서 response를 처리한다면 여러 사이트를 크롤링 하기가 쉽겠죠? 앞으로 다룰 '메인 카테고리 → 서브 카테고리'에 걸친 여러 사이트의 크롤링도 이런 방법으로 이루어집니다.
그전에! Scrapy는 하나의 주소(url)를 크롤링 한 상태에서 다시 동일해 보이는 주소를 크롤링하려고 할 시, 두 요청이 동일한 크롤링이라고 보고 반복적으로 크롤링하지 않도록 설정되어 있습니다. 즉 비슷한 주소로 요청(Request)하는 코드가 여러 개인 경우 하나만이 실행된다는 것인데, 이 경우 아래의 설정을 추가해 줘서 모든 요청 코드가 실행될 수 있도록 해줘야 합니다.
#settings.py
DUPEFILTER_CLASS = 'scrapy.dupefilters.BaseDupeFilter' # 코드 직접 추가