Crawling

SCRAPY 프레임워크의 사용 방법 정리 (2)

bluebamus 2025. 2. 28.

1. Pipelines

   - Scrapy Pipeline은 크롤링한 아이템(데이터)을 후처리(정제, 검증, 저장 등)하는 역할을 담당한다다.

   - 파이프라인은 아이템이 스파이더에서 yield된 후 순차적으로 통과하게 되어, 여러 단계의 처리가 가능하도록 한다.

 

   1.1. 기본 개념

      - Item Pipeline은 스파이더가 추출한 아이템(item)을 후처리(예: 데이터 정제, 유효성 검증, 저장 등)하기 위해 사용하는 컴포넌트이다.
      - 아이템이 스파이더로부터 yield되면 등록된 모든 파이프라인이 순차적으로 실행된다.
      - 파이프라인의 실행 순서는 settings.py의 ITEM_PIPELINES 설정에서 지정한 우선순위(정수값)에 따라 결정된다 (낮은 값이 더 먼저 실행).

 

   1.2. 기본 메소드 및 사용 가능한 옵션

      1.2.1. open_spider(spider)

         - 개념:
            - 스파이더가 시작될 때 한 번 호출되어, 파이프라인 관련 초기화 작업(예: 데이터베이스 연결, 파일 열기 등)을 수행
         - 매개변수:
             - spider: 현재 실행 중인 스파이더 인스턴스

         - 옵션/특징:
             - 파이프라인이 시작될 때 한 번 호출

 

         - 기본 사용 예시:

def open_spider(self, spider):
    self.file = open('items.json', 'w')

 

      1.2.2. close_spider(spider)

         - 개념:

            - 스파이더가 종료될 때 호출되어, 파이프라인 관련 마무리 작업(예: 데이터베이스 연결 종료, 파일 닫기 등)을 수행
         - 매개변수:
             - spider: 현재 실행 중인 스파이더 인스턴스

         - 옵션/특징:
             - 파이프라인이 종료될 때 한 번 호출


         - 기본 사용 예시:

def close_spider(self, spider):
    self.file.close()

 

      1.2.3. process_item(item, spider)

         - 개념:
            - 파이프라인 체인의 핵심 메소드로, 스파이더가 yield한 아이템마다 호출되어 아이템을 가공, 검증, 저장하는 작업을 수행
         - 매개변수:
            - item: 스파이더가 yield한 아이템(보통 dict 또는 Scrapy Item 객체)
            - spider: 해당 아이템을 생성한 스파이더 객체
         - 반환값:
            - 처리된 item (보통 체인 내 다음 파이프라인이나 최종 결과로 반환)

         - 옵션/특징:
            - 아이템을 가공한 후 반환하거나, 조건에 따라 DropItem 예외를 발생시켜 아이템을 폐기
            - 반드시 아이템을 반환해야 다음 파이프라인으로 전달


         - 기본 사용 예시:

def process_item(self, item, spider):
    # 데이터 정제 또는 유효성 검사 작업 수행
    if not item.get('title'):
        raise DropItem("Missing title in %s" % item)
    return item

 

      1.2.4. 선택적 메소드 (필요에 따라 구현)

         - from_crawler(cls, crawler)
            - 개념: 

               - 크롤러 인스턴스를 통해 파이프라인 객체를 생성하는 클래스 메소드
            - 용도: 

               - 크롤러 설정이나 확장 기능에 접근이 필요한 경우 사용

            - 옵션/특징:

               - 클래스 메소드로 선언하며, 인스턴스를 초기화하기 위한 추가 옵션들을 설정 가능
               - 이 메소드를 정의하면 __init__ 전에 호출되어 필요한 설정을 주입 가능

         - 기타: 

            - 이미지나 파일 다운로드 파이프라인 등 특수한 파이프라인은 추가 메소드(get_media_requests, 

item_completed 등)를 구현합니다.

 

         - 예시:

@classmethod
def from_crawler(cls, crawler):
    settings = crawler.settings
    return cls(settings.get('MY_SETTING'))

 

   1.3. 샘플 코드: 기본 Pipeline 구현

from scrapy.exceptions import DropItem

