Insights·2026-07-22

Scrapling이란 무엇이고, 사이트가 개편돼도 스크래퍼가 안 깨지는 이유는?

Scrapling은 파이썬으로 웹 데이터를 긁어오는 오픈소스 프레임워크다(BSD-3 라이선스, GitHub 별 7만 개). 가장 큰 특징은 적응형 셀렉터다. 보통 웹 스크래퍼는 '이 클래스명을 가진 요소를 가져와라'처럼 화면 위 위치를 규칙으로 지정해 데이터를 뽑는데, 상대 사이트가 개편돼 클래스명이나 구조가 바뀌면 그 규칙이 전부 어긋나 빈 값만 나온다. Scrapling은 처음 수집할 때 요소의 특징을 함께 저장해 두었다가, 다음 실행에서 adaptive 옵션을 켜면 유사도 알고리즘으로 옮겨간 요소를 다시 찾아낸다. 그래서 사이트가 바뀌어도 사람이 셀렉터를 다시 고치지 않아도 된다. 여기에 Cloudflare 같은 안티봇 우회, 대규모 동시 크롤러, Claude·Cursor에 붙이는 MCP 서버까지 한 라이브러리에 들어 있다.

웹 스크래핑과 셀렉터란 무엇인가

웹 스크래핑은 사람이 브라우저로 열어 보던 웹페이지에서 원하는 정보만 프로그램이 자동으로 뽑아내는 일이다. 쇼핑몰 가격을 매일 기록하거나, 리뷰를 모으거나, 여러 사이트의 공지를 한곳에 모으는 작업이 모두 여기에 해당한다.

핵심 도구는 셀렉터(selector)다. 웹페이지는 겉으로는 글과 이미지지만 속을 열어 보면 HTML이라는 태그 구조로 짜여 있다. 셀렉터는 그 구조에서 어디를 집을지 가리키는 주소 같은 것이다. 예를 들어 CSS 셀렉터 .price는 'price라는 클래스가 붙은 요소를 집어라'는 뜻이고, 그 요소의 텍스트를 가져오면 가격이 나온다.

즉 스크래퍼는 두 부분으로 나뉜다. 하나는 페이지를 받아오는 일(fetch), 다른 하나는 받아온 HTML에서 셀렉터로 원하는 조각을 집어내는 일(parse)이다. Scrapling은 이 두 가지를 모두 다룬다.

왜 스크래퍼는 사이트 개편에 깨지는가

문제는 셀렉터가 상대 사이트의 현재 구조에 묶여 있다는 점이다. 내가 .btn-primary를 집도록 짜 두었는데 사이트가 디자인을 바꾸면서 그 클래스명을 .button-main으로 바꾸면, 내 셀렉터는 이제 존재하지 않는 것을 가리킨다. 코드는 한 글자도 안 바뀌었지만 결과는 빈 값이다.

이건 드문 사고가 아니라 상시 일어나는 일이다. 상대 사이트는 내 스크래퍼를 배려할 이유가 없다. 마케팅 개편, A/B 테스트, 프레임워크 교체 같은 이유로 클래스명과 구조는 수시로 바뀐다. 그때마다 사람이 사이트를 다시 열어 새 클래스명을 찾고 셀렉터를 고쳐 넣는다. 스크래핑을 오래 운영해 본 팀이 유지보수에 쓰는 시간의 대부분이 여기서 나온다.

그래서 깨지지 않는 스크래퍼는 오랫동안 불가능에 가까웠다. 근본적으로 남의 화면 구조에 의존하기 때문이다. Scrapling의 적응형 셀렉터는 이 의존을 느슨하게 푸는 방식이다.

적응형 셀렉터는 어떻게 다시 찾는가

적응형(adaptive) 셀렉터의 아이디어는 단순하다. 처음 요소를 성공적으로 집었을 때, 그 요소의 특징을 함께 저장해 둔다. 클래스명뿐 아니라 태그 종류, 부모·형제 관계, 주변 텍스트, 화면상 위치 같은 여러 단서다. 이 특징을 auto_save 옵션으로 저장한다.

다음번에 사이트가 바뀌어 원래 셀렉터가 실패하면, adaptive 옵션을 켠 상태에서 Scrapling이 저장해 둔 특징과 가장 비슷한 요소를 페이지 전체에서 유사도로 찾아낸다. 클래스명 하나가 바뀌어도 나머지 단서가 남아 있으면 옮겨간 요소를 다시 집는다. 사람이 새 클래스명을 찾아 코드를 고치는 단계가 사라진다.

