Scrape โดยไม่ถูกบล็อก: คู่มือปฏิบัติพร้อมโค้ด
การถูกบล็อกระหว่าง scraping มักหมายถึงสามสิ่ง: คุณส่ง request มากเกินไปเร็วเกินไป client ของคุณดูไม่เหมือนเบราว์เซอร์หรือบอทที่รู้จักเลย หรือ IP address ของคุณอยู่ในรายการที่เว็บไซต์เชื่อถือน้อยลง คุณลดทั้งสามอย่างได้ด้วยนิสัยไม่กี่อย่าง: สังเกตการบล็อกให้เร็ว ชะลอเมื่อเว็บไซต์ตอบโต้ รักษาตัวตนที่สม่ำเสมอและซื่อตรง และใช้ proxy เฉพาะที่เหมาะสม คู่มือนี้อธิบายแต่ละข้อพร้อมโค้ดที่ใช้งานได้ ใช้สำหรับเว็บไซต์ที่คุณได้รับอนุญาตให้ scrape
รู้จักการบล็อก
การบล็อกไม่ได้เป็นหน้า error เสมอไป ให้สังเกต:
- 403 Forbidden มักหมายถึงเว็บไซต์ปฏิเสธ client ของคุณ หยุดและตรวจว่าคุณได้รับอนุญาตให้อยู่ที่นั่นหรือไม่ ก่อนลองอีกครั้ง
- 429 Too Many Requests หมายถึงคุณส่งมากเกินไป มักมาพร้อม header
Retry-After - 503 Service Unavailable อาจหมายถึงเว็บไซต์โหลดเกินกำลัง ให้ถอยออกมา
- การตอบกลับ 200 ที่มีเนื้อหาแทบไม่มี การ redirect ไปยังหน้าล็อกอินหรือความท้าทาย หรือหน้าที่ขาดข้อมูลที่คุณคาดหวัง
บันทึก status code และตัวอย่างสั้น ๆ ของ body สำหรับทุกความล้มเหลว การบล็อกที่คุณมองไม่เห็นใน log คือการบล็อกที่คุณแก้ไม่ได้
ถอยออกด้วย retry
เมื่อเว็บไซต์บอกว่า "ช้าลง" โค้ดของคุณต้องช้าลงมากกว่าเล็กน้อย การถอยแบบ exponential พร้อมจำกัดจำนวนครั้งที่ลองเป็นแนวทางมาตรฐาน และยังเคารพ Retry-After เมื่อเว็บไซต์ส่งมา:
import time
import requests
session = requests.Session()
session.headers.update({
"User-Agent": "ExampleBot/1.0 (+https://example.com/bot)",
"Accept-Language": "en-US,en;q=0.9",
})
def polite_get(url: str, max_attempts: int = 4) -> requests.Response:
delay = 2.0
resp = None
for _ in range(max_attempts):
resp = session.get(url, timeout=30)
if resp.status_code not in (429, 503):
return resp
retry_after = resp.headers.get("Retry-After", "")
wait = float(retry_after) if retry_after.isdigit() else delay
time.sleep(wait)
delay *= 2
return resp # ยังถูกบล็อกอยู่: คืน response สุดท้ายให้ผู้เรียกจัดการ
resp = polite_get("https://example.com/products?page=1")
print(resp.status_code, len(resp.text))
สังเกตสิ่งที่ฟังก์ชันนี้ไม่ทำ มันไม่ retry การตอบกลับ 403 และไม่หมุนผ่านตัวตนเพื่อเลี่ยงการบล็อกหนึ่งครั้ง 403 คือการตัดสินใจให้หยุด ไม่ใช่ปริศนาที่ต้องแก้
วินิจฉัยการบล็อกทีละขั้น
เมื่อการรันเริ่มล้มเหลว ให้ไล่ตรวจตามนี้ก่อนเปลี่ยนอย่างอื่น:
- ดู URL ที่ล้มเหลวเป็นครั้งแรกและ status code การบล็อกมักเริ่มที่จุดเฉพาะ ไม่ใช่สุ่ม
- เปรียบเทียบอัตรา request ในไม่กี่นาทีก่อนความล้มเหลวแรก การพุ่งเป็นชุดคือสาเหตุที่พบบ่อยที่สุด
- ตรวจว่าความล้มเหลวผูกกับ path หนึ่ง ส่วนหนึ่ง หรือช่วงเวลาของวันหรือไม่
- เปิด URL เดียวกันด้วยมือในเบราว์เซอร์ปกติหนึ่งครั้ง หากเบราว์เซอร์โหลดได้ ความต่างอยู่ที่รูปแบบ request ของคุณ หากเบราว์เซอร์ถูกบล็อกด้วย แสดงว่าเว็บไซต์หยุดให้บริการหน้านั้นกับคุณชั่วคราว
- แก้โค้ดหลังจากนั้นเท่านั้น ชะลอก่อน เพิ่ม backoff ที่สอง และทบทวนตัวตนเป็นอย่างสุดท้าย
การเปลี่ยนหลายอย่างพร้อมกันทำให้ไม่สามารถรู้ได้ว่าอะไรช่วย
รักษาตัวตนที่สม่ำเสมอและซื่อตรง
scraper มักถูกบล็อกเมื่อตัวตนเปลี่ยนไประหว่าง request หรือเมื่อไม่ตรงกับทราฟฟิกอื่น session เดียวที่มี User-Agent ชัดเจนหนึ่งตัวคือตัวตนที่เสถียรที่สุดและเรียบง่ายที่สุด ตั้งชื่อบอทของคุณ เพิ่มลิงก์สำหรับติดต่อ และส่งเฉพาะ header ที่ client ปกติจะส่ง การเปลี่ยน User-Agent เพื่อให้ดูเหมือนผู้เข้าชมหลายคนเป็นรูปแบบหนึ่งของการหลบเลี่ยง และมักทำให้การบล็อกมีแนวโน้มมากขึ้น ไม่ใช่น้อยลง
หากเว็บไซต์ให้เนื้อหาต่างกันกับเบราว์เซอร์และ HTTP client ธรรมดา ให้ใช้เบราว์เซอร์จริงสำหรับหน้าเหล่านั้น และรักษา rate limit เดิม นั่นเป็นเส้นทางที่ชอบด้วยกฎหมาย และทำให้รูปแบบ request สมเหตุสมผล
ใช้ proxy อย่างระมัดระวัง
proxy เปลี่ยน address ที่ request มาจาก มันเป็นเครื่องมือสำหรับความจำเป็นที่ชอบด้วยกฎหมาย เช่น การทดสอบจากภูมิภาคเฉพาะบนเว็บไซต์ที่คุณได้รับอนุญาตให้ทดสอบ หรือการกระจายภาระไปยังโครงสร้างพื้นฐานของคุณเอง มันไม่ใช่วิธีหนีจากข้อจำกัดที่เว็บไซต์ตั้งไว้กับคุณ รูปแบบของ proxy คือรูปแบบที่ task type ของ proxy ใช้:
proxies = {
"http": "http://user:pass@proxy.example.net:8000",
"https": "http://user:pass@proxy.example.net:8000",
}
resp = session.get("https://example.com/products", proxies=proxies, timeout=30)
การเลือกประเภท proxy เป็นคำถามอีกข้อหนึ่ง ซึ่งอธิบายไว้ใน residential vs datacenter proxies และ rotating proxies สำหรับ scraping
เมื่อการบล็อกกลายเป็น captcha
บางเว็บไซต์ตอบปัญหาอัตราด้วย captcha แทนการบล็อกแบบแข็ง ลำดับที่เหมาะสมคือ หยุด ชะลอ ตรวจกฎอีกครั้ง และจึงพิจารณาการ solve สำหรับ PopularCaptcha widget API ที่ใช้งานได้จริงของ Scarnox คืน token ที่คุณส่งในฟิลด์ h-captcha-response สำหรับ captcha ประเภทอื่น ให้ตรวจรายการที่ใช้งานได้จริง เพราะการรองรับ reCAPTCHA, Cloudflare Turnstile, GeeTest, AWS WAF และ Arkose กำลังจะมาเร็ว ๆ นี้ คู่มือโดยละเอียดคือ web scraping captcha
หากคุณเริ่มเห็นการบล็อกบนเว็บไซต์หนึ่ง สาเหตุเกือบทุกครั้งคือรูปแบบของ request การหลีกเลี่ยง captcha เมื่อ scraping ครอบคลุมนิสัยที่ป้องกันปัญหานี้
Scrape อย่างมีความรับผิดชอบ
- ตรวจ
robots.txtและข้อกำหนดการใช้งานของเว็บไซต์ก่อนเริ่ม และปฏิบัติตามเส้นทางและการหน่วงเวลาที่กำหนด - หยุดเมื่อได้รับ 403 หรือข้อความ "do not scrape" ที่ชัดเจน อย่าลองต่อ
- รักษาอัตรา request ให้ต่ำพอที่ผู้เข้าชมปกติจะไม่สังเกตเห็นทราฟฟิกของคุณ
- อย่าเก็บข้อมูลส่วนบุคคลที่คุณไม่มีเหตุผลต้องเก็บ และจัดการข้อมูลที่เก็บมาภายใต้กฎความเป็นส่วนตัวที่ใช้กับคุณ
- หากคุณต้องการปริมาณมากกว่าที่เว็บไซต์รองรับได้อย่างสบาย ให้ขอ feed หรือ API จากเจ้าของ