class ExamplePipeline:
    def open_spider(self, spider):
        # 스파이더 시작 시 초기화 작업
        spider.logger.info("Spider opened, initializing pipeline...")
        self.items_processed = 0

    def close_spider(self, spider):
        # 스파이더 종료 시 마무리 작업
        spider.logger.info(f"Spider closed. Total items processed: {self.items_processed}")

    def process_item(self, item, spider):
        # 아이템 가공 및 검증
        if 'price' in item and item['price'] < 0:
            raise DropItem(f"Invalid price in {item}")
        self.items_processed += 1
        return item
import json
from scrapy.exceptions import DropItem

class JsonWriterPipeline:
    # 스파이더 시작 시 파일 열기
    def open_spider(self, spider):
        self.file = open('items.jl', 'w', encoding='utf-8')

    # 스파이더 종료 시 파일 닫기
    def close_spider(self, spider):
        self.file.close()

    # 아이템 처리: JSON 직렬화 후 파일에 기록
    def process_item(self, item, spider):
        line = json.dumps(dict(item), ensure_ascii=False) + "\n"
        self.file.write(line)
        return item

class ValidateItemPipeline:
    # 아이템 유효성 검사 후 필요한 경우 폐기
    def process_item(self, item, spider):
        if 'title' not in item:
            raise DropItem(f"Missing title in {item}")
        return item

class MongoDBPipeline:
    @classmethod
    def from_crawler(cls, crawler):
        # settings.py에서 MongoDB 관련 설정을 읽어옵니다.
        mongo_uri = crawler.settings.get('MONGO_URI')
        mongo_db = crawler.settings.get('MONGO_DATABASE', 'items')
        return cls(mongo_uri, mongo_db)

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    def open_spider(self, spider):
        import pymongo
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        # 스파이더 이름을 컬렉션 이름으로 사용
        self.db[spider.name].insert_one(dict(item))
        return item

 

   1.4. 실무 기반 예제 시나리오

      - 예제 1: MySQL 데이터베이스 저장 Pipeline

import mysql.connector
from scrapy.exceptions import DropItem

class MySQLPipeline:
    def open_spider(self, spider):
        self.conn = mysql.connector.connect(
            host='localhost',
            user='scrapy_user',
            password='password',
            database='scrapy_db'
        )
        self.cursor = self.conn.cursor()
        self.cursor.execute("""
            CREATE TABLE IF NOT EXISTS items (
                id INT AUTO_INCREMENT PRIMARY KEY,
                title VARCHAR(255),
                price FLOAT
            )
        """)
    
    def close_spider(self, spider):
        self.conn.commit()
        self.conn.close()
    
    def process_item(self, item, spider):
        if not item.get('title'):
            raise DropItem("Missing title in item")
        self.cursor.execute(
            "INSERT INTO items (title, price) VALUES (%s, %s)",
            (item.get('title'), item.get('price', 0))
        )
        return item

 

      - 예제 2: 데이터 정제 및 JSON 파일 저장 Pipeline

import json

class JsonWriterPipeline:
    def open_spider(self, spider):
        self.file = open('items_cleaned.json', 'w', encoding='utf-8')
    
    def close_spider(self, spider):
        self.file.close()
    
    def process_item(self, item, spider):
        # 데이터 정제: 불필요한 공백 제거
        if 'title' in item:
            item['title'] = item['title'].strip()
        # JSON 파일에 기록
        line = json.dumps(dict(item), ensure_ascii=False) + "\n"
        self.file.write(line)
        return item

 

      - 예제 3: 필수 필드 검증 및 로깅 파이프라인
         - 시나리오: 아이템에 필수 필드 title이 누락되었을 경우 로그를 남기고 해당 아이템을 폐기한다.

import logging
from scrapy.exceptions import DropItem

class LoggingValidatePipeline:
    def process_item(self, item, spider):
        if 'title' not in item:
            logging.warning(f"Item dropped due to missing title: {item}")
            raise DropItem("Missing title")
        return item

 

      - 예제 4: MySQL 저장 파이프라인
         - 시나리오: 크롤링한 아이템을 MySQL 데이터베이스에 저장합니다.

import pymysql
from scrapy.exceptions import DropItem

