Price monitoring with web scraping: คู่มือปฏิบัติ
Price monitoring คือการตรวจราคาของสินค้าบนชุดเว็บไซต์ตามกำหนดเวลา และบันทึกสิ่งที่เห็นไว้เพื่อเปรียบเทียบในระยะยาว ผู้ค้าปลีก marketplace และนักวิเคราะห์ใช้วิธีนี้กันทั่วไป และการ scrape ราคาก็เป็นหนึ่งในวิธีที่ scraper พบ captcha บ่อยที่สุด ดังนั้นการออกแบบให้ถูกต้องตั้งแต่ต้นจึงสำคัญ คู่มือนี้ครอบคลุมว่าควรติดตามอะไร วิธีแยกตัวเลขจากหน้าเว็บที่ไม่ได้ตั้งใจให้ถูกประมวลผล วิธีจัดเก็บและแจ้งเตือนเมื่อมีการเปลี่ยนแปลง และวิธีอยู่ในกฎของเว็บไซต์ระหว่างที่ทำงาน
เริ่มจากแหล่งข้อมูลที่คุณได้รับอนุญาตให้ใช้
ก่อนเขียนโค้ดใด ๆ ให้ตรวจว่าเว็บไซต์มีช่องทางทางการสำหรับดึงข้อมูลหรือไม่ เช่น product feed, API หรือโปรแกรมพาร์ทเนอร์ ช่องทางเหล่านี้น่าเชื่อถือกว่า scraping และลดความเสี่ยงทางกฎหมายและทางเทคนิคไปได้มาก scraping เป็นทางเลือกสำรองสำหรับหน้าสาธารณะที่ไม่มีช่องทางทางการ และข้อกำหนดการใช้งานกับ robots.txt ยังคงมีผลอยู่ ภาพรวมทางกฎหมาย ครอบคลุมคำถามทั่วไป
สถาปัตยกรรมห้าส่วน
ระบบติดตามที่เชื่อถือได้มีห้าส่วน และการแยกแต่ละส่วนออกจากกันทำให้แก้ไข bug ได้ง่ายขึ้น:
- Scheduler ตัดสินว่าจะเข้าหน้าสินค้าใดและเมื่อไร กระจายการเข้าชมตลอดทั้งวัน แทนที่จะตรวจทุกอย่างในนาทีเดียวกัน
- Fetcher ดาวน์โหลดหน้าเว็บ โดยควบคุมจังหวะอย่างสุภาพ มี retry และแคช
- Parser ดึงราคา บริบทของสกุลเงิน และสถานะสต็อกออกมา
- Store เก็บทุกการสังเกตพร้อม timestamp เพื่อให้มีประวัติ
- Alerter เปรียบเทียบค่าใหม่กับค่าล่าสุด และแจ้งเตือนเมื่อข้ามเกณฑ์ที่คุณตั้งไว้
แยกราคาจากหน้าเว็บที่รกรุงรัง
ราคาปรากฏในหลายรูปแบบ มีตัวคั่นหลักพัน มีจุลภาคเป็นทศนิยม มี label อยู่หน้าตัวเลข หรือกระจายอยู่ในหลาย element ให้ parser มีขนาดเล็กและทดสอบกับตัวอย่างจริง นี่คือเวอร์ชันที่สมมติว่าใช้รูปแบบทั่วไปที่มีจุลภาคเป็นตัวคั่นหลักพันและจุดเป็นทศนิยม ให้ normalize รูปแบบอื่นก่อนเรียกใช้
import re
from decimal import Decimal, InvalidOperation
PRICE_PATTERN = re.compile(r"\d{1,3}(?:,\d{3})*(?:\.\d{1,2})?|\d+(?:\.\d{1,2})?")
def parse_price(text: str) -> Decimal | None:
"""คืนค่าตัวเลขตัวแรกในข้อความเป็น Decimal หรือ None"""
match = PRICE_PATTERN.search(text.replace(" ", " "))
if not match:
return None
try:
return Decimal(match.group(0).replace(",", ""))
except InvalidOperation:
return None
print(parse_price("Now 1,249.50 in stock")) # Decimal('1249.50')
print(parse_price("Sold out")) # None
ใช้ Decimal ไม่ใช่ float สำหรับทุกอย่างที่จะเปรียบเทียบหรือนำมารวม การปัดเศษของ floating-point ทำให้ราคาสองค่าที่เท่ากันดูต่างกันได้ เก็บข้อความดิบไว้ข้างค่าที่แยกได้ เพื่อให้แก้ bug ของ parser ได้ในภายหลังโดยไม่ต้องดึงทุกหน้าใหม่
เก็บประวัติและตรวจจับการเปลี่ยนแปลง
ราคาเพียงค่าเดียวคือภาพถ่ายครั้งเดียว คุณค่าของ monitor คือประวัติ เก็บหนึ่งแถวต่อหนึ่งการสังเกต พร้อม product ID แหล่งที่มา timestamp ค่าที่แยกได้ และข้อความดิบ จากนั้นการแจ้งเตือนก็เป็นเพียงการเปรียบเทียบกับแถวก่อนหน้า แจ้งเตือนเฉพาะการเปลี่ยนแปลงที่มีความหมาย เช่น ราคาลดเกินเปอร์เซ็นต์ที่ตั้งไว้ หรือสินค้าหมดสต็อก เพื่อไม่ให้ได้รับการแจ้งเตือนที่เป็นสัญญาณรบกวนมากเกินไป
จัดการ variant และ bundle
หน้าสินค้าหนึ่งหน้ามักแสดงราคาหลายค่า เช่น ราคาต่อไซส์หรือสี ราคา bundle ราคาสมาชิก หรือราคาที่ปรากฏหลังเลือกตัวเลือก ตัดสินใจก่อนสร้างว่า monitor ควรบันทึกอะไร วิธีที่พบบ่อยคือเก็บ identifier ของ variant ไว้ข้างราคา เพื่อให้การเปลี่ยนแปลงของไซส์หนึ่งไม่ถูกมองเป็นการเปลี่ยนแปลงของทั้งสินค้า ระวังราคาแบบ "เริ่มต้นที่" และราคาเดิมที่ถูกขีดฆ่า เพราะ parser ที่หยิบตัวเลขผิดจะสร้างการแจ้งเตือนที่ผิดพลาด เก็บข้อความ label ไว้ข้างแต่ละค่า เพื่อให้ตรวจได้ว่าอ่านอะไรไปเมื่อการแจ้งเตือนดูผิด
ตั้งเวลาอย่างสุภาพ
ตรวจแต่ละสินค้าในช่วงเวลาที่สอดคล้องกับความถี่ที่ราคาเปลี่ยนจริง สินค้าที่เปลี่ยนรายวันไม่จำเป็นต้องตรวจทุกชั่วโมง เพิ่ม jitter ให้แต่ละการเข้าชม จำกัดจำนวน request ต่อเว็บไซต์ต่อชั่วโมง และแคชผลลัพธ์ตามช่วงเวลาที่เลือก นิสัยเหล่านี้ทำให้ภาระที่คุณสร้างต่ำ และข้อมูลของคุณสม่ำเสมอ
เมื่อหน้าเว็บบล็อกคุณ
หน้าราคาเป็นเป้าหมายการเข้าถึงแบบอัตโนมัติที่พบบ่อย คุณอาจเจอการบล็อก rate limit หรือ captcha ถอยกลับเมื่อเจอ 429 หรือ 503 และหยุดเข้าเว็บไซต์ที่ยังคงปฏิเสธคุณ หากมี captcha ปรากฏบนหน้าที่คุณได้รับอนุญาตให้ automate captcha ประเภทที่ใช้งานได้จริงบน Scarnox คือ PopularCaptcha คู่มือ PopularCaptcha ด้วย Python แสดง flow ของ token อ่าน scrape โดยไม่ถูกบล็อก ก่อนเพิ่มเครื่องมือเข้าไปอีก เพราะการควบคุมจังหวะมักแก้ปัญหาได้มากกว่าเครื่องมือเพิ่มเติมใด ๆ
บางหน้าเรนเดอร์ราคาด้วย JavaScript สำหรับหน้าเหล่านั้น ให้ทำตามแนวทางใน scraping เว็บไซต์ที่ใช้ JavaScript
Scrape อย่างมีความรับผิดชอบ
- ใช้ feed หรือ API ทางการก่อนเสมอ และอ่านข้อกำหนดการใช้งานของทุกเว็บไซต์ที่คุณติดตาม
- เคารพ
robots.txtรักษาอัตรา request ให้ต่ำ และแคชผลลัพธ์ - อย่าติดตามคู่แข่งในลักษณะที่ทำให้บริการของพวกเขาเสื่อมลง
- เก็บข้อมูลที่รวบรวมให้จำกัดเฉพาะสิ่งที่ต้องใช้ และอย่าเก็บข้อมูลส่วนบุคคลที่ปรากฏในหน้าสินค้า
ขั้นตอนถัดไป
- Scrape search results
- Scrape โดยไม่ถูกบล็อก
- Rotating proxy สำหรับ scraping
- Is web scraping legal? ภาพรวมทั่วไป
เริ่มต้นด้วยเครดิตทดลองใช้ฟรี ไม่ต้องใช้บัตรเครดิต: สร้างบัญชี แล้วลอง flow ของ PopularCaptcha บนหน้าที่คุณได้รับอนุญาตให้ automate ดูอัตราค่าบริการปัจจุบันได้ที่ หน้าราคา