adaptive_selector.py
from scrapling.fetchers import StealthyFetcher

StealthyFetcher.adaptive = True

# 처음 수집 — auto_save=True로 요소의 특징을 함께 저장
page = StealthyFetcher.fetch('https://example.com')
products = page.css('.product', auto_save=True)

# 나중에 사이트 구조가 바뀐 뒤 — adaptive=True로 옮겨간 요소를 다시 찾는다
products = page.css('.product', adaptive=True)

설치하고 코드 없이 바로 써 보기

설치는 파이썬 패키지 관리자 pip로 한다. 터미널에서 pip install scrapling 한 줄이면 파서와 HTTP 요청 기능이 깔린다. 브라우저 자동화(동적 사이트·안티봇 우회)까지 쓰려면 scrapling install로 필요한 브라우저를 함께 받는다.

터미널 — 설치
pip install scrapling

# 브라우저 기반 기능(StealthyFetcher 등)까지 쓸 때
scrapling install
터미널 — 코드 없이 추출
# 페이지 본문을 마크다운으로 저장
scrapling extract get 'https://example.com' content.md

# 특정 CSS 셀렉터만, 크롬으로 위장해서
scrapling extract get 'https://example.com' content.txt --css-selector '.article' --impersonate 'chrome'

# Cloudflare가 막는 페이지를 우회해서 추출
scrapling extract stealthy-fetch 'https://nopecha.com/demo/cloudflare' out.html --solve-cloudflare
quickstart.py — 코드로 쓸 때
from scrapling.fetchers import Fetcher

page = Fetcher.get('https://quotes.toscrape.com/')
quotes = page.css('.quote .text::text').getall()
print(quotes)

적응형 말고 — 안티봇 우회, 대규모 크롤러, MCP

Scrapling이 한 라이브러리에 묶어 둔 나머지 세 가지도 실무에서 크다. 첫째, StealthyFetcher는 Cloudflare Turnstile 같은 안티봇 방어를 기본으로 우회한다. TLS 지문과 헤더를 실제 브라우저처럼 위장하고, 필요하면 solve_cloudflare 옵션으로 차단 화면을 풀고 지나간다. 예전에는 유료 서비스를 붙여야 넘던 벽이 라이브러리 옵션 하나가 됐다.

둘째, 대규모 수집을 위한 Spider 프레임워크가 있다. Scrapy처럼 start_urls와 parse 함수로 크롤러를 정의하고, 동시 요청 수 조절, 프록시 자동 로테이션, Ctrl+C로 멈췄다가 이어서 재개하는 pause·resume, 결과를 실시간으로 흘려보내는 스트리밍까지 지원한다. 한 사이트 몇 페이지부터 수백만 페이지 크롤까지 같은 도구로 확장된다.

셋째, AI와 붙이는 MCP 서버가 내장돼 있다. Claude나 Cursor 같은 AI 도구에 Scrapling을 MCP로 연결하면, AI가 웹페이지 전체를 통째로 삼키는 대신 Scrapling이 필요한 부분만 먼저 추출해 넘긴다. 그만큼 AI가 처리할 토큰이 줄어 속도와 비용이 함께 내려간다. AX 관점에서 특히 쓸모 있는 지점이다.

쓰기 전에 — 합법과 예의

도구가 쉬워졌다고 아무 데서나 긁어도 되는 건 아니다. 스크래핑은 대상 사이트의 이용약관, 로그인·유료 장벽, 개인정보, 저작권의 영향을 받는다. Scrapling에는 robots.txt를 존중하는 옵션(robots_txt_obey), 요청 사이 간격을 두는 지연, 도메인 차단 같은 장치가 들어 있다. 켜서 쓰는 게 상대 서버에 대한 예의이자 위험 관리다.

정리하면 Scrapling은 스크래핑을 한 번 짜고 계속 고치는 일에서, 한 번 짜고 두는 일로 옮기려는 시도다. 적응형 셀렉터가 유지보수를 줄이고, 안티봇 우회가 진입 장벽을 낮추고, MCP가 AI와의 연결 비용을 줄인다. 수집 자동화를 운영 중이거나 새로 붙이려 한다면, 한 번 짚어 볼 값어치가 있는 오픈소스다.