class MySQLPipeline:
    @classmethod
    def from_crawler(cls, crawler):
        db_settings = {
            'host': crawler.settings.get('MYSQL_HOST', 'localhost'),
            'user': crawler.settings.get('MYSQL_USER', 'root'),
            'password': crawler.settings.get('MYSQL_PASSWORD', ''),
            'db': crawler.settings.get('MYSQL_DB', 'scrapy_db'),
            'charset': 'utf8mb4'
        }
        return cls(db_settings)

    def __init__(self, db_settings):
        self.db_settings = db_settings

    def open_spider(self, spider):
        self.connection = pymysql.connect(**self.db_settings)
        self.cursor = self.connection.cursor()

    def close_spider(self, spider):
        self.connection.commit()
        self.connection.close()

    def process_item(self, item, spider):
        try:
            sql = "INSERT INTO items (title, link) VALUES (%s, %s)"
            self.cursor.execute(sql, (item.get('title'), item.get('link')))
        except Exception as e:
            raise DropItem(f"Failed to insert item: {e}")
        return item


2. Settings

  2.1. 기본 개념

      - settings.py는 Scrapy 프로젝트의 모든 설정값을 정의하는 중앙 관리 파일이다.
      - 여기에서 봇의 이름, 스파이더 모듈 경로, 파이프라인, 미들웨어, 다운로드 딜레이, 요청 동시 처리 수 등 다양한 옵션을 설정할 수 있다.
      - 커맨드라인이나 환경변수를 통해 동적으로 설정을 오버라이드할 수도 있다.

 

      - 설정 항목 종류:
         - 전역 설정 (BOT_NAME, SPIDER_MODULES, NEWSPIDER_MODULE 등)
         - 요청 관련 설정 (DOWNLOAD_DELAY, CONCURRENT_REQUESTS, DEFAULT_REQUEST_HEADERS 등)
         - 미들웨어 및 확장 기능 (SPIDER_MIDDLEWARES, DOWNLOADER_MIDDLEWARES, EXTENSIONS 등)
         - 아이템 처리 (ITEM_PIPELINES 등)

 

   2.2. 주요 설정 항목 및 옵션

      2.2.1. settings.py의 기본 설정

# Scrapy settings for temp project
#
# For simplicity, this file contains only settings considered important or
# commonly used. You can find more settings consulting the documentation:
#
#     https://docs.scrapy.org/en/latest/topics/settings.html
#     https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#     https://docs.scrapy.org/en/latest/topics/spider-middleware.html

BOT_NAME = "temp"

SPIDER_MODULES = ["temp.spiders"]
NEWSPIDER_MODULE = "temp.spiders"


# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = "temp (+http://www.yourdomain.com)"

# Obey robots.txt rules
ROBOTSTXT_OBEY = True

# Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32

# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16

# Disable cookies (enabled by default)
#COOKIES_ENABLED = False

# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False

# Override the default request headers:
#DEFAULT_REQUEST_HEADERS = {
#    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
#    "Accept-Language": "en",
#}

# Enable or disable spider middlewares
# See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
#    "temp.middlewares.TempSpiderMiddleware": 543,
#}

# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
#    "temp.middlewares.TempDownloaderMiddleware": 543,
#}

# Enable or disable extensions
# See https://docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
#    "scrapy.extensions.telnet.TelnetConsole": None,
#}

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
#ITEM_PIPELINES = {
#    "temp.pipelines.TempPipeline": 300,
#}

# Enable and configure the AutoThrottle extension (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True
# The initial download delay
#AUTOTHROTTLE_START_DELAY = 5
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False

# Enable and configure HTTP caching (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = "httpcache"
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = "scrapy.extensions.httpcache.FilesystemCacheStorage"

