คำตอบด่วน
ฉันสามารถรันคำขอพร้อมกันกี่รายการผ่านพร็อกซีเรซิเดนเชียลได้?
ได้มากเท่าที่แต่ละเป้าหมายยอมรับ: CrawlRelay คิดค่าบริการจากปริมาณข้อมูลพร็อกซีเรซิเดนเชียลตาม GB (US$0.50/GB เริ่มต้นที่ 50 GB) ไม่ใช่ต่อเทรดหรือการเชื่อมต่อ กำหนดความพร้อมใช้งานตามกฎ Little’s law โดยคำขอที่กำลังดำเนินการ = หน้าเว็บต่อวินาที × วินาทีต่อหน้าเว็บ แล้วจำกัดต่อโฮสต์ เริ่มที่ 2 ถึง 4 ลดลงเมื่อเจอการตอบสนอง 429 หรือ 503 ชำระด้วยคริปโต โดยไม่ต้อง KYC
ความพร้อมใช้งานโดยย่อ
| การคิดค่าบริการ | คิดตาม GB ของข้อมูลที่ส่งผ่าน; ไม่คิดค่าบริการต่อเทรดหรือการเชื่อมต่อ |
|---|---|
| กฎการกำหนดขนาด | กำลังดำเนินการ = ปริมาณงาน × ความหน่วงเวลา (กฎของ Little) |
| จุดเริ่มต้นต่อโฮสต์ | คำขอพร้อมกัน 2–4 รายการ; 1 รายการมีดีเลย์สำหรับไซต์ขนาดเล็ก |
| สัญญาณให้ชะลอ | 429, 503, เวลาในการตอบสนองที่เพิ่มขึ้น, หน้าเว็บท้าทาย |
| คำนวณแบนด์วิดท์ | หน้าเว็บต่อวินาที × ไบต์ต่อหน้า × 3,600 = ไบต์ต่อชั่วโมง |
| ค่ากลางเวลาตอบสนองพร็อกซีเรซิเดนเชียล | 0.93 วินาทีบนเครือข่ายพร็อกซี, 3.21 วินาทีบนเป้าหมายจริง (Proxyway 2026) |
ฉันควรกำหนดความพร้อมใช้งานอย่างไรจากปริมาณงานที่ต้องการ?
ใช้กฎ Little's law: จำนวนคำขอที่กำลังดำเนินการเท่ากับอัตราที่ต้องการคูณด้วยเวลาที่ใช้ต่อคำขอ งานวิจัยตลาดพร็อกซีของ Proxyway 2026 วัดค่ากลางที่ 3.21 วินาทีต่อคำขอบนเป้าหมายจริงผ่านพร็อกซีเรซิเดนเชียล ดังนั้นวางแผนที่ 2 ถึง 4 วินาทีสำหรับเว็บไซต์จริง ไม่ใช่แค่องค์ประกอบในระดับเครือข่ายที่ต่ำกว่า 1 วินาที
| เป้าหมาย | เวลาแต่ละคำขอ | คำขอที่กำลังดำเนินการ |
|---|---|---|
| 5 หน้าเว็บต่อวินาที | 2 วินาที | 10 |
| 20 หน้าเว็บต่อวินาที | 2 วินาที | 40 |
| 20 หน้าเว็บต่อวินาที | 4 วินาที | 80 |
| 100 หน้าเว็บต่อวินาที | 3 วินาที | 300 |
จากนั้นกระจายคำขอเหล่านั้นไปยังโฮสต์ต่างๆ สี่สิบคำขอพร้อมกันบน 200 เว็บไซต์ถือว่ายังนุ่มนวล แต่ถ้าใช้ 40 คำขอบนเว็บไซต์เล็กๆ ที่เดียวกัน นั่นคือการทดสอบโหลดที่มันไม่ยอมรับ
ปริมาณแบนด์วิดท์ที่ใช้จากปริมาณงานนี้เท่าไหร่?
คูณหน้าเว็บต่อวินาทีด้วยไบต์ต่อหน้าเว็บ ที่ 20 หน้า HTML ต่อวินาทีและ 50 KB ต่อหน้า เว็บรวบรวมข้อมูลจะย้ายข้อมูล 1 MB ต่อวินาที หรือ 3.6 GB ต่อชั่วโมง และประมาณ 86 GB ต่อวัน ถ้าหน้าแสดงผลขนาด 2 MB ที่อัตราเดียวกันจะย้ายข้อมูล 40 MB ต่อวินาที
คูณผลลัพธ์ด้วยราคาต่อ GB ของแผนคุณ US$0.50/GB เริ่มต้นที่ 50 GB ที่ราคา CrawlRelay เพื่อคำนวณค่าบริการรายชั่วโมง คู่มือ เครื่องมือคำนวณแบนด์วิดท์ แสดงขนาดหน้าเว็บทั่วไปตามประเภทหน้าเว็บ
ฉันควรตั้งขีดจำกัดต่อโฮสต์เริ่มต้นอย่างไร?
| เป้าหมาย | คำขอพร้อมกันต่อโฮสต์ | ดีเลย์ระหว่างคำขอ | หมายเหตุ |
|---|---|---|---|
| ไซต์เล็ก (บล็อก, ร้านค้าท้องถิ่น) | 1 | 2–5 วินาที | เคารพ Crawl-delay ใน robots.txt หากมี |
| เว็บไซต์ขนาดกลาง | 2–4 | 0.5–2 วินาที | ตรวจสอบเวลาในการตอบกลับ; ลดความเร็วเมื่อเวลาตอบกลับเพิ่มเป็นสองเท่า |
| แพลตฟอร์มขนาดใหญ่พร้อม CDN | 4–16 | AutoThrottle หรือปรับตามอัตโนมัติ | เพิ่มความเร็วเฉพาะขณะที่อัตรา 429 และ 5xx คงที่ |
| API สาธารณะ | ขีดจำกัดที่ระบุไว้ | ตามที่ระบุไว้ | ใช้คีย์ API และขีดจำกัดที่ผู้ให้บริการกำหนดให้คุณ |
ฉันจะปรับจำนวนงานพร้อมกันโดยอัตโนมัติได้อย่างไร?
ใช้การเพิ่มแบบสะสมและลดแบบทวีคูณ ตามกฎที่ TCP ใช้สำหรับการควบคุมความแออัด: เพิ่มช่องว่างหนึ่งช่องหลังจากการตอบสนองที่สะอาดติดต่อกัน และลดขีดจำกัดลงครึ่งหนึ่งเมื่อเจอ 429 หรือ 503 ตัวจำกัดด้านล่างนี้เก็บขีดจำกัดหนึ่งชุดต่อโฮสต์ หยุดทุกคำขอต่อโฮสต์นั้นเป็นเวลา Retry-After วินาที ลองใหม่ครั้งเดียว และไม่เกินขีดจำกัดสูงสุดที่คุณตั้งไว้ ข้อผิดพลาดเครือข่ายจะแสดงเป็นค่า ดังนั้นการหมดเวลาหนึ่งครั้งไม่หยุดการประมวลผลทั้งหมด
import asyncio
import random
from urllib.parse import urlsplit
import httpx
PROXY = "http://USERNAME-country-us:[email protected]:7777"
class AdaptiveLimit:
"""One per host: +1 slot after 20 clean responses, halve on 429/503, pause for Retry-After."""
def __init__(self, start=2, low=1, high=16):
self.limit, self.low, self.high = start, low, high
self.in_flight, self.clean = 0, 0
self.pause_until = 0.0
self.cond = asyncio.Condition()
async def __aenter__(self):
loop = asyncio.get_running_loop()
while True:
async with self.cond:
await self.cond.wait_for(lambda: self.in_flight < self.limit)
delay = self.pause_until - loop.time()
if delay <= 0:
self.in_flight += 1
return self
await asyncio.sleep(delay) # the host asked for a pause: wait outside the lock
async def __aexit__(self, *exc):
async with self.cond:
self.in_flight -= 1
self.cond.notify_all()
def record(self, status, retry_after=None):
if status in (429, 503):
self.limit, self.clean = max(self.low, self.limit // 2), 0
wait = int(retry_after) if retry_after and retry_after.isdigit() else 5 + random.random()
now = asyncio.get_running_loop().time()
self.pause_until = max(self.pause_until, now + wait)
elif status < 400:
self.clean += 1
if self.clean >= 20 and self.limit < self.high:
self.limit, self.clean = self.limit + 1, 0
gates = {}
def gate_for(url):
host = urlsplit(url).hostname
if host not in gates:
gates[host] = AdaptiveLimit()
return gates[host]
async def fetch(client, url, attempts=2):
gate = gate_for(url)
status = None
for _ in range(attempts):
try:
async with gate:
r = await client.get(url)
except httpx.HTTPError as exc:
return "error: %s" % type(exc).__name__
status = r.status_code
gate.record(status, r.headers.get("Retry-After"))
if status not in (429, 503):
break # the retry, if any, waits for the host's pause in __aenter__
return status
async def main(urls):
timeout = httpx.Timeout(30.0, connect=10.0)
async with httpx.AsyncClient(proxy=PROXY, timeout=timeout) as client:
print(await asyncio.gather(*(fetch(client, u) for u in urls)))
print({host: gate.limit for host, gate in gates.items()})
asyncio.run(main(["https://example.com/"] * 10))อะไรที่ทำให้การครอว์ลผ่านพร็อกซีช้าลง นอกเหนือจากเป้าหมาย?
- TLS handshakes. การเชื่อมต่อต่อคำขอซึ่งคุณต้องการสำหรับ IP ใหม่́ในแต่ละครั้ง จะมีการจับมือกับเว็บไซต์ทุกครั้ง เก็บการเชื่อมต่อแบบติดหนึบด้วย keep-alive สำหรับหน้าของไซต์เดียวเมื่อความหลากหลายของ IP ไม่สำคัญ
- การเชื่อมต่อออกที่ช้า. พร็อกซีเรซิเดนเชียลและพร็อกซีมือถือ 4G เป็นการเชื่อมต่อที่แท้จริงผ่านบ้านและเครือข่ายมือถือ ใช้การหมดเวลาและลองใหม่ด้วยการเชื่อมต่อใหม่แทนการรอ
- เป้าหมายแคบ. เมืองเล็กหรือ ASN เดียวมีการเชื่อมต่อออกน้อยกว่าประเทศ ตั้งเป้าเฉพาะในพื้นที่ที่ข้อมูลเปลี่ยนแปลงเท่านั้น
- การเรนเดอร์. เบราว์เซอร์แบบไม่มีอินเทอร์เฟซใช้ CPU หน่วยความจำและทราฟฟิกมากกว่าลูกค้า HTTP มาก เรนเดอร์เฉพาะหน้าที่ต้องใช้ JavaScript
- DNS. กับ
socks5h://หรือพอร์ต HTTP การแก้ไข DNS จะเกิดขึ้นที่พร็อกซี ไม่จำเป็นต้องมีแคชการแก้ไข DNS ในเครื่องสำหรับโฮสต์เป้าหมาย
คำถามเรื่องจำนวนงานพร้อมกัน
CrawlRelay จำกัดจำนวนเธรดหรือการเชื่อมต่อหรือไม่?
แผนราคาคิดตาม GB ของทราฟฟิก ไม่ได้คิดตามจำนวนเธรด การเชื่อมต่อ หรือคำขอ และแผนราคาที่เผยแพร่ไม่ได้จำกัดจำนวนเธรด ข้อจำกัดที่ใช้งานจริงคือความสามารถของเป้าหมายแต่ละอันและเครื่องของคุณเอง ถ้าคุณวางแผนครอว์ลขนาดใหญ่มาก ให้เขียนไปที่ [email protected] ก่อนเพื่อให้เราตรวจสอบความครอบคลุมสำหรับเป้าหมายของคุณ
ทำไมการครอว์ลช้าลงเมื่อเพิ่มเธรด?
โดยปกติเพราะเป้าหมายเริ่มจำกัดคุณ: เวลาในการตอบกลับเพิ่มขึ้น, มีการตอบกลับ 429 หรือ 503 ปรากฏ และการลองใหม่เพิ่มภาระงาน สาเหตุทั่วไปอีกอย่างคือเครื่องของคุณเอง CPU หรือซ็อกเก็ตหมด โดยเฉพาะอย่างยิ่งกับเบราว์เซอร์แบบไม่มีอินเทอร์เฟซ วัดความล่าช้าและอัตราความผิดพลาดต่อโฮสต์ก่อนเพิ่มเธรด
การเชื่อมต่อหนึ่งครั้งต่อหนึ่งคำขอช้ากว่าการใช้ keep-alive หรือไม่?
ใช่ เพราะต้องมีการจับมือ TCP และ TLS ต่อคำขอหนึ่งครั้ง โดยทั่วไปอยู่ในช่วงไม่กี่ร้อยมิลลิวินาทีผ่านพร็อกซีเรซิเดนเชียล นี่คือราคาของ IP ใหม่ในทุกคำขอ สำหรับหลายหน้าของเว็บไซต์เดียวที่ IP ไม่สำคัญ การเชื่อมต่อแบบติดหนึบด้วย keep-alive จะเร็วกว่าและใช้ทราฟฟิกน้อยกว่า
ฉันจะปฏิบัติตาม robots.txt crawl-delay ในการครอว์ลพร้อมกันได้อย่างไร?
อ่าน robots.txt เพียงครั้งเดียวต่อโฮสต์ เก็บแคชไว้ได้นานถึง 24 ชั่วโมงตามที่ RFC 9309 แนะนำ และแปลงค่า Crawl-delay ให้เป็นช่องว่างขั้นต่ำระหว่างคำขอต่อโฮสต์โดยมีจำนวนงานพร้อมกันเป็น 1 Python's urllib.robotparser เปิดให้ใช้งานฟีเจอร์นี้ผ่าน crawl_delay()
ขยายตามราคาต่อ GB
US$0.50/GB จาก 50 GB ถึง 1 TB ทราฟฟิกที่ไม่มีวันหมดอายุ