วิธีหลีกเลี่ยง captcha ตอน scraping (โดยไม่ละเมิดกฎ)
captcha ส่วนใหญ่ที่เจอระหว่าง scraping เป็นปฏิกิริยาต่อทราฟฟิกที่ดูเหมือนมาจากระบบอัตโนมัติ วิธีที่ถูกที่สุดในการจัดการคือหยุดกระตุ้นให้มันปรากฏ ซึ่งหมายถึงการมองหาแหล่งข้อมูลที่ถูกต้องตามกฎก่อน ตรวจสอบว่ากฎของเว็บอนุญาตให้ทำอะไรได้บ้าง ส่งคำขอให้น้อยลงและช้าลง และไม่ดึงหน้าเดิมซ้ำสองครั้ง การแก้ captcha เป็นทางสำรองสำหรับกรณีที่หลีกเลี่ยงไม่ได้ ไม่ใช่แผนหลัก
ตรวจหา API หรือ feed ทางการก่อน
เว็บจำนวนมากที่ถูก scrape มีวิธีให้ข้อมูลเดียวกันโดยไม่มี captcha อยู่แล้ว ได้แก่ API สาธารณะ การ export ข้อมูล feed แบบ RSS หรือ sitemap หรือโปรแกรมพันธมิตร แหล่งข้อมูลทางการเชื่อถือได้มากกว่า มีโอกาสเปลี่ยนแปลงโดยไม่แจ้งน้อยกว่า และให้เจ้าของเว็บมีส่วนในการกำหนดว่าคุณใช้งานอย่างไร ให้มองหาสิ่งต่อไปนี้
- ส่วนของนักพัฒนาหรือ API ในส่วน footer ของเว็บ
sitemap.xmlสำหรับรายการหน้าเว็บ- ลิงก์ RSS หรือ Atom ใน
<head>ของหน้า - หน้า "data" หรือ "download" สำหรับการ export ข้อมูลจำนวนมาก
หากแหล่งใดแหล่งหนึ่งครอบคลุมความต้องการของคุณ ให้ใช้แหล่งนั้น คุณจะหลีกเลี่ยง captcha ส่วนใหญ่ได้ด้วยการไม่ร้องขอ HTML เลย
เคารพ robots.txt และอัตราที่ไฟล์นั้นกำหนด
robots.txt บอกคุณว่าเส้นทางใดที่ client อัตโนมัติได้รับอนุญาตให้ดึงข้อมูล และบางครั้งยังบอกว่าควรรอนานเท่าใดระหว่างคำขอ ไลบรารีมาตรฐานของ Python อ่านไฟล์นี้ให้คุณได้
import time
from urllib.robotparser import RobotFileParser
import requests
USER_AGENT = "ExampleBot/1.0 (+https://example.com/bot)"
parser = RobotFileParser()
parser.set_url("https://example.com/robots.txt")
parser.read()
delay = parser.crawl_delay(USER_AGENT) or 5 # ใช้ค่าสำรองที่ระมัดระวัง 5 วินาที
urls = [
"https://example.com/products?page=1",
"https://example.com/products?page=2",
]
last_request = 0.0
for url in urls:
if not parser.can_fetch(USER_AGENT, url):
print("skipped by robots.txt:", url)
continue
wait = delay - (time.monotonic() - last_request)
if wait > 0:
time.sleep(wait)
resp = requests.get(url, headers={"User-Agent": USER_AGENT}, timeout=30)
last_request = time.monotonic()
print(url, resp.status_code)
หาก robots.txt ไม่อนุญาตเส้นทางใด คำตอบที่ซื่อตรงคือไม่แตะต้องเส้นทางนั้น หรือถามเจ้าของเว็บ การเลี่ยงด้วยเบราว์เซอร์ไม่ได้เปลี่ยนสิ่งที่เว็บขอไว้
ค่อย ๆ ทำและกระจายคำขอ
อัตราที่คงที่และไม่เร่งรีบมักไม่กระตุ้น captcha ในขณะที่การยิงเป็นชุดมักจะกระตุ้นเสมอ นิสัยไม่กี่อย่างช่วยได้มาก
- เลือกอัตราคำขอหนึ่งค่าต่อเว็บแล้วคงไว้ แทนที่จะรันด้วยความเร็วสูงสุด
- เพิ่ม random jitter เพื่อไม่ให้จังหวะเวลาสม่ำเสมอเกินไป
- หยุดและถอยออกมาสักพักเมื่อเจอ 429 หรือหน้า captcha
- รันงานในช่วงนอกเวลาเร่งด่วนหากโหลดของเว็บเป็นเรื่องที่ต้องใส่ใจ
แคชและอย่าดึงซ้ำ
ทุกคำขอที่คุณไม่ได้ส่ง คือคำขอที่เว็บไม่ต้องจัดการ เก็บหน้าที่ดึงมาพร้อมวันที่และ hash ของเนื้อหา และดึงใหม่เฉพาะเมื่อเนื้อหาน่าจะเปลี่ยนแล้วเท่านั้น คำขอแบบมีเงื่อนไขด้วย header If-Modified-Since หรือ ETag ช่วยให้เซิร์ฟเวอร์ตอบว่า "not modified" ได้อย่างประหยัดเมื่อเซิร์ฟเวอร์รองรับ
ใช้ session ซ้ำและส่ง header ตามปกติ
session ที่เก็บ cookie ระหว่างคำขอทำตัวเหมือนผู้เข้าชมมากกว่าสคริปต์ที่เริ่มใหม่ทุกครั้ง ใช้ requests.Session() สำหรับแต่ละเว็บ และส่ง User-Agent ที่ชัดเจนและซื่อตรง ซึ่งระบุชื่อบอทและวิธีติดต่อ อย่าปลอมตัวเป็นเบราว์เซอร์เพื่อเลี่ยงกฎ หากเว็บต้องใช้ JavaScript เพื่อแสดงเนื้อหา ให้ใช้เครื่องมือเบราว์เซอร์สำหรับหน้าเหล่านั้น และคงขีดจำกัดอัตราเดิมไว้
เมื่อ captcha ยังปรากฏอยู่
บางเว็บจะแสดง captcha ไม่ว่าคุณจะระมัดระวังแค่ไหน ให้ตรวจจับในโค้ดและหยุดงานนั้น แทนการทุบหน้าเว็บซ้ำ การตรวจจับและการแก้ตัวเลือกสำหรับ PopularCaptcha อธิบายไว้ใน captcha ตอน web scraping
วางแผนการ crawl ก่อนเริ่ม
การ crawl ที่ดึงทุกอย่างทุกวันคือวิธีที่ง่ายที่สุดในการกระตุ้น captcha จึงควรวางแผนงานก่อน
- จัดลำดับความสำคัญ ตัดสินใจว่าหน้าไหนเปลี่ยนบ่อยและหน้าไหนแทบไม่เปลี่ยน crawl หน้าที่เปลี่ยนบ่อยบ่อยขึ้น และหน้าอื่นนาน ๆ ครั้ง
- ใช้วันที่ใน sitemap sitemap หลายไฟล์มีค่า
lastmodให้ข้าม URL ที่ไม่มีการเปลี่ยนแปลงตั้งแต่การเยี่ยมครั้งล่าสุด - crawl แบบเพิ่มทีละส่วน เก็บเวลาการดึงที่สำเร็จล่าสุดของแต่ละ URL และเริ่มต่อจากจุดนั้นเมื่อเกิดความล้มเหลว แทนการเริ่มใหม่จากหน้าแรก
- กระจายโหลด แบ่งรายการขนาดใหญ่เป็นชุดเล็ก ๆ และรันกระจายตลอดวัน ไม่ใช่ทั้งหมดพร้อมกัน
แผนแบบนี้ช่วยลดจำนวนคำขอ ซึ่งเป็นปัจจัยที่คุณควบคุมได้มากที่สุด
เขียนแผนไว้เป็นไฟล์ config สั้น ๆ หรือตาราง โดยระบุเว็บ ส่วนที่ดึง ช่วงเวลารีเฟรช และงบคำขอรายวันของแต่ละเว็บ เมื่องบหมดแล้ว งานจะหยุดจนถึงช่วงถัดไป การถือว่างบเป็นขีดจำกัดตายตัว แทนที่จะเป็นแค่แนวทาง คือสิ่งที่ป้องกันไม่ให้ crawler เคลื่อนเข้าสู่รูปแบบทราฟฟิกที่กระตุ้น captcha ตั้งแต่แรก ทบทวนงบทุกสองสามสัปดาห์ เพราะเว็บที่เติบโตอาจมีทราฟฟิกเพิ่มขึ้นด้วย และสิ่งที่เคยสุภาพเมื่อไตรมาสที่แล้วอาจไม่สุภาพแล้วในตอนนี้
การ scrape อย่างรับผิดชอบ
- ตรวจสอบ
robots.txtและข้อกำหนดการใช้งานก่อนเริ่ม และปฏิบัติตามสิ่งที่ระบุไว้ - รักษาอัตราคำขอให้ต่ำ และหยุดเมื่อเว็บส่งสัญญาณว่ากำลังรับภาระไม่ไหว
- อย่าเก็บข้อมูลส่วนบุคคลที่ไม่มีเหตุผลให้ถือไว้ และลบเมื่อไม่ต้องใช้แล้ว
- อย่านำเนื้อหาที่มีลิขสิทธิ์มาเผยแพร่ซ้ำเป็นจำนวนมาก ใช้ข้อมูลเพื่อการวิเคราะห์ การเปรียบเทียบ หรือผลิตภัณฑ์ของคุณเอง และอ้างอิงแหล่งที่มาเมื่อเหมาะสม
- ติดต่อเจ้าของเว็บหากคุณต้องการข้อมูลจำนวนมากขึ้น เขาอาจมี feed ให้