# Set settings whose default value is deprecated to a future-proof value
TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
FEED_EXPORT_ENCODING = "utf-8"

 

      2.2.2. 프로젝트 기본 설정

         - BOT_NAME = "temp"
            - Scrapy 프로젝트의 봇(크롤러) 이름을 정의한다. 이 이름은 로그 메시지나 디버깅 정보 등에서 사용되며, 사용자 에이전트의 기본 값 일부로도 사용될 수 있다.

 

         - SPIDER_MODULES = ["temp.spiders"]

            - Scrapy가 스파이더(크롤러 클래스)를 찾을 모듈(폴더) 목록이다. 여기서는 temp/spiders 디렉토리에 있는 스파이더들을 자동으로 인식한다.

 

         - NEWSPIDER_MODULE = "temp.spiders"
            - 새로운 스파이더를 생성할 때 기본으로 생성될 모듈을 지정한다. 예를 들어, scrapy genspider 명령어로 새 스파이더를 만들면 이 모듈에 생성된다.

 

      2.2.3. 사용자 에이전트 및 robots.txt 관련 설정

         - USER_AGENT (주석 처리됨)
            - 예시: 

               - #USER_AGENT = "temp (+http://www.yourdomain.com)"
            - 웹사이트에 크롤링 요청을 보낼 때, 요청 헤더의 User-Agent 값을 설정한다.

            - 활성화 시: 

               - 웹 서버에 자신을 어떻게 식별할지 결정한다. 보통 크롤링의 경우 사이트 관리자에게 본인 정보를 제공하기 위해 사용한다.

            - 주석 상태: 

               - Scrapy의 기본 사용자 에이전트가 사용된다.

            - 기본값을 그대로 사용하면 Scrapy의 기본 User-Agent가 전송되지만, 이를 직접 설정하면 자신을 명확히 식별할 수 있으며, 일부 웹사이트에서는 이를 기준으로 접근을 제한할 수도 있다.

 

         - ROBOTSTXT_OBEY = True
            - Scrapy가 크롤링할 때 대상 사이트의 robots.txt 파일을 준수하도록 한다.
            - 동작:

               - 사이트의 robots.txt에 명시된 URL 접근 제한을 자동으로 인식하여 해당 경로는 크롤링하지 않는다.
            - 주의: 

               - 크롤링 정책에 따라 사이트 관리자가 금지한 영역은 수집하지 않도록 하여 법적/윤리적 문제를 방지한다.

 

      2.2.4. 동시 요청 및 딜레이 관련 설정

         - CONCURRENT_REQUESTS (주석 처리됨)

            - 예시: #CONCURRENT_REQUESTS = 32

            - 동시에 보낼 수 있는 요청의 최대 개수를 지정한다. 기본값은 16이며, 주석을 해제하여 값을 늘리면 속도가 빨라질 수 있으나 서버에 부담을 줄 수 있다.

            - 기본값: 

               - 보통 16이며, 여기서 32로 설정하면 더 많은 요청을 병렬 처리할 수 있지만, 대상 서버에 부담을 줄 수 있다.

 

         - DOWNLOAD_DELAY (주석 처리됨)
            - 예시:

               - #DOWNLOAD_DELAY = 3

            - 동일 사이트에 요청할 때 각 요청 사이에 지연 시간을(초 단위) 설정한다.
               - 예: 3초로 설정 시, 동일 도메인에 연속해서 요청을 보낼 때 3초씩 기다리게 된다.

 

         - CONCURRENT_REQUESTS_PER_DOMAIN = 16 (주석 처리됨)
            - 동일 도메인에 대해 동시에 보낼 수 있는 최대 요청 수를 지정한다.

         - CONCURRENT_REQUESTS_PER_IP = 16 (주석 처리됨)
            - 동일 IP 주소에 대해 동시에 보낼 수 있는 최대 요청 수를 지정한다.
            - 참고: 

               - 도메인 기반과 IP 기반의 동시 요청 제한 중 하나만 적용된다.

            - 이 설정들은 DOWNLOAD_DELAY와 함께 작동하며, 너무 많은 요청이 한 사이트에 몰리지 않도록 제어한다.

 

      2.2.5. 쿠키 및 텔넷 콘솔 설정

         - COOKIES_ENABLED (주석 처리됨)
            - 예시: 

               - #COOKIES_ENABLED = False

            - 활성화 시: 

               - 쿠키를 사용하지 않도록 하여, 세션 관리나 로그인 유지 등 쿠키 기반의 기능을 비활성화할 수 있다.
            - 기본값:

               - 크롤링 시 웹사이트와의 세션 유지나 로그인 상태를 위해 쿠키 사용 여부를 설정한다.

            - 쿠키는 활성화되어 있으므로, 특별한 이유가 없다면 그대로 두어도 무방하다.

 

         - TELNETCONSOLE_ENABLED (주석 처리됨)
            - 예시: 

               - #TELNETCONSOLE_ENABLED = False

            - Scrapy는 기본적으로 텔넷 콘솔을 열어 실행 중인 크롤러의 상태를 모니터링하고 디버깅할 수 있도록 한다.

            - 이 설정을 False로 하면 텔넷 콘솔 기능을 비활성화한다.

            - 활성화 시: 

               - 기본적으로 제공되며, 실시간으로 크롤러 상태를 점검하거나 디버깅하는 데 유용하지만, 보안상의 이유로 외부 접근을 막고 싶다면 비활성화할 수 있다.

 

      2.2.6. 기본 요청 헤더 설정

         - DEFAULT_REQUEST_HEADERS (주석 처리됨)

            - Scrapy가 각 요청에 기본적으로 포함시킬 HTTP 헤더들을 지정할 수 있다.

