統合

Shifterと一緒に使用する Scrapy

ShifterのレジデンシャルおよびISP Proxiesを小さなダウンローダーミドルウェアを通じて任意の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

機能

Scrapy の標準ダウンローダーミドルウェアパイプラインに組み込めます。フォークやランタイムのパッチは不要です。
デフォルトはリクエストごとのローテーション。スティッキーセッションには`sid`、N秒間のタイムドピンには`ttl-N`を使用
scrapy-playwright、scrapy-splash、scrapy-rotating-proxiesとドロップイン互換
ユーザー名パラメータを使用した 195+ か国での Geo ターゲティング -- 国、地域、都市、ASN
Scrapy Cloud、Scrapyd、GitHub Actions、Airflow、およびあらゆるオーケストレーションレイヤーで動作します。
Scrapy 2.x および Python 3.7+ と互換性あり -- 同期・非同期コールバックの両方に対応

ダウンローダーミドルウェア(スティッキーセッション)

Scrapyにプロキシを組み込む標準的な方法です。ユーザー名に`sid`を追加すると、スパイダーからのすべてのリクエストが1つのレジデンシャル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()),
            }

国別スパイダー(並列ジオスクレイピング)

1つのスパイダークラスを構築し、実行時に国をパラメーター化します。それぞれが独自のレジデンシャル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に切り替えます。起動オプションにプロキシを渡してください。スケジューリングとパイプラインは引き続き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()
FAQ

よくある質問

Shifter と Scrapy の併用に関するよくある質問。

`request.meta['proxy']`をShifterのURLに設定する小さなダウンローダーミドルウェアを作成し、優先度を750未満(HttpProxyMiddlewareより前に実行されるように)でDOWNLOADER_MIDDLEWARESに登録します。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 を構築すると、そのスパイダーからのすべてのリクエストがUK の住宅IP を経由します。

はい。PLAYWRIGHT_LAUNCH_OPTIONSでプロキシを設定してください(`server`、`username`、`password`)。scrapy-playwrightはそれらをPlaywrightの起動呼び出しに転送し、拡張機能なしでヘッドレスモードのbasic-auth認証を処理します。

はい。Scrapy Cloudプロジェクトは通常のScrapyスパイダーです。ダウンローダーミドルウェアとShifterプロキシURLはプロジェクトのtarballに含まれます。認証情報をソースにコミットしないよう、Scrapy Cloudプロジェクト設定(または環境変数)として追加してください。

始める

でShifterを使い始める Scrapy

20 行のミドルウェアを通じて、Shifter の 205M+ レジデンシャル・ISP プロキシを Scrapy スパイダーに組み込みます。リクエストごとのローテーション、スティッキーセッション、および scrapy-playwright の完全サポートを提供します。

Shifterを無料で試す数分でセットアップ完了。いつでもキャンセル可能。