ติดตามราคาซูเปอร์มาร์เก็ตด้วย Playwright
(sakisv.net)- ในเดือนธันวาคม 2022 ท่ามกลางเงินเฟ้อสูง ได้สร้างไปป์ไลน์ pricewatcher.gr เพื่อติดตามการเปลี่ยนแปลงราคาของซูเปอร์มาร์เก็ต 3 รายใหญ่ในกรีซทุกวัน
- รายการสินค้าอยู่หลังการเรนเดอร์ด้วย JavaScript และ infinite scroll จึงใช้ Playwright ควบคุมเบราว์เซอร์เพื่อดึงข้อมูลจาก DOM แทน
curlหรือrequests.get() - สภาพแวดล้อมสำหรับรันงานเปลี่ยนจากการใช้แล็ปท็อปเก่าซึ่งช้าเกินไป และ AWS EC2 ซึ่งแพงเกินไป มาเป็นการ สร้างเซิร์ฟเวอร์ Hetzner เฉพาะเมื่อจำเป็น แล้วรันสแครปเปอร์ 3 ตัวแบบขนานก่อนปิดเครื่อง
- สำหรับซูเปอร์มาร์เก็ตที่ Akamai บล็อก IP ที่ไม่ใช่ที่พักอาศัย ใช้ Tailscale exit node เพื่อให้ทราฟฟิกออกผ่าน IP บ้าน และตรวจจับความล้มเหลวด้วยอีเมลแจ้งเตือน การแปลงข้อมูลที่เข้มงวด และฮิวริสติกจำนวนสินค้า
- ลดเวลารันด้วยเซิร์ฟเวอร์ 8vCPU และการบล็อกคำขอรูปภาพ โดยต้นทุนการรัน 31 ครั้งล่าสุดอยู่ที่เซิร์ฟเวอร์ Hetzner €4.94, IPv4 €0.09 และค่าเก็บข้อมูล Cloudflare R2 €0.00
การสแครปเว็บไซต์ซูเปอร์มาร์เก็ตที่ใช้ JavaScript
- ในเดือนธันวาคม 2022 ท่ามกลางสถานการณ์เงินเฟ้อสูง ได้สร้าง pricewatcher.gr เพื่อติดตามการเปลี่ยนแปลงราคาของซูเปอร์มาร์เก็ต 3 รายใหญ่ในกรีซ
- e-shop ของซูเปอร์มาร์เก็ตทั้งสามแห่งใช้ การเรนเดอร์ด้วย JavaScript และบางส่วนโหลดสินค้าเพิ่มเติมเมื่อเลื่อนหน้าจอ คล้าย infinite scroll ของโซเชียลมีเดีย
- ไม่สามารถดึงข้อมูลสินค้าด้วย
curlหรือrequests.get()แบบง่าย ๆ ได้ จึงใช้ Playwright - Playwright ควบคุมเบราว์เซอร์แบบโปรแกรมได้ และจัดการงานต่อไปนี้ผ่าน API
- เปิดแท็บใหม่และไปยัง URL
- ตรวจสอบ DOM
- ดูรายละเอียดขององค์ประกอบ
- ดักจับและตรวจสอบคำขอ
- Playwright รองรับ Chromium, Safari, Firefox และใช้งานได้กับ Node, Java, .NET, Python
- สแครปเปอร์ค้นหาองค์ประกอบ
load moreของ infinite scroll แล้วเลื่อนต่อไปเรื่อย ๆ จากนั้นตัดสินค้าที่มีป้ายหมดออกจากรายการli.product-item - สุดท้ายจะแยกวิเคราะห์ ชื่อสินค้า·ราคา·รูปภาพ·ลิงก์ ฯลฯ จาก `` ของแต่ละสินค้า และทำขั้นตอนเดียวกันซ้ำกับหมวดหมู่สินค้าถัดไป
เลือกสภาพแวดล้อมสำหรับรันทุกวัน
- บน M1 MacBook Pro การประมวลผลซูเปอร์มาร์เก็ตหนึ่งแห่งทั้งหมดใช้เวลา 50 นาทีถึง 2 ชั่วโมง 30 นาที และแม้รันสแครปเปอร์ 3 ตัวแบบขนานก็แทบไม่ต่างกันอย่างเห็นได้ชัด
- แล็ปท็อปเพียงพอสำหรับการพัฒนาและทดสอบ แต่จำเป็นต้องมีสภาพแวดล้อมถาวรสำหรับรันทุกวัน
-
รันด้วยแล็ปท็อปเก่าเพียงเครื่องเดียว
- ความพยายามแรกคือแล็ปท็อปเก่ารุ่นปี 2013
- สเปกคือโปรเซสเซอร์สาย M แบบดูอัลคอร์ 2.20GHz และ RAM 4GB ก่อนเพิ่ม RAM เป็น 12GB ในภายหลัง
- แต่แม้ซูเปอร์มาร์เก็ตที่ “เร็ว” ก็ใช้เวลาประมวลผล มากกว่า 2 ชั่วโมง จึงไม่ถึงประสิทธิภาพที่คาดไว้
-
รันบนคลาวด์
- พิจารณาอินสแตนซ์ EC2 บน AWS ระดับ 4 คอร์·RAM 8GB แต่มีต้นทุนสูงเกินไปสำหรับไซด์โปรเจกต์
- ณ เวลาที่เขียน
c5a.xlargeในeu-north-1มีราคา $0.1640 ต่อชั่วโมง หรือประมาณ $118.08 ต่อเดือน / $1,416.96 ต่อปี - เซิร์ฟเวอร์ระดับเทียบเท่าของ Hetzner คือ
cpx31ราคา $17.22(€15.72) ต่อเดือน หรือ $206.64 ต่อปี ถูกกว่า AWS ประมาณ 7 เท่า - จึงเลือก Hetzner เป็นสภาพแวดล้อมสำหรับรันงานสุดท้าย
ไปป์ไลน์รายวันที่สร้างด้วย Concourse
- แล็ปท็อปเก่าไม่ได้ทำการสแครปเองโดยตรง แต่ทำหน้าที่เป็น เซิร์ฟเวอร์ CI ที่มอบหมายงานให้เซิร์ฟเวอร์ Hetzner
- ใช้ Concourse เป็นเครื่องมือ CI
- Concourse แนะนำตัวเองว่าเป็น “a continuous thing-doer”
- มุ่งสู่บิลด์ที่ทำซ้ำได้ผ่านโมเดลไปป์ไลน์แบบ declarative และการจัดการเวอร์ชันของอินพุต
- ไปป์ไลน์รันทุกคืนตามลำดับต่อไปนี้
- สร้างเซิร์ฟเวอร์สำหรับสแครป
- รันงานสแครปซูเปอร์มาร์เก็ต 3 แห่งแบบขนาน
- หลังงานทั้งหมดเสร็จสิ้น ปิดเซิร์ฟเวอร์เพื่อลดต้นทุน
- ส่งเอาต์พุตดิบของแต่ละสแครปเปอร์ไปยังงานแปลงข้อมูล
- โหลดข้อมูลที่แปลงแล้วเข้าสู่ pricewatcher.gr
- หากขั้นตอนใดล้มเหลว ส่งอีเมลแจ้งเตือน
การเลี่ยงข้อจำกัด IP และ Tailscale exit node
- ซูเปอร์มาร์เก็ตที่ใช้ทดสอบทำงานปกติ แต่ซูเปอร์มาร์เก็ตอีกแห่งอยู่หลัง Akamai และเปิดกฎไฟร์วอลล์ที่บล็อกคำขอจาก IP ที่ไม่ใช่ที่พักอาศัย
- โครงสร้างที่ต้องการกลับด้านกับ VPN ทั่วไป คือทำให้ดูเหมือนว่าคำขอออกจาก IP บ้านจริง
- ใช้ Tailscale เชื่อมอุปกรณ์หลายเครื่องให้เหมือนอยู่ในเครือข่ายเดียวกัน
- เมื่อกำหนดให้อุปกรณ์หนึ่งเป็น exit node ใน Tailscale จะตั้งค่าให้คำขอจากอุปกรณ์อื่นออกผ่านโหนดนั้นได้
- แล็ปท็อปเก่าจึงทำหน้าที่เป็น exit node สำหรับทราฟฟิกสแครปด้วย
- การที่ ISP ที่ใช้อยู่ใช้ CGNAT ทำให้ IP สาธารณะไม่ได้ผูกกับบุคคลใดบุคคลหนึ่งเท่านั้น แต่ถูกแชร์กับลูกค้ารายอื่นของ ISP จึงยังเป็นตัวแปรอยู่
ประเภทความล้มเหลวและวิธีตรวจจับ
- การตั้งค่านี้ใช้งานมา 1 ปีครึ่ง และโดยรวมทำงานได้อย่างน่าเชื่อถือ
- โปรเจกต์สแครปย่อมได้รับผลกระทบจากการเปลี่ยนแปลงของผู้พัฒนาเว็บไซต์เป้าหมาย
- ความล้มเหลวแบ่งได้กว้าง ๆ เป็นสองประเภท
-
การเปลี่ยนแปลงที่ทำให้พัง
- คือกรณีที่การเปลี่ยนแปลงของเว็บไซต์ทำให้สแครปเปอร์ล้มเหลวทันที
- ตัวอย่างเช่น
- มีการเพิ่มแบบสำรวจ จึงต้องกดปุ่มเพิ่มอีกครั้ง
- เลย์เอาต์เปลี่ยนไปทั้งหมด จนต้องรีแฟกเตอร์สแครปเปอร์ครั้งใหญ่
-
การเปลี่ยนแปลงที่ไม่ทำให้พัง
- กรณีที่สแครปเปอร์ยังรันได้ตามปกติ แต่การตีความข้อมูลผิดเพี้ยนไปนั้นจัดการยากกว่า
- เช่น หากรูปแบบการแสดงราคาถูกเปลี่ยนให้แยกส่วนทศนิยมด้วย `` มันฝรั่งทอดราคา €1.99 อาจถูกแยกวิเคราะห์เป็น €199
- เพื่อจับการเปลี่ยนแปลงแบบนี้ จึงตั้งค่าขั้นตอนแปลงข้อมูลให้ตรวจสอบอินพุตอย่างเข้มงวดที่สุดเท่าที่ทำได้
- เนื่องจากรันทุกวัน จึงยังมีเวลาตรวจสอบปัญหา แต่ถ้าพังระหว่างพักร้อนก็อาจเป็นปัจจัยที่น่ากังวล
การปรับเวลาในการรันและเสถียรภาพให้เหมาะสม
- สถาปัตยกรรมโดยรวมแทบคงเดิมตั้งแต่แรก แต่มีการปรับหลายส่วนเพื่อเพิ่มความน่าเชื่อถือและลดงานที่ต้องทำด้วยมือ
- การปรับปรุงที่นำมาใช้ประกอบด้วย
- อีเมลแจ้งเตือนเมื่อเกิดความล้มเหลว
- ฮิวริสติกที่ส่งการแจ้งเตือนเมื่อจำนวนสินค้าของซูเปอร์มาร์เก็ตบางแห่งมากหรือน้อยเกินไป
- timeout
- retry ที่ไม่เริ่มใหม่ตั้งแต่ต้น
- คอขวดที่ใหญ่ที่สุดคือ เวลาในการรันสแครป
- ยิ่งใช้เวลานาน ต้นทุนก็ยิ่งเพิ่ม
- เมื่อเกิดความล้มเหลวแล้วต้องลองใหม่ตั้งแต่ต้น ความไม่สะดวกก็ยิ่งมากขึ้น
-
ใช้เซิร์ฟเวอร์ที่ใหญ่ขึ้น
- เปลี่ยนเซิร์ฟเวอร์จาก 4vCPU·16GB RAM เป็น 8vCPU·16GB RAM
- เวลารันลดลงประมาณ 20% และได้ประสิทธิภาพใกล้เคียงกับที่ได้จาก MBP
- เนื่องจากใช้เซิร์ฟเวอร์สแครปเพียงประมาณ 2 ชั่วโมง ส่วนต่างราคาจึงถือว่าเล็กน้อยมาก
-
ดึงข้อมูลให้น้อยลง
- ใช้
page.routeของ Playwright เพื่อบล็อกคำขอรูปภาพ - จัดการคำขอ
.png,.jpgด้วยการ abort เพื่อไม่ดึงรูปภาพระหว่างโหลดสินค้า - วิธีนี้ทำให้การสแครปเร็วขึ้น และยังช่วยลดแบนด์วิดท์กับต้นทุนของเว็บไซต์เป้าหมายได้เล็กน้อย
- ใช้
ต้นทุนสำหรับการรัน 31 ครั้ง
- ค่าใช้จ่ายตามใบแจ้งหนี้ Hetzner ล่าสุดมีดังนี้
- เซิร์ฟเวอร์ที่สร้าง 31 เครื่อง: €4.94
- ที่อยู่ IPv4 31 รายการที่เซิร์ฟเวอร์เหล่านั้นได้รับ: €0.09
- ข้อมูลสแครปถูกเก็บไว้ใน Cloudflare R2
- เนื่องจากยังไม่เกิน free tier 10GB ของ Cloudflare R2 ค่าเก็บข้อมูลจึงเป็น €0.00
- ไปป์ไลน์ทั้งหมดทำงานโดยผสาน Playwright, Hetzner, Concourse, Tailscale และ Cloudflare R2 เพื่อติดตามการเปลี่ยนแปลงราคาซูเปอร์มาร์เก็ตทุกวัน
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ตั้งแต่ต้นปีนี้ก็ทำอะไรคล้าย ๆ กันสำหรับ New Zealand อยู่ ใช้ Playwright/Typescript ดึงข้อมูลแล้วเก็บเป็นไฟล์ Parquet ลงบน cloud storage แต่ยังไม่ได้เอามาแสดงบนหน้าจอ
งานส่วนใหญ่หมดไปกับการหลบเลี่ยง บริการ reverse proxy อย่าง Akamai และ Cloudflare ตอนเริ่มทำคิดว่าไม่มีใครทำ แต่ตอนนี้รู้แล้วว่าใน NZ มีสตาร์ตอัปอย่างน้อย 3 แห่งที่ทำเรื่องเดียวกัน ดูเหมือนว่าเงินเฟ้อจะกระตุ้นนวัตกรรมที่นี่พอสมควร
รูปแบบก็เป็นไปตามคาด ซูเปอร์มาร์เก็ตใช้วิธีเดิม ๆ ในการทำให้ราคาซับซ้อนที่สุดเท่าที่จะทำได้ และใช้การขึ้นลงราคาแบบ ‘ฟันเลื่อย’ เพื่อแยกคนที่ไม่มีเวลาออกจากคนที่ไม่มีเงิน พวกเขายังมักแบ่งลูกค้าที่ภักดีต่อแบรนด์ออกจากลูกค้าที่อ่อนไหวต่อราคา เช่น ถ้ามีแบรนด์ช็อกโกแลตยอดนิยม 3 แบรนด์ ในแต่ละสัปดาห์ก็จะมีแค่หนึ่งแบรนด์ที่ขายในราคาสมเหตุสมผล
ตรงที่ว่า “แบ่งลูกค้าที่ภักดีต่อแบรนด์ออกจากลูกค้าที่อ่อนไหวต่อราคา ถ้ามีแบรนด์ช็อกโกแลตยอดนิยม 3 แบรนด์ ในแต่ละสัปดาห์ก็จะมีแค่หนึ่งแบรนด์ที่ขายในราคาสมเหตุสมผล” นี่น่าสนใจเป็นพิเศษ
ใน AU มี scraper แบบนี้เกิดขึ้นแล้วก็หายไปเยอะ แต่โดยปกติซูเปอร์มาร์เก็ตรายใหญ่จะบล็อกมัน วนซ้ำระหว่างความรู้สึกว่าใช้งานได้จริงกับ “ทำไมไม่มีสิ่งนี้นะ?” ทั้งที่จริง ๆ มันเคยมีมาแล้วหลายครั้ง
ใช้เวลาไม่ถึง 20 ชั่วโมงในการทำ crawler และ infrastructure ที่รองรับมัน
แถมยังมี marketplace แค่เจ้าเดียวที่มีราคาจากหลายร้านทั้งหมดอยู่ด้วย เลยยิ่งมีประโยชน์
บทความดีมาก ผมเจอปัญหาคล้ายกันในเว็บไซต์เปรียบเทียบราคาคอนแทคเลนส์ที่ทำอยู่ https://lenspricer.com/ และตอนนี้เปิดให้บริการในราว 30 ประเทศ เข้าใจดีเลยว่าการที่เว็บไซต์เปลี่ยน HTML เป็นเรื่องน่าปวดหัวแค่ไหน
อุปสรรคใหญ่ช่วงแรกอย่างหนึ่งคือการ จับคู่สินค้าเดียวกัน ข้ามเว็บไซต์มากกว่า 100 แห่ง แม้จะคิดว่าชื่อสินค้าน่าจะเป็นเอกลักษณ์ แต่ทุกเจ้าก็ชอบเขียนดัดแปลงในแบบของตัวเอง ส่วนใหญ่จัดการได้ด้วย regex แต่ก็มีจำนวนไม่น้อยที่ต้องแมปด้วยมือ และบางส่วนใช้ AI แต่ก็ตรวจสอบเองทั้งหมด
การสร้าง scraper และ infrastructure นั้นค่อนข้างง่ายกว่า สิ่งที่ยากคือการดูแล scraper ทั้งหมด และเวลาสินค้าหายไปจากเว็บไซต์ ต้องแยกให้ออกว่าเป็นความผิดพลาดของ scraper ถูกบล็อก เว็บไซต์เปลี่ยน หรือแค่เว็บไซต์ปิดปรับปรุงตอนที่ crawl อยู่
เป็นโปรเจกต์ที่สนุก แต่บางครั้งก็ยาก และมีปัญหาจุกจิกที่น่ารำคาญเวลาแก้
ราคาก็หลากหลายมาก ส่วนความคุ้มครองก็มักเป็นแนวคืนเงินทางไปรษณีย์ราว 30%
จำนวนร้านก็ดูน้อยมากด้วย บางทีทุกลิงก์อาจเป็นลิงก์ผู้สนับสนุนทั้งหมดก็ได้ ใน idealo.de ผมยังเจอราคาที่ต่ำกว่านี้
Costco ขึ้นชื่อเรื่องนี้มาก สินค้าอิเล็กทรอนิกส์เกือบทั้งหมดที่ขายในร้านและสินค้าอื่นอีกมากมี SKU แบบสั่งทำพิเศษ และบ่อยครั้งตัวสินค้าก็มีสเปกต่างกันนิดหน่อยด้วย
ผมสร้างเว็บไซต์คล้ายกันในเมืองของตัวเองและได้รับความสนใจพอสมควร ดึงข้อมูลทั้งจากแอปและเว็บไซต์ แล้วรันบนเซิร์ฟเวอร์เดี่ยว RAM 2GB ของ Linode พร้อม IPv4 5 ตัวและ IPv6 ฟรี 1000 ตัว
สินค้าทั้งหมดถูกเก็บข้อมูลทุก ๆ ไม่เกิน 40 นาที โดยเฉลี่ยราว 25 นาที ใช้ curl-impersonate และพยายามดึง JSON ให้ได้มากที่สุด 90% ของตลาดส่งราคาผ่าน Ajax call และอีก 10% ที่เหลือก็ parse HTML ได้ง่ายด้วย regex
ดูได้ที่ https://www.economizafloripa.com.br
https://www.economizafloripa.com.br/?q=parceria-comercial
พอเห็นหน้านั้นแล้ว โปรเจกต์นี้ก็ดูเปลี่ยนจาก “เครื่องมือที่มีประโยชน์สำหรับคนที่อยากทวงคืนการควบคุมจากบริษัทที่ขายสินค้าจำเป็นต่อการดำรงชีวิต” ไปเป็น “อีกหนึ่งความพยายามหาเงิน” แน่นอนว่านั่นเป็นสิทธิของคุณ แต่ตอนอ่านหน้าแรกผมคาดหวังแรงจูงใจที่มีจริยธรรมกว่านี้
เป็นบทความที่ดีมาก
ผมคิดว่าทางที่ดีที่สุดคือแยกกระบวนการ scraping กับ parsing ออกจากกันเป็นคนละโปรเซส ถ้าเก็บ JSON หรือ HTML ต้นฉบับไว้ ก็ย้อนกลับมาแก้ parser แล้วรันใหม่ได้ทุกเมื่อ
ผมเคยทำระบบและเว็บไซต์คล้าย ๆ กันสำหรับเนเธอร์แลนด์เป็นส่วนหนึ่งของโปรเจ็กต์ปริญญาโท: https://www.superprijsvergelijker.nl/
งาน scraping ส่วนใหญ่ในโปรเจ็กต์ของผมใช้การส่ง HTTP request แบบตรง ๆ ไปยัง JSON API บางเว็บไซต์ใช้ Playwright instance เพื่อเอา session cookie ที่ยังใช้ได้ และหลบระบบกันบอทกับ CAPTCHA ส่วน crawler/scraper, parser และ API ที่เหลือทำด้วย Haskell แล้วรันบน AWS ECS เว็บไซต์ใช้ NextJS
โจทย์หลักที่ผมยังพยายามแก้อยู่คือการจับคู่สินค้าจากซูเปอร์มาร์เก็ตต่าง ๆ เพื่อแสดงราคาไว้ในหน้าจอเดียว ตัวอย่างอยู่ที่นี่: https://www.superprijsvergelijker.nl/supermarkt-aanbieding/6...
ถ้ามีการให้หมายเลขบาร์โค้ดที่ถูกต้องมาอย่างน้อยหนึ่งรายการ ส่วนใหญ่ก็ทำงานได้ดี
ผมคิดว่าซูเปอร์มาร์เก็ตรายใหญ่สองเจ้าของ Australia แค่ใช้ อัลกอริทึม AI วิเคราะห์ราคา ทั้งสองฝั่ง ก็สามารถสร้างโครงสร้างแบบ duopoly ที่ตั้งราคาเชิงต่อต้านการแข่งขันได้แล้ว อัลกอริทึมสุดท้ายมีแนวโน้มจะไปในทางร่วมมือกันเพื่อเพิ่มกำไรสูงสุด
ทำแบบถูกกฎหมายก็ได้ด้วยแค่ข้อมูลราคาที่หาได้สาธารณะ และถ้าแชร์ต้นทุนซัพพลายหรือข้อมูลกำไรต่อสินค้า ก็ทำแบบผิดกฎหมายได้ด้วย ผลลัพธ์ก็น่าจะคล้ายกัน
AI ที่ฝึกมาแล้วสองตัวจะหาวิธีเพิ่มกำไรสูงสุดด้วย regression analysis หลายมิติ หรืออาจจะไฮเปอร์หลายมิติ ในรูปแบบประหลาด ๆ และสุดท้ายผู้บริโภคก็จะเป็นคนแบกรับกำไรสูงสุดของผู้เล่นที่ดูเหมือนจะแข่งขันกันอยู่ ถ้าเข้าถึงข้อมูลราคาแบบนี้ได้ การรันแมชชีนเลิร์นนิงสองชุดที่โฟกัสกับตลาดแบบ duopoly ก็แทบไม่ต้องใช้อะไรมาก
ตรรกะของพวกเขาคือ ถ้าราคาทั้งหมดเปิดเผยต่อสาธารณะ ผู้บริโภคกลับจะต้องจ่ายแพงขึ้น เพราะซูเปอร์มาร์เก็ตจะปรับราคาเข้าหาจุดที่ทุกฝ่ายได้กำไรสูงสุดร่วมกัน
ซูเปอร์มาร์เก็ตที่นี่จ้าง “นักล่าราคา” มาหลายปีแล้ว คนพวกนี้จะไปยังร้านคู่แข่งแล้วจดราคาสินค้าทุกชิ้น
ใน Norway คุณจะเห็นได้บ่อยว่าถ้าซูเปอร์มาร์เก็ต A ลดราคาสินค้าบางอย่างในสัปดาห์หนึ่ง ซูเปอร์มาร์เก็ต B ก็จะออกโปรโมชันคล้ายกันในสัปดาห์ถัดไปหรืออีกสัปดาห์เพื่อดึงลูกค้า
น่าจะเพิ่มการตรวจสอบอัตโนมัติเพื่อจับการเปลี่ยนแปลงแบบนี้ได้ เช่น ถ้า การตรวจสอบความสมเหตุสมผล ไม่ผ่าน ก็ไม่ต้องซิงก์การเปลี่ยนแปลงของราคา/สินค้า
อาจตั้งเกณฑ์ไว้ได้ว่าราคาแต่ละรายการห้ามเปลี่ยนเกิน 100% และจำนวนสินค้าที่ active อยู่ห้ามเปลี่ยนเกิน 20%
ผมเลยใช้ heuristic แบบนี้เพื่อตรวจว่าวันนี้ scraping สำเร็จหรือไม่แทน เช่นเช็กว่าจำนวนสินค้าที่ดึงมาได้วันนี้อยู่ในช่วงประมาณ 10% ของค่าเฉลี่ย 7 วันล่าสุดหรือเปล่า
สิ่งที่ยากไม่ใช่ตัว scraping เอง แต่คือการ หลบระบบป้องกันการบล็อก ที่ซับซ้อนขึ้นเรื่อย ๆ
ต้องหมุน residential proxy ตลอด ต้องใช้ตัวที่คะแนนดี และต้องไม่เผยแพทเทิร์นการ scraping ข้อมูลออกมา บางซูเปอร์มาร์เก็ตไม่แสดง network request ใน network tab ทำให้ใช้วิธีดึงเฉพาะ API response ไม่ได้
ถึงจะพยายามทำ man-in-the-middle กับ mobile app เพื่อดู network request และข้อมูล ก็ยังโดนบล็อกถ้าปลอมตัวไม่เนียนพอ
ผมเคยลองแล้ว แต่สรุปว่าไม่คุ้มเพราะต้นทุนกับงานพัฒนาที่ต้องทำต่อเนื่อง จริง ๆ แล้วบริการเปรียบเทียบราคาซูเปอร์มาร์เก็ตบางเจ้าก็ใช้แรงงานค่าแรงต่ำมานั่งดึงข้อมูลกันตรง ๆ
นี่เป็นแค่ side project ถ้ามันเริ่มกินเวลาบ่อยเกินไป ผมก็คงหยุดแล้วเปิดซอร์สโค้ดกับข้อมูลทั้งหมดแทน
แต่ก็สงสัยว่า network request ที่ไม่โผล่ใน network tab นี่ทำได้ยังไง
สำหรับผม ส่วนที่ยากที่สุดคือการจับคู่และเปรียบเทียบสินค้าระหว่างซูเปอร์มาร์เก็ตต่าง ๆ
ถ้ามี ความโปร่งใสด้านราคา ของสินค้า ก็น่าจะดีมาก จะได้ติดตามเรื่องแบบนี้ได้ง่ายขึ้นมากทั้งตามร้านและตามพื้นที่
เช่นเปรียบเทียบราคา oat milk ซึ่งเป็นนมทางเลือก ตามรหัสไปรษณีย์และตามร้านขายของชำได้ หรือจะติดตาม “shrinkflation” ที่ราคาเท่าเดิมแต่ปริมาณลดลงก็ได้
ในแง่นั้นก็ดูเหมือนกำลังติดตามราคาอยู่แล้ว เลยสงสัยว่ามีการเช็กต้นทุนต่อกรัมหรือต่อออนซ์ด้วยไหม เพราะผู้ผลิตหรือร้านค้าอาจคงราคาเดิมแต่ให้ปริมาณน้อยลง และผมสงสัยว่าเครื่องมือนี้จะจับเรื่องนั้นได้หรือเปล่า
แต่ก็เป็นฟีเจอร์ที่เพิ่มได้ไม่ยาก และถ้ามี shrinkflation เกิดขึ้น ก็สามารถแสดงช่วงเวลาที่มันเกิดได้
ในตลาดสวีเดน มีการทำเรื่องนี้มานานกว่า 8 ปีแล้ว มีเว็บไซต์ชื่อ https://www.matspar.se/ ที่ลูกค้าสามารถดูสินค้าทั้งหมดจากร้านค้าออนไลน์หลัก ๆ เปรียบเทียบราคา แล้วใส่สินค้าที่ต้องการลงในตะกร้าได้
ตอนท้ายยังสามารถเปรียบเทียบยอดรวมของตะกร้าที่รวมค่าจัดส่งแล้ว และส่งออกตะกร้าไปยังร้านที่ต้องการเพื่อสั่งซื้อได้
เขาเป็นผู้ร่วมก่อตั้งและปัจจุบันเป็น CTO จึงทำงานด้านการสแครปและการบำรุงรักษามาอย่างมากตลอดช่วงที่ผ่านมา ตอนนี้สแครปราคา มากกว่า 30 ล้านรายการต่อวัน
จากข้อมูลสาธารณะ บริษัทมีรายได้ราว 400,000 ดอลลาร์ และมีพนักงาน 6 คน: https://www.allabolag.se/5590076351/matspar-i-sverige-ab
ตอนที่ย้ายไปอยู่พื้นที่ใหม่ ฉันเคยติดตามราคาอยู่ แต่ตอนนี้รู้สึกว่าการไปซื้อจากตลาดหรือร้านใหญ่ 2 แห่งที่คงราคาต่ำไว้เสมอนั้นง่ายกว่ามาก
ถ้าเป็น Europe ก็น่าจะเป็น Aldi/Lidl
ถ้าเป็นสหรัฐฯ ก็อาจเป็น Costco/Trader Joe's
ออนไลน์ก็มี CamelCamelCamel/Amazon สำหรับสินค้าไม่ใช่อาหาร แต่เป็นหมวดสุขภาพ/ความงาม/อิเล็กทรอนิกส์บางส่วน
ถ้าซื้อจากผู้ผลิตโดยตรงได้ บางครั้งก็ดีกว่าเสียอีก เช่น ฉันเคยซื้อสบู่ยี่ห้อหนึ่งที่ชอบแบบยกล็อตจากเว็บขายส่ง แล้วได้ราคาต่ำกว่าราคาขายปลีกไม่ถึงครึ่ง ส่วนแชมพูก็ซื้อโดยตรงแบบแกลลอนถูกกว่าร้านค้าปลีกไหน ๆ มาก
Trader Joe's คุณภาพสูงกว่า แต่โดยทั่วไปก็แพงกว่า