{
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en",
}

 

            - 동작: 

               - 이 헤더들은 요청마다 자동으로 추가되어, 대상 서버에 요청의 형식이나 언어 등을 전달한다. 만약 헤더를 커스터마이징하면, 사이트가 요구하는 특정 헤더를 추가하거나 브라우저와 유사한 요청을 보낼 수 있다.

 

      2.2.7. 미들웨어 설정

         - 미들웨어는 스파이더와 다운로더 사이에서 요청과 응답을 가로채거나 수정하는 역할을 합니다.

 

         - SPIDER_MIDDLEWARES (주석 처리됨)

            - 예시:

#SPIDER_MIDDLEWARES = {
#    "temp.middlewares.TempSpiderMiddleware": 543,
#}

 

            - 스파이더 미들웨어는 스파이더의 입력(응답)과 출력(아이템, 요청)을 가로채거나 수정할 수 있다.
            - 각 미들웨어에 대해 숫자 값(우선순위)을 부여하여 여러 미들웨어 간의 실행 순서를 제어한다.

            - 키: 

               - 미들웨어 클래스의 경로
            - 값: 

               - 우선순위 번호 (숫자가 작을수록 먼저 실행됨)
            - 동작: 

               - 스파이더로 들어가는 응답(response)을 처리하거나, 스파이더가 생성한 아이템/요청에 대해 후처리할 수 있다.

 

         - DOWNLOADER_MIDDLEWARES (주석 처리됨)
            - 예시:

#DOWNLOADER_MIDDLEWARES = {
#    "temp.middlewares.TempDownloaderMiddleware": 543,
#}

 

            - 다운로드 미들웨어는 실제 HTTP 요청과 응답을 가로채어 수정할 수 있다.
            - 예를 들어, User-Agent를 변경하거나 프록시 설정, 요청 재시도 등의 기능을 수행할 수 있다.

            - 동작: 

                - 요청(request) 전송 전이나 응답(response) 수신 후에 추가 작업(예: 헤더 수정, 프록시 설정, 에러 처리 등)을 수행할 수 있다.

 

      2.2.8. 확장(Extensions) 설정

         - EXTENSIONS (주석 처리됨)

            - 예시:

#EXTENSIONS = {
#    "scrapy.extensions.telnet.TelnetConsole": None,
#}

 

            - Scrapy 확장은 크롤링 프로세스의 특정 이벤트에 반응하여 추가 기능(예: 로그, 통계, 모니터링)을 제공한다.
            - 여기서는 기본적으로 제공되는 텔넷 콘솔 확장을 비활성화(값을 None으로 설정)할 수 있다.

               - 예: 텔넷 콘솔 확장을 None으로 설정하면 해당 확장이 비활성화됩니다.

 

      2.2.9. 아이템 파이프라인

         - ITEM_PIPELINES (주석 처리됨)

            - 예시:

