크롤링/scrapy

scrapy(스크래피) 크롤링 실전 (csv 저장까지)

개발자J군 2020. 9. 24. 21:21

scrapy로 11번가의 베스트 상품을 크롤링 하는 예제

수집항목 : 각 카테고리별 베스트 200 상품 (메인카테고리, 서브카테고리, 제목, 가격, 판매자, 세부url)

진행순서

1. 프로젝트 만들기

>>scrapy startproject elest   (프로젝트명은 영어만 가능)

 

2.스파이더 봇 만들기

scrapy genspider elebest www.11st.co.kr/browsing/BestSeller.tmall?method=getBestSellerMain 

*url은 추후 수정가능

 

3. elebest.py 파일 작성하기

elebest.py

import scrapy
from elest.items import ElestItem

class ElebestSpider(scrapy.Spider):
    name = 'elebest'
    
    #__init__ 함수처럼 기본으로 실행됨. start_requests 함수 작성시 start_urls 변수는 주석처리 또는 삭제 
    def start_requests(self):
        url = "https://www.11st.co.kr/browsing/BestSeller.tmall?method=getBestSellerMain"
        yield scrapy.Request(url = url , callback=self.parse_main)

	#카테고리의 세부 url을 얻는 중간 단계
    def parse_main(self, response):
        ca_link = response.css("div.best_category_box > ul > li button::attr(onclick)").getall()
        ca_name = response.css("div.best_category_box > ul > li button::text").getall()

        sub_link = response.css("div.sub_category_box > ul > li a::attr(onclick)").getall()
        sub_name = response.css("div.sub_category_box > ul > li a::text").getall()
        
        #세부 카테고리들의 베스트 상품만 크롤링 
        for index, link in enumerate(sub_link):
            link_first = link.find("(")
            link_last = link.find(")")
            link = link[link_first+1:link_last].split(",")
            url = "http://www.11st.co.kr/browsing/BestSeller.tmall?method=getBestSellerMain&cornerNo={}&dispCtgrNo={}".format(link[0],link[1])
            yield scrapy.Request(url =url,
            callback=self.parse_items, meta={"maincategory_name":ca_name[int(link[0])],"subcategory_name":sub_name[index]})
         
         #대표카테고리의 베스트 200도 크롤링 하고 싶다면 아래 코드 추가
        # for index, link in enumerate(ca_link):
        #     link_first = link.find("(")
        #     link_last = link.find(")")
        #     link = link[link_first+1:link_last]
        #     yield scrapy.Request(url ="http://www.11st.co.kr/browsing/BestSeller.tmall?method=getBestSellerMain&cornerNo="+link,
        #     callback=self.parse_items, meta={"maincategory_name":ca_name[index], "subcategory_name":"ALL"})          
            

각각의 카테고리의 이름과 링크를 최종적으로 parse_items 함수로 넘겨준다. (meta는 카테고리 이름 정보)

 

    def parse_items(self, response):
        best_items = response.css("ul.cfix ")[1].css("li")
        for s, item in enumerate(best_items):
            doc = ElestItem()
            main_category=response.meta["maincategory_name"]
            sub_category = response.meta["subcategory_name"]
            ranking = s+1
            title = item.css("a p::text").get()
            price = item.css("strong.sale_price::text").get()
            seller = item.css("div.store a::text").get()
            link = item.css("div a::attr(href)").get()
            doc["main_category"] =  main_category
            doc["sub_category"] =sub_category
            doc["ranking"] =  ranking
            doc["title"] =  title
            doc["price"] = price
            doc["seller"] = seller
            doc["link"] = link

            yield doc

elebest.py 내의 parse_items 함수에서 상품의 제목, 가격 등을 뽑는다. (메인카테고리, 서브카테고리는 메타로 받은 정보)

 

 

4.items.py 작성

import scrapy


class ElestItem(scrapy.Item):
    main_category= scrapy.Field()
    sub_category = scrapy.Field()
    ranking= scrapy.Field()
    title= scrapy.Field()
    price= scrapy.Field()
    seller= scrapy.Field()
    link= scrapy.Field()

 

5.settings.py 작성

settings.py

BOT_NAME = 'elest'

SPIDER_MODULES = ['elest.spiders']
NEWSPIDER_MODULE = 'elest.spiders'

#csv 한글 깨짐 방지
FEED_EXPORT_ENCODING="utf-8-sig"

#각 카테고리의 상품의 순서가 섞이지 않게 딜레이 부여
DOWNLOAD_DELAY = 1

ROBOTSTXT_OBEY = True

#순서대로 크롤링, 시간이 조금 더 소요됨.
CONCURRENT_REQUESTS = 1

#csv 저장시 순서 정렬
FEED_EXPORT_FIELDS=["ranking","main_category","sub_category","title", "price", "seller","link"]


#하나의 함수에서 동일한 url로 Request 할경우
DUPEFILTER_CLASS ='scrapy.dupefilters.BaseDupeFilter'

 

6. 봇 실행 (csv로 저장)

>> scrapy crawl elebest -o elebest.csv -t csv

 

몽고db 저장은 아래 글 참조.

 

scrapy[스크래피] mongo db 인서트

스크래피(scrapy)로 크롤링한 정보를 몽고db에 인서트 시킬 경우 settings.py 와 pipelines.py 수정이 필요하다. 봇 네임등은 스크래피 봇 생성시 기본적으로 작성되기 때문에 MONGO_URI,MONGO_DATABASE 부분만 ��

pycoding.tistory.com

 

7.csv파일 확인

 

반응형