# Scrapy proxy middleware สำหรับพร็อกซีเรซิเดนเชียลหมุนเวียน

> Scrapy proxy middleware หมุนเวียนพร็อกซีเรซิเดนเชียลแบบหมุนและติดหนึบต่อต่อคำขอ, ตั้งค่า AutoThrottle และ retry, scrapy-playwright โค้ดตรวจสอบไวยากรณ์แล้ว

- URL: https://crawlrelay.com/th/docs/scrapy/
- อัปเดตล่าสุด: 2026-10-13
- Publisher: CrawlRelay (https://crawlrelay.com)

ดาวน์โหลด middleware 30 บรรทัดที่เลือกประเทศและเซสชันต่อต่อคำขอ รวมถึงตั้งค่าที่ช่วยให้การครอว์ลสุภาพ: robots.txt, concurrency ต่อโดเมน, AutoThrottle และ retries

**คำตอบด่วน — ฉันจะใช้พร็อกซีหมุนเวียนร่วมกับ Scrapy ได้อย่างไร?**

ตั้งค่า `request.meta["proxy"]` เป็น `http://USERNAME:PASSWORD@gw.crawlrelay.com:7777` ใน downloader middleware ตัวเล็กที่ทำงานก่อน Scrapy `HttpProxyMiddleware`; Scrapy จะส่งข้อมูลรับรองให้คุณด้วย ในพร็อกซีเรซิเดนเชียล **CrawlRelay** ประเทศและเซสชันติดหนึบจะอยู่ในชื่อผู้ใช้ ทำให้ middleware ตัวเดียวจัดการได้ทั้งสองอย่าง ค่าใช้จ่ายทราฟฟิกเริ่มต้นที่ US$0.50/GB จาก 50 GB จ่ายด้วยคริปโต โดยไม่ต้อง KYC

## การตั้งค่า Scrapy เบื้องต้น

| คุณลักษณะ | ค่า |
| --- | --- |
| ตำแหน่งพร็อกซี | `request.meta["proxy"]` กำหนดโดย middleware ของคุณ |
| ลำดับ middleware | middleware ของคุณต่ำกว่า 750 ซึ่งเป็นลำดับของ `HttpProxyMiddleware` ที่มากับตัวโปรแกรม |
| ข้อมูลรับรอง | ใน URL ของพร็อกซี; Scrapy จะแปลงเป็น header `Proxy-Authorization` |
| SOCKS5 | ไม่รองรับกับตัวจัดการ HTTP/1.1 เริ่มต้น Scrapy 2.17+ รองรับ SOCKS ผ่าน HttpxDownloadHandler ตัวเลือก พอร์ต HTTP 7777 ง่ายที่สุด |
| การหมุนเวียน | สร้าง exit ใหม่ต่อการเชื่อมต่อใหม่; ID เซสชันเฉพาะต่อคำขอมักให้ IP ต่างกัน |
| ความสุภาพ | `ROBOTSTXT_OBEY`, `CONCURRENT_REQUESTS_PER_DOMAIN`, `AUTOTHROTTLE_ENABLED` |
| Retries | สถานะ 429 และ 5xx อยู่ใน `RETRY_HTTP_CODES` เริ่มต้น; Retry-After ไม่ได้ถูกอ่านโดยค่าเริ่มต้น |

## ฉันจะเขียน proxy middleware อย่างไร?

ใส่คลาสใน `middlewares.py` สร้างชื่อผู้ใช้จากการตั้งค่าและกุญแจ `meta` ตัวเลือกสามตัว: `proxy_country`, `proxy_session` และ `proxy_ttl` คำขอไม่มี `proxy_session` จะหมุนเวียน IP; คำขอมี `proxy_session="new"` จะได้เซสชันใหม่จึงมักเป็น exit IP ที่ต่างกัน; คำขอที่มีเซสชัน ID ตายตัวจะแชร์ exit เดียวกับคำขออื่นของ flow เดียวกัน middleware จะคำนวณพร็อกซีใหม่ในทุกขั้นตอนรวมการลองใหม่ และไม่แตะพร็อกซีที่ตั้งโดยโค้ดอื่น หาก `CRAWLRELAY_USER` หายไป การครอว์ลจะหยุดตอนเริ่ม แทนที่จะรันจาก IP ของคุณเอง

*middlewares.py*

```python
import uuid
from urllib.parse import quote


class CrawlRelayProxyMiddleware:
    """Sets request.meta["proxy"]; Scrapy's HttpProxyMiddleware then sends the credentials."""

    def __init__(self, user, password, country):
        self.user, self.password, self.country = user, password, country

    @classmethod
    def from_crawler(cls, crawler):
        s = crawler.settings
        if not s.get("CRAWLRELAY_USER"):
            # Fail loudly: NotConfigured would only disable the middleware and crawl from your own IP
            raise ValueError("CRAWLRELAY_USER is not set: refusing to crawl without the proxy")
        return cls(s.get("CRAWLRELAY_USER"), s.get("CRAWLRELAY_PASSWORD", ""), s.get("CRAWLRELAY_COUNTRY", "us"))

    def process_request(self, request, spider=None):
        if "proxy" in request.meta and not request.meta.get("_crawlrelay"):
            return None  # a proxy set by other code: leave it alone
        parts = [self.user, "country", request.meta.get("proxy_country", self.country)]
        session = request.meta.get("proxy_session")
        if session == "new":  # a fresh session for this request (and for each of its retries)
            session = uuid.uuid4().hex[:12]
        if session:
            parts += ["session", session, "ttl", str(request.meta.get("proxy_ttl", 10))]
        username = "-".join(parts)
        request.meta["proxy"] = "http://%s:%s@gw.crawlrelay.com:7777" % (
            quote(username, safe=""), quote(self.password, safe=""))
        request.meta["_crawlrelay"] = True
        return None
```

## การตั้งค่า Scrapy ตัวไหนที่ช่วยให้การครอว์ลผ่านพร็อกซีสุภาพและเร็ว?

พร็อกซีช่วยกระจายคำขอของคุณผ่าน IP หลายหมายเลข แต่เป้าหมายยังเห็นอัตราการส่งทั้งหมด การตั้งค่าเหล่านี้ควบคุมโดเมนแต่ละแห่งให้ทำงานในจังหวะที่ยั่งยืนและให้ AutoThrottle ชะลอตัวเองเมื่อการตอบสนองช้าลง ให้รักษา `ROBOTSTXT_OBEY = True` ซึ่งโปรเจกต์ Scrapy ใหม่ตั้งไว้แล้ว

*settings.py (ตอนหนึ่ง)*

```python
import os

BOT_NAME = "myproject"
ROBOTSTXT_OBEY = True
USER_AGENT = "ExampleCrawler/1.0 (+https://example.com/crawler-info)"

CRAWLRELAY_USER = os.environ.get("CRAWLRELAY_USER")  # e.g. the username from your dashboard
CRAWLRELAY_PASSWORD = os.environ.get("CRAWLRELAY_PASSWORD")
CRAWLRELAY_COUNTRY = "us"

DOWNLOADER_MIDDLEWARES = {
    "myproject.middlewares.CrawlRelayProxyMiddleware": 350,  # runs before HttpProxyMiddleware (750)
}

CONCURRENT_REQUESTS = 32
CONCURRENT_REQUESTS_PER_DOMAIN = 4
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 1.0
AUTOTHROTTLE_MAX_DELAY = 30.0
AUTOTHROTTLE_TARGET_CONCURRENCY = 2.0

RETRY_ENABLED = True
RETRY_TIMES = 3
RETRY_HTTP_CODES = [429, 500, 502, 503, 504, 522, 524, 408]
DOWNLOAD_TIMEOUT = 45
```

## ฉันจะรักษา IP เดียวสำหรับการแบ่งหน้าและสลับสำหรับหน้ารายการอย่างไร?

ส่งพร็อกซีเรซิเดนเชียลคงที่ `proxy_session` ในคำขอของโฟลว์ที่ขึ้นอยู่กับหน้าก่อนหน้า และไม่ต้องส่งในหน้าที่เป็นอิสระ แมงมุมข้างล่างนี้รันบน books.toscrape.com ซึ่งเป็นไซต์ทดลองสำหรับฝึกขูดข้อมูล

*spiders/catalog.py*

```python
import scrapy


class CatalogSpider(scrapy.Spider):
    name = "catalog"
    start_urls = ["https://books.toscrape.com/"]

    def parse(self, response):
        for href in response.css("article.product_pod h3 a::attr(href)").getall():
            # Product pages are independent: rotating exits
            yield response.follow(href, callback=self.parse_item)
        next_page = response.css("li.next a::attr(href)").get()
        if next_page:
            # The listing flow keeps one sticky exit for 30 minutes
            yield response.follow(next_page, callback=self.parse,
                                  meta={"proxy_session": "listing1", "proxy_ttl": 30})

    def parse_item(self, response):
        yield {
            "title": response.css("div.product_main h1::text").get(),
            "price": response.css("p.price_color::text").get(),
            "url": response.url,
        }
```

## Scrapy ใช้การเชื่อมต่อซ้ำหรือไม่ และนั่นจะหยุดการสลับหรือเปล่า?

ใช่ Scrapy รักษาการเชื่อมต่อให้คงอยู่และใช้ซ้ำตามพร็อกซีและโฮสต์เป้าหมาย ดังนั้นคำขอที่ต่อเนื่องในการเชื่อมต่อเดียวกันจะใช้ทางออกเดียวกัน สำหรับการครอว์ส่วนใหญ่ถือว่าโอเค: Scrapy เปิดได้สูงสุดถึง `CONCURRENT_REQUESTS_PER_DOMAIN` การเชื่อมต่อต่อเว็บไซต์ และแต่ละการเชื่อมต่อใหม่โดยปกติจะได้ IP residential ที่แตกต่างกัน

เมื่อคำขอต้องส่งออกผ่าน IP ใหม่ เช่น การลองใหม่หลังจากได้ [502](https://crawlrelay.com/th/docs/errors/502-bad-gateway/) จากทางออกที่ล้มเหลว ให้ส่งคำขออีกครั้งโดยมี `response.request.replace(meta={**response.meta, "proxy_session": "new"}, dont_filter=True)` กลาง หลักการทำงานของ middleware จะสร้างชื่อผู้ใช้เซสชันใหม่ ชื่อผู้ใช้ที่ต่างกันหมายถึงกลุ่มการเชื่อมต่อที่ต่างกัน ดังนั้น Scrapy จะเปิดการเชื่อมต่อใหม่และเกตเวย์มักจะมอบทางออกที่แตกต่างกัน

## ฉันจะปฏิบัติตาม Retry-After ในการตอบสนอง 429 ใน Scrapy อย่างไร?

Scrapy มีระบบ `RetryMiddleware` ที่ลองทำซ้ำกับ 429 แต่ไม่รอช่วงหยุดชั่วคราว `Retry-After` AutoThrottle จะค่อย ๆ ลดความถี่ของโดเมน ทำให้สถานการณ์โดยส่วนใหญ่นั้นเพียงพอ สำหรับ API ที่ส่งค่า `Retry-After` ยาว ๆ เพิ่ม middleware เล็ก ๆ ที่อ่านเฮดเดอร์และตั้งเวลาการลองใหม่พร้อมหยุดชั่วคราว หรือปรับลด `CONCURRENT_REQUESTS_PER_DOMAIN` สำหรับโดเมนนั้น หน้าของ [429](https://crawlrelay.com/th/docs/errors/429-too-many-requests/) อธิบายความหมายของเฮดเดอร์

## ฉันจะใช้พร็อกซีกับ scrapy-playwright อย่างไร?

สำหรับหน้าที่ต้องใช้ JavaScript scrapy-playwright จะส่งตัวเลือกการเปิดตัวของ Playwright ผ่านการตั้งค่า ให้ใส่ข้อมูลรับรองเป็นฟิลด์แยก Chromium ไม่ยอมรับข้อมูลรับรองที่เขียนใน URL ของเซิร์ฟเวอร์ ใช้ 1 คอนเท็กซ์ต่อเซสชันติดหนึบหากคุณเรนเดอร์โฟลว์ที่ล็อกเอาท์ซึ่งครอบคลุมหลายหน้า

*settings.py สำหรับ scrapy-playwright*

```python
import os

DOWNLOAD_HANDLERS = {
    "http": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
    "https": "scrapy_playwright.handler.ScrapyPlaywrightDownloadHandler",
}
TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"

PLAYWRIGHT_LAUNCH_OPTIONS = {
    "proxy": {
        "server": "http://gw.crawlrelay.com:7777",
        "username": os.environ.get("CRAWLRELAY_USER", "USERNAME") + "-country-us",
        "password": os.environ.get("CRAWLRELAY_PASSWORD", "PASSWORD"),
    },
}
```

## คำถามเกี่ยวกับ Scrapy และพร็อกซี

### ฉันจำเป็นต้องใช้ scrapy-rotating-proxies หรือรายชื่อพร็อกซีหรือไม่?

ไม่จำเป็น แพ็กเกจเหล่านั้นจะสลับที่อยู่พร็อกซีทีละตัวและบล็อกตัวที่ล้มเหลว ในเกตเวย์ residential การสลับเกิดขึ้นภายใต้ที่อยู่เดียว: การเชื่อมต่อใหม่จะได้รับ residential IP ที่แตกต่างกันเท่านั้น มิดเดิลแวร์ตัวเดียวที่ตั้งค่า `request.meta["proxy"]` ก็เพียงพอแล้ว

### ทำไม Scrapy ถึงแสดง TunnelError กับพร็อกซีของฉัน?

`TunnelError: Could not open CONNECT tunnel` หมายความว่าพร็อกซีปฏิเสธหรือไม่สำเร็จในการร้องขอ CONNECT สำหรับเว็บ HTTPS สถานะในข้อความแจ้งเหตุผล: 407 คือข้อมูลรับรอง, 502 หรือ 504 คือทางออกหรือเป้าหมาย ดูที่หน้าของ [407](https://crawlrelay.com/th/docs/errors/407-proxy-authentication-required/) และ [502](https://crawlrelay.com/th/docs/errors/502-bad-gateway/)

### ฉันควรใช้จำนวนคำขอพร้อมกันต่อโดเมนเท่าไหร่?

เริ่มที่ 2 ถึง 4 ต่อโดเมน และปล่อย AutoThrottle ปรับเพิ่มทีละน้อย เพิ่มจำนวนขึ้นเฉพาะเมื่อเปอร์เซ็นต์ 429, 403 และ 5xx ยังคงที่ และสังเกตเวลาตอบสนองของเว็บไซต์ เว็บใหญ่จะรับได้มากกว่าเว็บเล็ก เว็บเล็กอาจต้องหน่วงเวลาระหว่างคำขอและใช้การเชื่อมต่อเดี่ยว

### ฉันควรปิด ROBOTSTXT_OBEY เพื่อให้ได้ข้อมูลมากขึ้นหรือไม่?

ไม่ควร robots.txt คือวิธีที่เว็บบอกเส้นทางที่อนุญาตให้ไคลเอนต์อัตโนมัติสามารถเข้าถึงได้ และ RFC 9309 ได้มาตรฐานรูปแบบนี้ในปี 2022 การละเลยจะเพิ่มความเสี่ยงทางกฎหมายและจริยธรรม รวมถึงละเมิด [นโยบายการใช้งานที่ยอมรับได้](https://crawlrelay.com/th/acceptable-use/) หากใช้เพื่อเข้าถึงเนื้อหาที่เว็บไซต์ปิดกั้น

### การครอว์ Scrapy ใช้ปริมาณข้อมูลขนาดไหน?

Scrapy ดาวน์โหลดแค่ HTML เท่านั้น ดังนั้นแต่ละหน้าจะมีขนาดไม่กี่สิบกิโลไบต์ (บีบอัดแล้ว) ตรวจสอบค่า `downloader/response_bytes` ในสถิติที่ Scrapy แสดงเมื่อจบการทำงานแล้วหารด้วยจำนวนการตอบกลับ คู่มือ [แบนด์วิดท์](https://crawlrelay.com/th/guides/bandwidth-calculator/) จะช่วยคำนวณค่าใช้จ่ายจากข้อมูลนั้น

**เสียบ residential IPs ลงในโปรเจกต์ Scrapy ของคุณ** US$5.94 สำหรับ 10 GB เพื่อทดสอบ, US$0.50/GB จาก 50 GB [ดูราคา](https://crawlrelay.com/th/pricing/) · [คู่มือจำนวนคำขอพร้อมกัน](https://crawlrelay.com/th/docs/concurrency/)

---

CrawlRelay: CrawlRelay คือพร็อกซีเรซิเดนเชียลหมุนเวียนพร้อมพร็อกซีมือถือ 4G/5G สำหรับนักพัฒนา เหมาะกับสแครปเปอร์และระบบจัดการข้อมูล AI: เติมเงินจ่ายตามการใช้งานจาก US$0.50/GB จ่ายด้วยคริปโต ไม่ต้องอัปโหลดบัตรประชาชน ไม่ต้อง KYC — ไม่ต้องใช้บัตรประชาชน ไม่ต้องถ่ายเซลฟี่ ไม่ต้องใช้เอกสาร จ่ายด้วยคริปโต