#ITEM_PIPELINES = {
#    "temp.pipelines.TempPipeline": 300,
#}

 

            - 크롤링한 데이터를 처리하는 아이템 파이프라인의 설정이다.
            - 각 파이프라인에 대해 숫자 값(우선순위)를 부여하여 여러 파이프라인 간 처리 순서를 지정할 수 있다.
            - 예를 들어, 데이터를 정제, 저장, 또는 데이터베이스로 보내는 등의 작업을 수행한다.

            - 키: 

               - 파이프라인 클래스의 경로
            - 값: 

               - 우선순위 (숫자가 낮을수록 먼저 실행)
            - 동작: 

               - 데이터 클렌징, 중복 제거, 저장(DB 또는 파일 시스템) 등 다양한 후처리 작업을 수행할 수 있다.

 

      2.2.10. AutoThrottle (자동 요청 속도 조절)

         - AUTOTHROTTLE_ENABLED (주석 처리됨)

            - 예시: #AUTOTHROTTLE_ENABLED = True
            - AutoThrottle 확장은 서버의 응답 속도에 따라 요청 간의 딜레이를 자동으로 조절하여 서버에 과부하를 주지 않도록 한다.


         - AUTOTHROTTLE_START_DELAY (주석 처리됨)
            - 예시: #AUTOTHROTTLE_START_DELAY = 5
            - AutoThrottle이 시작될 때의 초기 다운로드 지연 시간을 설정한다.


         - AUTOTHROTTLE_MAX_DELAY (주석 처리됨)
            - 예시: #AUTOTHROTTLE_MAX_DELAY = 60
            - 서버의 응답이 느린 경우 적용할 최대 지연 시간을 설정한다.


         - AUTOTHROTTLE_TARGET_CONCURRENCY (주석 처리됨)
            - 예시: #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
            - 서버에 동시에 보낼 요청의 목표 개수를 설정한다. 이 값에 따라 AutoThrottle이 적절한 딜레이를 계산한다.


         - AUTOTHROTTLE_DEBUG (주석 처리됨)
            - 예시: #AUTOTHROTTLE_DEBUG = False
            - AutoThrottle의 동작 과정을 디버깅 모드로 출력할지 여부를 결정한다.

 

      2.2.11. HTTP 캐시 설정

         - HTTPCACHE_ENABLED (주석 처리됨)

            - 예시: #HTTPCACHE_ENABLED = True
            - HTTP 캐시를 활성화하면 동일한 URL에 대한 응답을 로컬에 저장하여, 재요청 시 네트워크 부하를 줄이고 속도를 높일 수 있다.


         - HTTPCACHE_EXPIRATION_SECS (주석 처리됨)
            - 예시: #HTTPCACHE_EXPIRATION_SECS = 0
            - 캐시된 데이터의 만료 시간을 초 단위로 지정합니다. 0이면 만료되지 않음을 의미한다.


         - HTTPCACHE_DIR (주석 처리됨)
            - 예시: #HTTPCACHE_DIR = "httpcache"
            - 캐시 파일을 저장할 디렉터리를 지정한다.


         - HTTPCACHE_IGNORE_HTTP_CODES (주석 처리됨)
            - 예시: #HTTPCACHE_IGNORE_HTTP_CODES = []
            - 캐시하지 않을 HTTP 응답 코드(예: 500, 404 등)를 리스트로 지정할 수 있다.


         - HTTPCACHE_STORAGE (주석 처리됨)
            - 예시: #HTTPCACHE_STORAGE = "scrapy.extensions.httpcache.FilesystemCacheStorage"
            - 캐시 저장소의 백엔드를 지정한다. 여기서는 파일 시스템 기반 캐시 저장소를 사용한다.

 

      2.2.12. 미래 호환 설정

         - TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
            - Scrapy는 Twisted 프레임워크를 기반으로, 이 설정은 비동기 I/O를 처리하기 위한 리액터(reactor)를 지정한다.
            - AsyncioSelectorReactor는 Python의 asyncio 라이브러리와 통합되어 있어, 비동기 작업 처리에 더욱 효율적인 환경을 제공한다.

            - Scrapy는 비동기 네트워크 라이브러리인 Twisted를 사용한다. 이 설정은 Twisted가 사용할 reactor(이벤트 루프)로 Asyncio 기반의 reactor를 사용하도록 지정한다.
            - 효과: 

               - Python의 asyncio와의 호환성이 개선되며, 최신 비동기 기능을 활용할 수 있다.

 

         - FEED_EXPORT_ENCODING = "utf-8"

            - 크롤링 결과를 파일(예: JSON, CSV 등)로 저장할 때 기본 인코딩을 지정한다.
            - utf-8로 설정하면 다양한 문자(한글 포함)를 올바르게 저장할 수 있다.

 

      2.2.13. 동작 방식 정리

         - 프로젝트 초기화
            - Scrapy는 설정 파일에서 BOT_NAME, SPIDER_MODULES, NEWSPIDER_MODULE 등을 읽어 프로젝트 구조와 봇의 기본 정보를 파악한다.

 

         - 요청 전송 단계
            - User-Agent: 설정된 값(또는 기본값)을 요청 헤더에 포함한다.
            - robots.txt: ROBOTSTXT_OBEY가 True이므로, 먼저 대상 웹사이트의 robots.txt 파일을 확인하여 크롤링 가능한 URL인지 검증한다.

 

         - 요청 스케줄링 및 동시성 제어
            - CONCURRENT_REQUESTS, DOWNLOAD_DELAY, CONCURRENT_REQUESTS_PER_DOMAIN/IP 설정에 따라 동시에 보낼 요청 수와 각 요청 간의 딜레이가 적용된다.
            - AutoThrottle가 활성화되면, 서버 응답 속도에 따라 자동으로 요청 간 딜레이가 조정된다.

 

         - 중간 처리 (미들웨어)

            - 다운로드 요청은 설정된 Downloader Middleware를 통해 가로채어 추가 작업(헤더 수정, 프록시 적용 등)이 수행될 수 있다.
            - 응답은 Spider Middleware를 통해 스파이더로 전달되기 전에 추가 처리(예: 디코딩, 데이터 수정 등) 받을 수 있다.

 

         - 아이템 처리 및 저장

            - 스파이더가 데이터를 파싱하면, Item Pipeline을 통해 데이터 정제, 변환, 저장(예: 데이터베이스, 파일) 등의 후처리를 진행한다.

            - 최종 결과물은 FEED_EXPORT_ENCODING 설정에 따라 지정된 인코딩(utf-8)으로 저장된다.

 

         - 캐싱 및 성능 최적화

            - HTTP 캐시가 활성화되면, 이미 요청한 URL의 응답을 로컬 캐시에 저장하여 재요청 시 네트워크 부하를 줄인다.


         - 비동기 I/O 처리
            - TWISTED_REACTOR 설정에 따라, Scrapy는 AsyncioSelectorReactor를 사용하여 효율적인 비동기 네트워크 처리를 수행한다.

 

      2.2.14. USER_AGENT_LIST 설정

         - 예시:

