Shifter와 함께 사용 Scrapy
Shifter의 레지덴셜 및 ISP 프록시를 작은 다운로더 미들웨어를 통해 모든 Scrapy 스파이더에 연결하세요. 요청별 로테이션, 고정 세션, 스파이더별 지역 타겟팅을 단 20줄의 Python 코드로 구현할 수 있습니다.
빠른 시작
설치
pip install scrapy 기본 사용법
# settings.py
DOWNLOADER_MIDDLEWARES = {
"myproject.middlewares.ShifterProxyMiddleware": 350,
"scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": 360,
}
# middlewares.py
class ShifterProxyMiddleware:
PROXY = (
"customer-USERNAME-country-us-sid-123ABC:"
"PASSWORD@p.shifter.io:443"
)
def process_request(self, request, spider):
request.meta["proxy"] = self.PROXY
# Run as usual:
# scrapy crawl my_spider 기능
예시
Downloader Middleware(고정 세션)
Scrapy에 프록시를 연결하는 표준적인 방법입니다. 사용자 이름에 `sid`를 추가하면 스파이더의 모든 요청이 하나의 레지덴셜 IP를 공유하게 됩니다. 지역 타겟팅을 위해 `country-uk-city-london`을 추가하세요.
# myproject/middlewares.py
import secrets
class ShifterProxyMiddleware:
"""Routes every Scrapy request through Shifter's residential pool."""
def __init__(self, country="us", city=None, ttl=300):
self.sid = secrets.token_hex(4)
parts = [
"customer-USERNAME",
f"country-{country}",
]
if city:
parts.append(f"city-{city}")
parts.append(f"sid-{self.sid}")
parts.append(f"ttl-{ttl}")
username = "-".join(parts)
self.proxy_url = f"http://{username}:PASSWORD@p.shifter.io:443"
@classmethod
def from_crawler(cls, crawler):
s = crawler.settings
return cls(
country=s.get("SHIFTER_COUNTRY", "us"),
city=s.get("SHIFTER_CITY"),
ttl=s.getint("SHIFTER_TTL", 300),
)
def process_request(self, request, spider):
request.meta["proxy"] = self.proxy_url
# myproject/settings.py
DOWNLOADER_MIDDLEWARES = {
"myproject.middlewares.ShifterProxyMiddleware": 350,
"scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": 360,
}
SHIFTER_COUNTRY = "uk"
SHIFTER_CITY = "london" 요청별 로테이션
sid를 설정하지 마세요. 게이트웨이가 모든 요청마다 IP를 회전하도록 두세요. 각 페이지가 다른 방문자처럼 보여야 하는 페이지네이션 대상의 대용량 스크래핑에 유용합니다.
# myproject/middlewares.py
import secrets
class ShifterRotatingMiddleware:
"""Rotates the residential IP on every Scrapy request."""
PROXY_HOST = "p.shifter.io:443"
def process_request(self, request, spider):
# Unique sid per request -> guaranteed new IP for every fetch
unique_sid = secrets.token_hex(6)
username = (
f"customer-USERNAME-country-{spider.country}"
f"-sid-{unique_sid}"
)
request.meta["proxy"] = (
f"http://{username}:PASSWORD@{self.PROXY_HOST}"
)
# myproject/spiders/products.py
import scrapy
class ProductsSpider(scrapy.Spider):
name = "products"
country = "us" # consumed by the middleware
custom_settings = {
"DOWNLOADER_MIDDLEWARES": {
"myproject.middlewares.ShifterRotatingMiddleware": 350,
},
"CONCURRENT_REQUESTS": 32,
}
start_urls = [
f"https://example.com/products?page={i}" for i in range(1, 100)
]
def parse(self, response):
for card in response.css(".product-card"):
yield {
"title": card.css("h2::text").get(),
"price": card.css(".price::text").get(),
"url": response.urljoin(card.css("a::attr(href)").get()),
} 국가별 스파이더 (동시 지역 스크래핑)
스파이더 클래스 하나를 만들고 실행 시점에 국가를 매개변수화하세요. 각각 자체 레지덴셜 IP 풀을 가진 여러 인스턴스를 병렬로 실행할 수 있습니다.
# scrapy crawl localized -a country=uk
# scrapy crawl localized -a country=de
# scrapy crawl localized -a country=jp
import scrapy
class LocalizedSpider(scrapy.Spider):
name = "localized"
def __init__(self, country="us", *args, **kwargs):
super().__init__(*args, **kwargs)
self.country = country
self.start_urls = [
f"https://www.example.com/{country}/products",
]
def start_requests(self):
proxy = (
f"customer-USERNAME-country-{self.country}-sid-{self.country}-batch:"
f"PASSWORD@p.shifter.io:443"
)
for url in self.start_urls:
yield scrapy.Request(url, meta={"proxy": proxy}, callback=self.parse)
def parse(self, response):
for product in response.css(".product"):
yield {
"country": self.country,
"title": product.css("h2::text").get(),
"price": product.css(".price::text").get(),
} Scrapy + scrapy-playwright (JS 렌더링 페이지)
대상에 JavaScript가 필요할 때는 다운로더를 scrapy-playwright로 교체하세요. 프록시는 launch 옵션에 전달합니다 — Scrapy는 여전히 스케줄링과 파이프라인을 처리합니다.
# pip install scrapy-playwright
# playwright install chromium
# settings.py
DOWNLOAD_HANDLERS = {
"http": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
"https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
}
TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
PLAYWRIGHT_LAUNCH_OPTIONS = {
"headless": True,
"proxy": {
"server": "http://p.shifter.io:443",
"username": "customer-USERNAME-country-fr-sid-789GHI",
"password": "PASSWORD",
},
}
# spider.py
import scrapy
class JsHeavySpider(scrapy.Spider):
name = "js_heavy"
start_urls = ["https://app.example.com/dashboard"]
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(
url,
meta={"playwright": True, "playwright_include_page": True},
callback=self.parse,
)
async def parse(self, response):
page = response.meta["playwright_page"]
await page.wait_for_selector(".widget")
widgets = await page.query_selector_all(".widget")
for w in widgets:
yield {"label": await w.text_content()}
await page.close() 자주 묻는 질문
Scrapy와 Shifter 사용에 관한 일반적인 질문.
`request.meta['proxy']`를 Shifter URL로 설정하는 작은 다운로더 미들웨어를 작성한 다음, DOWNLOADER_MIDDLEWARES에 750보다 낮은 우선순위로 등록하십시오(HttpProxyMiddleware보다 먼저 실행되도록). Python 20줄이면 충분하며 SDK가 필요하지 않습니다.
process_request에서 새로운 sid를 생성하세요. 예를 들어 `secrets.token_hex(6)`을 사용하고 프록시 사용자명에 삽입합니다. 각 요청은 서로 다른 sid를 받게 되며, 따라서 Shifter의 게이트웨이로부터 서로 다른 레지덴셜 IP를 받게 됩니다. 외부 scrapy-rotating-proxies 의존성이 필요 없습니다.
전체 크롤링 실행에 대해 고정된 sid를 사용하세요. 스파이더 시작 시(또는 미들웨어 생성자에서) 한 번 생성하고 모든 요청에서 재사용하세요. `ttl-N`을 추가하면 IP 수명을 N초로 연장할 수 있습니다.
예. 스파이더 실행 시 `-a country=uk` 인수를 전달하거나, custom_settings에서 설정으로 노출하거나, 미들웨어 내부에서 읽으세요. 사용자 이름에 `country-uk`를 포함하여 프록시 URL을 구성하면, 해당 스파이더의 모든 요청이 영국 레지덴셜을 통과합니다.
예. PLAYWRIGHT_LAUNCH_OPTIONS에서 `server`, `username`, `password`로 프록시를 구성하세요. scrapy-playwright는 이를 Playwright의 launch 호출로 전달하며, 이 호출은 확장 프로그램 없이도 헤드리스 모드에서 basic-auth 인증을 처리합니다.
예. Scrapy Cloud 프로젝트는 단순히 Scrapy 스파이더일 뿐이며, 다운로더 미들웨어와 Shifter 프록시 URL은 프로젝트 tarball 안에 포함되어 배포됩니다. 소스에 커밋되지 않도록 인증 정보는 Scrapy Cloud 프로젝트 설정(또는 환경 변수)으로 추가하세요.
Shifter 사용을 함께 시작하기 Scrapy
20줄 미들웨어를 통해 Shifter의 2억 500만+ 레지덴셜 및 ISP 프록시를 Scrapy 스파이더에 연결하세요. 요청별 로테이션, 고정 세션, 완전한 scrapy-playwright 지원을 제공합니다.