USER_AGENT_LIST = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0",
    "Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.59",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 OPR/77.0.4054.277",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 OPR/77.0.4054.277",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
    "Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (iPad; CPU OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 YaBrowser/21.6.2.855 Yowser/2.5 Safari/537.36",
]

 

      2.2.15. PROXY_LIST 설정

         - 예시:

PROXY_LIST = [
   'http://username:password@proxy1:port',
   'http://username:password@proxy2:port',
   'http://username:password@proxy3:port',
   'http://username:password@proxy4:port',
   'http://username:password@proxy5:port',
   'http://username:password@proxy6:port',
   'http://username:password@proxy7:port',
   'http://username:password@proxy8:port',
   'http://username:password@proxy9:port',
   'http://username:password@proxy10:port',
   'http://username:password@proxy11:port',
   'http://username:password@proxy12:port',
   'http://username:password@proxy13:port',
   'http://username:password@proxy14:port',
   'http://username:password@proxy15:port',
]

 

   2.4. 실무 기반 시나리오 예제

      - 예제 1: 고속 크롤링을 위한 설정 (동시 요청수 증가 및 딜레이 최소화)

# settings.py for high-speed crawling

BOT_NAME = 'fast_scrapy_bot'
SPIDER_MODULES = ['fastproject.spiders']
NEWSPIDER_MODULE = 'fastproject.spiders'

ROBOTSTXT_OBEY = False  # 사이트 내부 규칙 무시 (주의 필요)
CONCURRENT_REQUESTS = 64  # 동시 요청 수 증가
DOWNLOAD_DELAY = 0  # 딜레이 없이 요청

DEFAULT_REQUEST_HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) FastScrapyBot/1.0',
}

ITEM_PIPELINES = {
    'fastproject.pipelines.FastPipeline': 300,
}

 

      - 예제 2: 프록시와 사용자 에이전트를 설정한 보안 크롤링 환경

# settings.py for secure crawling with proxies

BOT_NAME = 'secure_scrapy_bot'
SPIDER_MODULES = ['secureproject.spiders']
NEWSPIDER_MODULE = 'secureproject.spiders'

ROBOTSTXT_OBEY = True
CONCURRENT_REQUESTS = 16
DOWNLOAD_DELAY = 1

# 프록시 서버 및 사용자 에이전트 설정
DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 750,
    'secureproject.middlewares.CustomProxyMiddleware': 745,
}

DEFAULT_REQUEST_HEADERS = {
    'User-Agent': 'SecureScrapyBot/2.0 (+http://example.com/bot)',
    'Accept-Language': 'en-US,en;q=0.9',
}

ITEM_PIPELINES = {
    'secureproject.pipelines.ValidationPipeline': 300,
}

 

      - 예제 3: MongoDB 저장 프로젝트 설정
          - 시나리오: 크롤링한 데이터를 MongoDB에 저장하기 위한 설정값을 포함한다.

BOT_NAME = 'mongo_spider'

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

ROBOTSTXT_OBEY = True

# MongoDB 관련 설정
MONGO_URI = 'mongodb://localhost:27017'
MONGO_DATABASE = 'scrapy_items'

ITEM_PIPELINES = {
    'mongo_spider.pipelines.MongoDBPipeline': 300,
}

CONCURRENT_REQUESTS = 8
DOWNLOAD_DELAY = 2

 

      - 예제 4: 고급 사용자 에이전트와 쿠키 비활성화 설정
          - 시나리오: 사이트에서 봇 탐지를 피하기 위해 사용자 에이전트를 커스터마이징하고, 쿠키를 비활성화한다.

BOT_NAME = 'custom_spider'

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

# robots.txt 무시 (필요에 따라)
ROBOTSTXT_OBEY = False

# 사용자 에이전트 및 쿠키 설정
USER_AGENT = 'CustomBot/1.0 (+http://www.example.com)'
COOKIES_ENABLED = False

ITEM_PIPELINES = {
    'custom_spider.pipelines.JsonWriterPipeline': 300,
}

DOWNLOAD_DELAY = 0.5

 

3. scrapy.cfg

   3.1. 기본 개념

      - scrapy.cfg는 Scrapy 프로젝트의 최상위 디렉토리에 위치하는 구성 파일로, Scrapy 명령어 실행 시 기본 설정 모듈을 지정한다.
      - INI 형식으로 작성되며, 주로 [settings] 및 [deploy] 섹션으로 구성된다.
      - 이 파일을 통해 개발/배포 환경 별로 다른 설정 파일을 쉽게 적용할 수 있다.

 

   3.2. 주요 섹션 및 설정 항목

      3.2.1. [settings]

         - 설명: 

            - 기본적으로 사용할 설정 모듈을 지정합니다.
         - 옵션: 

            - default = yourproject.settings

         - 예시:

[settings]
default = myproject.settings

 

      3.2.2. [deploy]

         - 설명:

            - Scrapyd 같은 배포 도구에 배포할 때 사용되는 설정을 포함합니다.
         - 옵션:

            - url:

               - 설명: scrapyd 서버의 배포 URL
               - 예시: url = http://localhost:6800/
            - project:

                - 설명: 배포될 프로젝트의 이름
                - 예시: project = myproject
            - version: (옵션)
                - 설명: 배포 시 버전 관리 (보통 Git commit 해시 등으로 관리 가능)
             - 추가 옵션:
                - 필요한 경우 다른 사용자 정의 섹션을 추가할 수 있음

            - 예시:

[settings]
default = myproject.settings

[deploy]
# scrapyd 서버에 배포 시 사용
url = http://localhost:6800/
project = myproject

 

   3.3. 기본 사용법 예제

[settings]
default = myproject.settings

[deploy]
# 로컬 Scrapyd 서버로 배포할 경우 설정
# url = http://localhost:6800/
# project = myproject

 

   3.4. 실무 기반 시나리오 예제

      - 예제 1: 기본 프로젝트 배포 설정 (scrapyd 연동)

[settings]
default = fastproject.settings

[deploy]
url = http://scrapyd.myserver.com:6800/
project = fastproject

 

      - 예제 2: 다중 환경(개발/프로덕션) 분리 설정

[settings]
# 기본 개발 환경 설정
default = devproject.settings

[deploy:production]
# 프로덕션 환경 배포를 위한 설정 (deploy 명령어 시 profile 지정)
url = http://production.scrapyd.server:6800/
project = devproject_prod

 

      - 예제 3: 다중 환경 설정 및 원격 배포

         - 시나리오: 개발 환경과 프로덕션 환경을 구분하여 설정하고, 원격 Scrapyd 서버에 배포하는 예제이다.

[settings]
default = custom_spider.settings
production = custom_spider.settings_prod

[deploy]
url = http://scrapyd.example.com:6800/
project = custom_spider

 

댓글