ทำ Market Research แบบอัตโนมัติ: ดึงข้อมูล Shopify ด้วย Python

อัปเดตล่าสุดเมื่อ April 16, 2026

ปลายทาง /products.json ของ Shopify นี่แหละถือเป็นหนึ่งใน “ความลับที่ไม่ค่อยลับ” ที่สุดในวงการข้อมูลอีคอมเมิร์ซ แค่เติมท้าย URL ของร้าน Shopify เข้าไป ก็จะได้ JSON ที่มีโครงสร้างพร้อมใช้งานกลับมาเลย—ไม่ต้องมี API key, ไม่ต้องยืนยันตัวตน, ไม่ต้องมานั่งแกะ HTML ที่ซ้อนกันเป็นชั้น ๆ ให้ปวดหัว

ผมทำงานอยู่กับทีม เลยคลุกกับเรื่องการดึงข้อมูลจากเว็บพอสมควร และการ scrape Shopify ก็เป็นหัวข้อที่ถูกถามเข้ามาตลอด—ทั้งจากทีมขายที่ต้องตามดูราคาคู่แข่ง คนทำอีคอมเมิร์ซที่ต้องเทียบแค็ตตาล็อกสินค้า ไปจนถึงทีมจัดซื้อที่กำลังมองหาซัพพลายเออร์รายใหม่ ๆ ด้วย บน Shopify และส่วนแบ่งราว ปริมาณข้อมูลสินค้าที่ดึงออกมาได้จึงมหาศาลมาก

คู่มือนี้จะพาไล่ตั้งแต่ต้นจนจบ: endpoint นี้คืนค่าอะไรบ้าง, จะไล่ pagination ยังไงให้ดึงสินค้าได้เป็นพันรายการ, จะรับมือ rate limit โดยไม่โดนบล็อกยังไง, และจะทำให้ JSON ที่ซ้อนกันของ Shopify กลายเป็น CSV หรือไฟล์ Excel ที่อ่านง่ายด้วย pandas ได้อย่างไร ผมยังจะพูดถึง endpoint อื่นที่คนไม่ค่อยพูดถึง (/collections.json, /meta.json) และแถมทางเลือกแบบ no-code สำหรับคนที่ไม่อยากแตะ Python เลยด้วย

/products.json ของ Shopify คืออะไร และทำไมถึงดึงข้อมูลได้ง่าย

ร้าน Shopify ทุกแห่งจะมี endpoint สาธารณะที่ {store-url}/products.json ซึ่งคืนข้อมูลสินค้าที่เป็นโครงสร้างชัดเจนมาให้ ไม่ต้องใช้ API key ไม่ต้องใช้ OAuth ไม่ต้องล็อกอินใด ๆ แค่เติม /products.json ต่อท้าย URL ของร้าน ก็จะได้ JSON array ของสินค้าทั้งหมดในแค็ตตาล็อกกลับมา

ลองเปิดดูได้เลยตอนนี้: เข้าไปที่ หรือ ในเบราว์เซอร์ คุณจะเห็น JSON ที่สะอาดและเป็นระเบียบ มีทั้งชื่อสินค้า ราคา ตัวเลือกสินค้า รูปภาพ แท็ก และข้อมูลอื่น ๆ ครบ

ถ้าเทียบกับวิธีอื่น เช่น การไล่ parse HTML ของธีม Shopify ซึ่งมักซ้อนลึก ไม่เหมือนกันในแต่ละร้าน และเปลี่ยนไปทุกครั้งที่เจ้าของร้านอัปเดตธีม จะเห็นได้ชัดว่ามันยุ่งกว่ามาก ตัวอย่างเช่น:

แนวทาง HTML (ชวนปวดหัว):

1<div class="product-card__info">
2  <h3 class="product-card__title">
3    <a href="/products/classic-blue-jeans">Classic Blue Jeans</a>
4  </h3>
5  <span class="price price--on-sale" data-product-price>$149.00</span>
6</div>

แนวทาง JSON (อ่านง่าย):

1{
2  "title": "Classic Blue Jeans",
3  "handle": "classic-blue-jeans",
4  "vendor": "Hiut Denim",
5  "variants": [{"price": "149.00", "sku": "HD-BLU-32", "available": true}]
6}

JSON ชนะทั้งเรื่องความสม่ำเสมอ ความเสถียร และความง่ายในการ parse นอกจากนี้ endpoint นี้ยังรองรับ query parameter สำคัญ 2 ตัวคือ ?limit= (สูงสุด 250 สินค้าต่อหน้า ค่าเริ่มต้นคือ 30) และ ?page= สำหรับ pagination ซึ่งเราจะใช้กันเยอะมากในโค้ดด้านล่าง

สิ่งที่ต้องแยกให้ออก: นี่คือ public storefront endpoint ไม่ใช่ โดย Admin API ต้องใช้ access token ของเจ้าของร้าน และให้ข้อมูลเช่นออเดอร์ ระดับสต็อก และข้อมูลลูกค้า ส่วน /products.json แบบสาธารณะจะให้เฉพาะข้อมูลสินค้าที่อ่านได้อย่างเดียว ใคร ๆ ก็เข้าถึงได้ เดี๋ยวผมจะอธิบายความต่างนี้ให้ชัดขึ้นอีกครั้งด้านล่าง เพราะมีคนสับสนเรื่องนี้บ่อยมาก

ข้อควรระวัง: ไม่ใช่ทุกร้าน Shopify จะเปิด endpoint นี้ไว้ จากที่ผมทดสอบ ประมาณ 71% ของร้านจะคืน JSON ที่ใช้งานได้ (เช่น allbirds.com, gymshark.com, colourpop.com, kyliecosmetics.com ใช้ได้หมด) แต่บางร้านที่ตั้งค่าเองอาจได้ 404 (เช่น hiutdenim.co.uk, bombas.com) วิธีเช็กเร็ว ๆ คือเข้า {store-url}/products.json ในเบราว์เซอร์แล้วดูผลลัพธ์

ทำไมต้อง scrape Shopify ด้วย Python? ตัวอย่างการใช้งานทางธุรกิจ

แล้วทำไปเพื่ออะไร? คำตอบคือ ROI นั่นเอง ใช้ automated price scraping เพื่อทำ competitive intelligence แล้ว จากเดิมมีแค่ 34% ในปี 2020 และงานวิจัยยังพบว่า ข้อมูลพวกนี้มีมูลค่าจริง ๆ

กรณีใช้งานที่พบบ่อยที่ผมเห็นมีดังนี้:

This paragraph contains content that cannot be parsed and has been skipped.

Python เหมาะกับงานนี้ที่สุด ใช้ Python เป็นภาษาหลักอยู่แล้ว และ ecosystem อย่าง requests สำหรับ HTTP, pandas สำหรับจัดการข้อมูล, httpx สำหรับ async ทำให้เปลี่ยนจาก "มีแค่ URL" ไปเป็น "มีสเปรดชีตพร้อมใช้" ได้ในโค้ดไม่ถึง 80 บรรทัด

อ้างอิงฟิลด์ products.json แบบครบถ้วน: มีอะไรให้ดึงบ้าง

บทความสอน scrape ส่วนใหญ่จะโชว์แค่ title, id, กับ handle แล้วก็จบ แต่ JSON response ของ Shopify จริง ๆ มีฟิลด์มากกว่า 40 รายการ ครอบคลุมทั้ง product, variant, image และ options การรู้ว่ามีอะไรให้ใช้บ้างก่อนเริ่มเขียนโค้ด จะช่วยให้ไม่ต้องกลับมาดึงข้อมูลใหม่ทีหลัง

อ้างอิงนี้ผมรวบรวมจาก response จริงของ /products.json ที่ดึงเมื่อวันที่ 16 เมษายน 2026 โครงสร้างจะเหมือนกันในทุก store ที่เปิด endpoint นี้ไว้

ฟิลด์ระดับสินค้า

ฟิลด์ชนิดข้อมูลตัวอย่างค่าการใช้งานทางธุรกิจ
idInteger123456789รหัสสินค้าที่ไม่ซ้ำ ใช้ deduplicate
titleString"Classic Blue Jeans"ชื่อสินค้าสำหรับแค็ตตาล็อกและการเปรียบเทียบ
handleString"classic-blue-jeans"slug ของ URL—ใช้สร้างลิงก์สินค้าเป็น {store}/products/{handle}
body_htmlString (HTML) หรือ null

Our best-selling...

คำอธิบายสินค้า ใช้วิเคราะห์คอนเทนต์และ SEO
vendorString"Hiut Denim"ชื่อแบรนด์/ซัพพลายเออร์ ใช้ทำ lead gen หรือ sourcing
product_typeString"Jeans"การจัดหมวดหมู่สินค้าเพื่อวิเคราะห์ตลาด
created_atISO DateTime"2024-01-15T10:30:00-05:00"ใช้ดูเวลาที่สินค้าเพิ่มเข้าแค็ตตาล็อก (จับสินค้าใหม่)
updated_atISO DateTime"2025-03-01T08:00:00-05:00"ตรวจจับการเปลี่ยนแปลงล่าสุดในแค็ตตาล็อก
published_atISO DateTime"2024-01-16T00:00:00-05:00"บอกว่าสินค้าถูกเปิดเผยบน storefront เมื่อไร
tagsArray of Strings["organic", "women", "straight-leg"]วิเคราะห์คีย์เวิร์ด/แท็กเพื่อ SEO การจัดหมวดหมู่ และเทรนด์
variantsArray of Objects(ดูฟิลด์ variant ด้านล่าง)ราคา SKU และความพร้อมขายของแต่ละ variant
imagesArray of Objects(ดูฟิลด์ image ด้านล่าง)URL รูปสินค้า ใช้ทำแค็ตตาล็อกและวิเคราะห์เชิงภาพ
optionsArray of Objects[{"name": "Size", "values": ["S","M","L"]}]ทำความเข้าใจโครงสร้างตัวเลือกสินค้า (ไซซ์ สี วัสดุ)

ฟิลด์ระดับ Variant (ซ้อนอยู่ใต้สินค้าแต่ละชิ้น)

ฟิลด์ชนิดข้อมูลตัวอย่างการใช้งาน
idInteger987654321รหัส variant ที่ไม่ซ้ำ
titleString"32 / Blue"ชื่อที่แสดงของ variant
skuString"HD-BLU-32"ใช้จับคู่ SKU กับระบบสต็อก
priceString"185.00"ใช้ติดตามราคา (หมายเหตุ: เป็น string ต้องแปลงเป็น float ก่อนคำนวณ)
compare_at_priceString หรือ null"200.00"ราคาตั้งต้น—สำคัญมากสำหรับการติดตามส่วนลด
availableBooleantrueสถานะพร้อมขาย (ตัวบอกสต็อกที่เปิดให้ดูได้)
weightFloat1.2ใช้วิเคราะห์การขนส่ง/โลจิสติกส์
option1, option2, option3String"32", "Blue", nullค่าของตัวเลือกแต่ละตัว
created_at, updated_atISO DateTimeใช้ติดตามการเปลี่ยนแปลงระดับ variant

ฟิลด์ระดับ Image

ฟิลด์ชนิดข้อมูลตัวอย่างการใช้งาน
idInteger111222333รหัสรูปภาพที่ไม่ซ้ำ
srcString (URL)"https://cdn.shopify.com/..."ลิงก์ดาวน์โหลดรูปโดยตรง
altString หรือ null"Front view of jeans"alt text ของรูป ใช้วิเคราะห์ accessibility
positionInteger1ลำดับของรูป
width, heightInteger2048, 2048ขนาดของรูปภาพ

อะไรที่ไม่มีใน Public Endpoint

มีจุดที่ต้องระวังมากคือ inventory_quantity ไม่มีให้ใน response ของ /products.json แบบสาธารณะ ฟิลด์นี้ถูกเอาออกจาก JSON ที่เปิดให้สาธารณะตั้งแต่เดือนธันวาคม 2017 ด้วยเหตุผลด้านความปลอดภัย สิ่งที่ดูได้จาก public endpoint คือแค่ค่า boolean available ของแต่ละ variant (true หรือ false) ถ้าต้องการตัวเลขสต็อกจริง ๆ ต้องใช้ Admin API ที่ยืนยันตัวตนแล้วเท่านั้น

ก่อนเริ่มเขียนโค้ด ลองดูตารางนี้แล้วตัดสินใจว่า field ไหนสำคัญกับงานของคุณ ถ้าเป็นงานติดตามราคา คุณต้องใช้ variants[].price, variants[].compare_at_price, และ variants[].available ถ้าเป็นงานหาลีด ให้เน้น vendor, product_type, และ tags คัดให้ตรงตั้งแต่ต้น จะช่วยให้ CSV สะอาดกว่าเยอะ

นอกจาก products.json ยังมี Collections, Meta และ endpoint อื่นของ Shopify

บทความสอน scrape ทั่วไปแทบไม่พูดถึง endpoint เหล่านี้ แต่ถ้าทำ competitive intelligence แบบจริงจัง มันสำคัญมาก

/collections.json — หมวดหมู่สินค้าทั้งหมดของร้าน

คืนข้อมูล collection (หมวดหมู่) ทุกอันในร้าน พร้อมชื่อ, handle, คำอธิบาย และจำนวนสินค้า ผมลองกับ zoologistperfumes.com, allbirds.com, และ gymshark.com แล้ว ทุกเว็บคืน JSON ได้ปกติ

1{
2  "collections": [
3    {
4      "id": 308387348539,
5      "title": "Attars",
6      "handle": "attars",
7      "published_at": "2026-03-29T12:20:32-04:00",
8      "products_count": 1,
9      "image": { "src": "https://cdn.shopify.com/..." }
10    }
11  ]
12}

ถ้าอยากรู้ว่า competitor จัดโครงสร้างแค็ตตาล็อกยังไง endpoint นี้แหละคือคำตอบ

/collections/{handle}/products.json — สินค้าตามหมวดหมู่

คืนสินค้าที่กรองตาม collection เฉพาะ หมายเหตุคือโครงสร้าง JSON เหมือน /products.json แต่จำกัดอยู่แค่หนึ่งหมวดหมู่เท่านั้น สำคัญมากสำหรับการ scrape ระดับหมวดหมู่—เช่นคุณอยากติดตามเฉพาะคอลเลกชัน “Sale” หรือ “New Arrivals” ของคู่แข่ง

/meta.json — เมตาข้อมูลระดับร้าน

คืนชื่อร้าน, คำอธิบาย, สกุลเงิน, ประเทศ และส่วนที่มีประโยชน์ที่สุดคือ published_products_count ตัวเลขนี้ช่วยให้คุณคำนวณได้ล่วงหน้าว่าต้องใช้ pagination กี่หน้า: ceil(published_products_count / 250) ไม่ต้องเดาแบบสุ่มแล้วไล่เพิ่ม page ไปเรื่อย ๆ จนเจอ response ว่าง

ควรใช้ endpoint ไหน

สิ่งที่ต้องการEndpointต้องยืนยันตัวตนไหม
สินค้าทั้งหมด (สาธารณะ)/products.jsonไม่ต้อง
สินค้าในหมวดหมู่เฉพาะ/collections/{handle}/products.jsonไม่ต้อง
เมตาข้อมูลร้าน + จำนวนสินค้า/meta.jsonไม่ต้อง
คอลเลกชัน (หมวดหมู่) ทั้งหมด/collections.jsonไม่ต้อง
ข้อมูลออเดอร์/ยอดขาย (เฉพาะร้านตัวเอง)Admin API /orders.jsonต้องใช้ (API key)
ปริมาณสต็อก (เฉพาะร้านตัวเอง)Admin API /inventory_levels.jsonต้องใช้

คำถามที่เจอบ่อยในฟอรั่ม—"จะ scrape ดูได้ไหมว่าคู่แข่งขายไปกี่ชิ้น"—คำตอบสั้น ๆ คือ ไม่ได้ ถ้าใช้แค่ public endpoint ข้อมูลยอดขายและจำนวนสต็อกต้องใช้ Admin API ที่ยืนยันตัวตนแล้ว ซึ่งหมายความว่าคุณต้องมีสิทธิ์ของเจ้าของร้าน Public endpoint ให้ได้แค่ข้อมูลแค็ตตาล็อกสินค้าเท่านั้น

shopify-data-access-methods.webp

วิธี scrape Shopify ด้วย Python แบบทีละขั้น

  • ระดับความยาก: มือใหม่
  • เวลาที่ใช้: ประมาณ 15 นาที (ตั้งค่า + scrape ครั้งแรก)
  • สิ่งที่ต้องมี: Python 3.11+, pip, terminal และ URL ของร้าน Shopify ที่ต้องการ scrape

ขั้นตอนที่ 1: ติดตั้ง Python และไลบรารีที่จำเป็น

ตรวจให้แน่ใจว่าคุณติดตั้ง Python 3.11 หรือใหม่กว่าแล้ว (pandas 3.0.x ต้องการเวอร์ชันนี้) จากนั้นติดตั้งไลบรารีสองตัวที่ต้องใช้:

1pip install requests pandas

ถ้าจะ export เป็น Excel ด้วย ก็ให้ติดตั้งด้วย:

1pip install openpyxl

ที่หัวสคริปต์ ให้เพิ่ม import เหล่านี้:

1import requests
2import pandas as pd
3import time
4import random
5import json

ถ้ารันสคริปต์แล้วควรจะไม่เจอ import error ถ้า pandas ฟ้องเรื่องเวอร์ชัน ให้ขยับไปใช้ Python 3.12

ขั้นตอนที่ 2: ดึงข้อมูลสินค้าจาก /products.json

นี่คือฟังก์ชันพื้นฐานที่รับ URL ร้านค้า, เรียก endpoint และคืนค่า JSON ที่ parse แล้ว:

1def fetch_products_page(store_url, page=1, limit=250):
2    """Fetch a single page of products from a Shopify store."""
3    url = f"{store_url.rstrip('/')}/products.json"
4    params = {"limit": limit, "page": page}
5    headers = {
6        "User-Agent": "Mozilla/5.0 (compatible; ProductResearch/1.0)"
7    }
8    response = requests.get(url, params=params, headers=headers, timeout=30)
9    response.raise_for_status()
10    return response.json().get("products", [])

รายละเอียดสำคัญ:

  • limit=250 คือค่าสูงสุดที่ Shopify อนุญาตต่อหน้า ค่าเริ่มต้นคือ 30 ดังนั้นการตั้งค่านี้ช่วยลดจำนวน request ลงได้มากถึง 8 เท่า
  • header User-Agent: ควรตั้งให้ดูสมจริงเสมอ request ที่ไม่มี User-Agent มักมีโอกาสชนระบบ anti-bot ของ Shopify มากขึ้น
  • timeout=30: อย่าปล่อยให้ request ค้างอยู่ตลอดไป

ลองทดสอบกับร้านที่รู้จัก:

1products = fetch_products_page("https://allbirds.com")
2print(f"Fetched {len(products)} products")
3print(f"First product: {products[0]['title']}")

คุณควรจะเห็นผลลัพธ์ประมาณ Fetched 250 products และชื่อสินค้าตัวแรก

ขั้นตอนที่ 3: จัดการ pagination เพื่อ scrape สินค้าทั้งหมด

การ request เพียงครั้งเดียวจะได้สินค้าไม่เกิน 250 รายการเท่านั้น ร้านส่วนใหญ่มีมากกว่านั้น (เช่น Allbirds มีมากกว่า 1,420 รายการ) คุณจึงต้องวนทีละหน้าไปเรื่อย ๆ จนกว่าจะได้ response ว่างกลับมา

1def scrape_all_products(store_url, delay=1.0):
2    """Scrape all products from a Shopify store, handling pagination."""
3    all_products = []
4    page = 1
5    while True:
6        print(f"Fetching page {page}...")
7        products = fetch_products_page(store_url, page=page, limit=250)
8        if not products:
9            print(f"No more products. Total: {len(all_products)}")
10            break
11        all_products.extend(products)
12        print(f"  Got {len(products)} products (total so far: {len(all_products)})")
13        page += 1
14        # อย่าเร่งเกินไป: เว้นช่วงระหว่าง request
15        time.sleep(delay + random.uniform(0, 0.5))
16    return all_products

เมื่อ products กลับมาว่าง แปลว่าไปถึงหน้าสุดท้ายแล้ว

การใช้ time.sleep() พร้อมสุ่ม jitter เล็กน้อยช่วยให้คุณอยู่ต่ำกว่าขีดจำกัด rate limit แบบไม่เป็นทางการของ Shopify (ประมาณ 2 request/วินาที)

ทริกเพิ่มประสิทธิภาพ: ถ้าคุณดึง /meta.json มาก่อน คุณจะรู้จำนวนสินค้าทั้งหมดอยู่แล้ว และสามารถคำนวณจำนวนหน้าที่ต้องใช้ได้เป๊ะ ๆ ด้วย pages = ceil(product_count / 250) แบบนี้จะไม่ต้องยิง request ว่างเกินมา 1 ครั้งท้ายสุด

ขั้นตอนที่ 4: แยกฟิลด์ที่ต้องการออกมาใช้งาน

เมื่อคุณได้สินค้าทั้งหมดเป็น Python list ของ dictionary แล้ว ก็แค่ดึงเฉพาะฟิลด์ที่ต้องใช้ ตัวอย่างนี้ดึงฟิลด์ยอดนิยมสำหรับงานติดตามราคา:

1def extract_product_data(products):
2    """Extract key fields from products, flattening variants."""
3    rows = []
4    for product in products:
5        for variant in product.get("variants", []):
6            rows.append({
7                "product_id": product["id"],
8                "title": product["title"],
9                "handle": product["handle"],
10                "vendor": product.get("vendor", ""),
11                "product_type": product.get("product_type", ""),
12                "tags": ", ".join(product.get("tags", [])),
13                "created_at": product.get("created_at", ""),
14                "variant_id": variant["id"],
15                "variant_title": variant.get("title", ""),
16                "sku": variant.get("sku", ""),
17                "price": variant.get("price", ""),
18                "compare_at_price": variant.get("compare_at_price", ""),
19                "available": variant.get("available", ""),
20                "image_url": product["images"][0]["src"] if product.get("images") else ""
21            })
22    return rows

โค้ดนี้จะสร้าง 1 แถวต่อ 1 variant ซึ่งเป็นรูปแบบที่มีประโยชน์มากที่สุดสำหรับการเปรียบเทียบราคา เพราะสินค้าชิ้นหนึ่ง เช่น "Classic Blue Jeans" อาจมีถึง 12 variant (6 ไซซ์ × 2 สี) และแต่ละ variant ก็มีราคาและสถานะพร้อมขายต่างกัน

ส่งออก Shopify ที่ scrape ได้เป็น CSV และ Excel ด้วย pandas

บทความสอน scrape Shopify ส่วนใหญ่จบที่การ dump raw JSON ลงไฟล์แล้วถือว่าเสร็จ แต่แบบนั้นเหมาะกับนักพัฒนา ทว่าไม่ค่อยมีประโยชน์กับนักวิเคราะห์อีคอมเมิร์ซที่ต้องการสเปรดชีตไปใช้ภายในวันศุกร์

ปัญหาคือ JSON ของ Shopify ซ้อนกันหลายชั้น สินค้าหนึ่งชิ้นมี variant ได้เป็นสิบ ๆ ตัว และแต่ละตัวก็มีราคา SKU และ availability ของตัวเอง การแปลงให้เป็นแถวและคอลัมน์จึงต้องใช้ pandas ช่วย

แปลง JSON ซ้อนเป็นตารางที่อ่านง่าย

มี 2 วิธีหลัก ขึ้นอยู่กับวัตถุประสงค์:

ตัวเลือก A: 1 แถวต่อ 1 variant (เหมาะที่สุดสำหรับงานติดตามราคาและสต็อก)

1# ใช้ฟังก์ชัน extract_product_data จากขั้นตอนที่ 4
2products = scrape_all_products("https://allbirds.com")
3rows = extract_product_data(products)
4df = pd.DataFrame(rows)
5print(f"DataFrame shape: {df.shape}")
6print(df.head())

วิธีนี้จะได้ตารางแบบ flat ซึ่งแต่ละแถวคือคู่ product-variant ที่ไม่ซ้ำกัน ร้านที่มี 500 สินค้า และเฉลี่ยสินค้า 1 ชิ้นมี 4 variant ก็จะได้ DataFrame ประมาณ 2,000 แถว

ตัวเลือก B: 1 แถวต่อ 1 สรุปสินค้า (เหมาะกับภาพรวมแค็ตตาล็อก)

1def summarize_products(products):
2    """One row per product with min/max price across variants."""
3    rows = []
4    for product in products:
5        prices = [float(v["price"]) for v in product.get("variants", []) if v.get("price")]
6        rows.append({
7            "product_id": product["id"],
8            "title": product["title"],
9            "vendor": product.get("vendor", ""),
10            "product_type": product.get("product_type", ""),
11            "variant_count": len(product.get("variants", [])),
12            "min_price": min(prices) if prices else None,
13            "max_price": max(prices) if prices else None,
14            "any_available": any(v.get("available", False) for v in product.get("variants", [])),
15            "tags": ", ".join(product.get("tags", []))
16        })
17    return rows

Export เป็น CSV, Excel และ Google Sheets

1# Export เป็น CSV (ใช้ utf-8-sig เพื่อให้ Excel อ่านอักขระพิเศษได้)
2df.to_csv("shopify_products.csv", index=False, encoding="utf-8-sig")
3# Export เป็น Excel (ต้องใช้ openpyxl)
4df.to_excel("shopify_products.xlsx", index=False, engine="openpyxl")
5print("Exported to shopify_products.csv and shopify_products.xlsx")

ถ้าจะส่งต่อไป Google Sheets ก็ใช้ไลบรารี gspread กับ service account ได้ แต่พูดตรง ๆ เลย สำหรับงานส่วนใหญ่การ export เป็น CSV แล้วอัปโหลดเข้า Google Drive จะเร็วและง่ายกว่า

สแครปแบบใช้งานจริง: rate limit, retry และการหลบการบล็อก

สคริปต์พื้นฐานจะใช้งานได้ดีกับร้านเล็ก ๆ แต่ถ้าจะสแครปร้านที่มีสินค้ามากกว่า 5,000 รายการ หรือไล่หลายร้านต่อเนื่อง ปัญหาจะเริ่มโผล่

เข้าใจ rate limit และพฤติกรรมการบล็อกของ Shopify

public JSON endpoints ของ Shopify ไม่มีการระบุ rate limit แบบเป็นทางการ (ต่างจาก Admin API ที่มี leaky bucket model) แต่จากการทดสอบจริงพบว่า:

  • อัตราที่ปลอดภัย: ประมาณ 2 request ต่อวินาทีต่อร้าน
  • เพดานแบบนุ่ม ๆ: ประมาณ 40 request ต่อนาที ก่อนเริ่มโดน throttle
  • HTTP 429: "Too Many Requests" คือ response มาตรฐานเมื่อโดนจำกัดอัตรา
  • HTTP 430: โค้ดเฉพาะของ Shopify ที่บอกว่าถูกบล็อกระดับ security ไม่ใช่แค่ rate limit
  • HTTP 403 หรือ redirect ไป CAPTCHA: บางร้านมี Cloudflare หรือระบบป้องกันเพิ่ม

request ที่มาจาก cloud infrastructure ร่วมกัน เช่น AWS Lambda หรือ Google Cloud Run มีโอกาสโดนบล็อกมากเป็นพิเศษ เพราะ IP เหล่านั้นมักถูกใช้แบบผิดปกติค่อนข้างสูง

เทคนิคให้ scrape Shopify ได้เสถียร

นี่คือพัฒนาการจาก "รันได้บนเครื่องฉัน" ไปสู่ "พร้อมใช้งานจริง":

ระดับเทคนิคความน่าเชื่อถือ
ขั้นพื้นฐานrequests.get() + ?page=พังกับแค็ตตาล็อกใหญ่ และอาจโดนบล็อก
ระดับกลางrequests.Session() + ?limit=250 + time.sleep(1) + retry ตอน 429ใช้ได้กับร้านส่วนใหญ่
ขั้นสูงAsync httpx + สลับ User-Agent + exponential backoffพร้อมใช้งานจริง รองรับ 10K+ สินค้า

ระดับกลาง (แนะนำสำหรับคนส่วนใหญ่):

1import requests
2from requests.adapters import HTTPAdapter
3from urllib3.util.retry import Retry
4> This paragraph contains content that cannot be parsed and has been skipped.
5การตั้งค่า `Retry` จะจัดการ 429 ให้อัตโนมัติด้วย exponential backoff โดย `backoff_factor=1` หมายถึงช่วงเวลาหน่วงจะเป็น 0.5s → 1s → 2s → 4s → 8s ระหว่างการ retry นอกจากนี้การใช้ `requests.Session()` ซ้ำยังช่วยให้มี connection pooling ลด overhead เวลา request ไปโดเมนเดิมหลายครั้ง
6**การสลับ User-Agent**: ถ้าคุณ scrape หลายร้าน ให้สลับระหว่าง browser User-Agent ที่สมจริง 35 แบบ ไม่ใช่เพื่อหลอกใคร แต่เพื่อไม่ให้ดูเหมือนบอทที่ส่ง header เดิมทุก request
7<iframe width="560" height="315" src="https://www.youtube.com/embed/p3Z-qtUp4p8" title="Web Scraping Project: Save Shopify Products to Database" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe>
8## สคริปต์ Python ฉบับสมบูรณ์สำหรับ scrape Shopify พร้อม export CSV
9นี่คือสคริปต์ฉบับเต็มแบบคัดลอกไปใช้ได้เลย ที่รวมทุกอย่างข้างบนเข้าไว้ด้วยกัน โค้ดจริงประมาณ 75 บรรทัด (ยังไม่รวมคอมเมนต์) และผมทดสอบกับ Allbirds (1,420 สินค้า), ColourPop (2,000+ สินค้า) และ Zoologist Perfumes (แค็ตตาล็อกเล็ก)
10```python
11import requests
12import pandas as pd
13import time
14import random
15from requests.adapters import HTTPAdapter
16from urllib3.util.retry import Retry
17> This paragraph contains content that cannot be parsed and has been skipped.
18def scrape_shopify(store_url, delay=1.0):
19    """Scrape all products from a Shopify store via /products.json."""
20    session = create_session()
21    all_products = []
22    page = 1
23    base_url = f"{store_url.rstrip('/')}/products.json"
24> This paragraph contains content that cannot be parsed and has been skipped.
25        if not products:
26            break
27        all_products.extend(products)
28        print(f"{len(products)} products (total: {len(all_products)})")
29        page += 1
30        time.sleep(delay + random.uniform(0, 0.5))
31    return all_products
32> This paragraph contains content that cannot be parsed and has been skipped.
33if __name__ == "__main__":
34    STORE_URL = "https://allbirds.com"  # เปลี่ยนเป็นร้านเป้าหมายของคุณ
35    OUTPUT_CSV = "shopify_products.csv"
36    OUTPUT_EXCEL = "shopify_products.xlsx"
37    print(f"Scraping {STORE_URL}...")
38    products = scrape_shopify(STORE_URL)
39    print(f"\nTotal products scraped: {len(products)}")
40    print("Flattening to variant-level rows...")
41    rows = flatten_to_variants(products)
42    df = pd.DataFrame(rows)
43    print(f"DataFrame: {df.shape[0]} rows x {df.shape[1]} columns")
44    df.to_csv(OUTPUT_CSV, index=False, encoding="utf-8-sig")
45    df.to_excel(OUTPUT_EXCEL, index=False, engine="openpyxl")
46    print(f"\nExported to {OUTPUT_CSV} and {OUTPUT_EXCEL}")

รันด้วย python scrape_shopify.py สำหรับ Allbirds ใช้เวลาประมาณ 45 วินาที และจะได้ CSV ที่มีข้อมูลประมาณ 5,000+ แถว (หนึ่งแถวต่อหนึ่ง variant) เอาต์พุตในเทอร์มินัลจะออกมาประมาณนี้:

1Scraping https://allbirds.com...
2  Page 1... 250 products (total: 250)
3  Page 2... 250 products (total: 500)
4  ...
5  Page 6... 170 products (total: 1420)
6Total products scraped: 1420
7Flattening to variant-level rows...
8DataFrame: 5680 rows x 14 columns
9Exported to shopify_products.csv and shopify_products.xlsx

ไม่อยากใช้ Python? scrape Shopify ได้ใน 2 คลิกด้วย Thunderbit (แบบ No-code)

ไม่ใช่ทุกคนที่อยากติดตั้ง Python, ไล่แก้ import error หรือคอยดูแลสคริปต์ scrape เอง สำหรับเซลส์ที่ต้องรู้ราคาคู่แข่งพรุ่งนี้เช้า Python อาจเกินจำเป็น

นั่นจึงเป็นเหตุผลที่เราสร้าง ขึ้นมา—AI web scraper ที่ทำงานเป็น Chrome extension ไม่ต้องเขียนโค้ด ไม่ต้องใช้ API key ไม่ต้องตั้ง environment

Thunderbit scrape ร้าน Shopify อย่างไร

Thunderbit มี Shopify Scraper template เฉพาะที่ตั้งค่ามาให้พร้อมสำหรับหน้าสินค้า Shopify อยู่แล้ว แค่ติดตั้ง เข้าไปที่ร้าน Shopify แล้วกด "Scrape" ระบบจะดึงชื่อสินค้า คำอธิบาย ราคา รายละเอียด variant รูปภาพ และข้อมูล vendor ให้โดยอัตโนมัติ

สำหรับร้านที่ template ไม่ตรงพอดี (เช่นธีมปรับแต่งเองหรือเลย์เอาต์แปลก ๆ) ฟีเจอร์ AI Suggest Fields ของ Thunderbit จะอ่านหน้าเว็บแล้วสร้างชื่อคอลัมน์ให้อัตโนมัติ คุณสามารถปรับแต่งต่อได้—เปลี่ยนชื่อคอลัมน์ เพิ่มฟิลด์ หรือเขียนคำสั่งเช่น "ดึงเฉพาะสินค้าที่มี compare_at_price เท่านั้น"

ฟีเจอร์บางอย่างของ Thunderbit เทียบตรงกับสิ่งที่สคริปต์ Python ทำได้:

  • Subpage scraping: เข้าไปยังหน้ารายละเอียดสินค้าทีละหน้าโดยอัตโนมัติ แล้วเติมข้อมูลคำอธิบายเต็ม รีวิว หรือรายละเอียด variant ลงในตาราง—สิ่งเดียวกับที่สคริปต์ Python ทำผ่านการไล่หน้า แต่ไม่ต้องเขียนโค้ดเลย
  • Automatic pagination: จัดการ pagination แบบ click-through และ infinite scroll ให้โดยไม่ต้องตั้งค่า
  • Scheduled scraping: ตั้งงานให้รันซ้ำเป็นรอบ ๆ (เช่น “ทุกวันจันทร์ 9 โมงเช้า”) สำหรับเฝ้าดูราคาอย่างต่อเนื่อง—ไม่ต้องมี cron job หรือเซิร์ฟเวอร์
  • ส่งออกฟรี ไป CSV, Excel, Google Sheets, Airtable หรือ Notion ได้ทุกแพลน

เทียบ Python Script กับ Thunderbit แบบตรงไปตรงมา

ปัจจัยPython ScriptThunderbit (No-code)
เวลาเริ่มต้น15–60 นาที (ตั้งค่าสภาพแวดล้อม + โค้ด)ประมาณ 2 นาที (ติดตั้ง Chrome extension)
ต้องเขียนโค้ดไหมต้อง (Python)ไม่ต้อง
ปรับแต่งได้แค่ไหนไม่จำกัดAI suggest fields + custom prompts
การจัดการ paginationต้องเขียนเองอัตโนมัติ
รูปแบบ exportต้องเขียนเอง (CSV/Excel)CSV, Excel, Google Sheets, Airtable, Notion (ฟรี)
การรันตามเวลาต้องมี cron job + hostingมี scheduler ในตัว
การรับมือ rate limitต้องเขียน retry/backoff เองจัดการให้อัตโนมัติ
เหมาะกับใครนักพัฒนา, data pipeline ขนาดใหญ่ผู้ใช้งานธุรกิจ, งานดึงข้อมูลเร็ว ๆ, เฝ้าติดตามซ้ำ ๆ

ใช้ Python เมื่อคุณต้องการควบคุมทุกอย่างเอง หรือกำลังเชื่อมเข้ากับ data pipeline ขนาดใหญ่ ใช้ Thunderbit เมื่อคุณต้องการข้อมูลเร็ว ๆ และไม่อยากเสียเวลาดูแลโค้ด สำหรับมุมมองเชิงลึกเรื่อง เรามีคู่มือแยกไว้อีกบทความหนึ่ง

python-vs-thunderbit-comparison.webp

เคล็ดลับและแนวทางปฏิบัติที่ดีในการ scrape ร้าน Shopify

ไม่ว่าคุณจะใช้เครื่องมืออะไร ข้อแนะนำเหล่านี้ก็ยังใช้ได้เสมอ:

  • ใช้ ?limit=250 เสมอ เพื่อลดจำนวน request ให้เหลือน้อยที่สุด ค่าเริ่มต้น 30 ต่อหน้าจะทำให้ต้องยิง request มากกว่าเดิมถึง 8 เท่าเพื่อข้อมูลเท่าเดิม
  • เคารพเซิร์ฟเวอร์ของร้าน: เว้นช่วง 1–2 วินาทีระหว่าง request การยิงถี่ ๆ ไม่ใช่แค่เสียมารยาท แต่ยังเพิ่มโอกาสโดนบล็อกด้วย
  • เช็ก robots.txt ก่อน: robots.txt มาตรฐานของ Shopify จะไม่บล็อก /products.json แต่บางร้านเพิ่มกฎเอง จึงควรตรวจสอบก่อน scrape ขนาดใหญ่
  • เก็บ raw JSON ไว้ก่อน แล้วค่อย process ถ้ากติกาการ parse เปลี่ยนทีหลัง คุณจะไม่ต้อง scrape ใหม่ทั้งหมด การ json.dump(all_products, open("raw_data.json", "w")) ก่อน flatten ช่วยลดปวดหัวได้มาก
  • deduplicate ด้วย product.id: บางครั้ง pagination ที่ขอบหน้าอาจคืนสินค้าซ้ำกันได้ การใช้ df.drop_duplicates(subset=["product_id", "variant_id"]) ช่วยจัดการได้
  • แปลง price เป็น float ก่อนคำนวณ เพราะ Shopify ส่งราคากลับมาเป็น string (เช่น "185.00") ไม่ใช่ตัวเลข
  • เฝ้าดูการเปลี่ยนแปลงของ endpoint: แม้ /products.json จะเสถียรมาหลายปี แต่ Shopify ก็อาจจำกัดการเข้าถึงในอนาคตได้ ถ้า scraper ใช้ไม่ได้กะทันหัน ให้ลองเช็กร้านด้วยมือก่อน

ถ้าอยากเรียนรู้เรื่องการสร้าง scraper ที่ทนทานมากขึ้น ลองอ่านคู่มือ ของเรา

ข้อควรพิจารณาด้านกฎหมายและจริยธรรมเมื่อ scrape Shopify

เป็นหัวข้อสั้น ๆ แต่สำคัญมาก

endpoint /products.json ให้ข้อมูลสินค้าที่เปิดเผยต่อสาธารณะ—ข้อมูลเดียวกับที่ผู้เข้าชมร้านทั่วไปเห็นได้ Shopify Terms of Service มีถ้อยคำเกี่ยวกับการไม่ใช้ "automated means" เพื่อเข้าถึง "the Services" แต่คำนี้หมายถึงตัวแพลตฟอร์มเอง (เช่นแดชบอร์ดผู้ดูแล ระบบเช็กเอาต์) ไม่ใช่ข้อมูลหน้าร้านที่เปิดสาธารณะ ณ เดือนเมษายน 2026 ยังไม่มีคดีฟ้องร้องเกี่ยวกับการ scrape Shopify โดยตรง

บรรทัดฐานทางกฎหมายที่สนับสนุนการ scrape ข้อมูลสาธารณะมีอยู่แล้ว เช่น คดี hiQ v. LinkedIn ที่ระบุว่าการ scrape ข้อมูลที่เข้าถึงได้สาธารณะไม่ได้ละเมิด CFAA และคดี Meta v. Bright Data (2024) ก็วินิจฉัยว่าข้อจำกัดใน TOS ใช้ได้เมื่อผู้ใช้ล็อกอินอยู่เท่านั้น

แนวทางที่ควรทำ:

  • scrape เฉพาะข้อมูลสินค้าที่เปิดเผยสาธารณะ
  • อย่า scrape ข้อมูลส่วนบุคคลหรือลูกค้า
  • เคารพ robots.txt และ rate limit
  • ปฏิบัติตาม GDPR/CCPA หากต้องจัดการข้อมูลส่วนบุคคลใด ๆ (ข้อมูลแค็ตตาล็อกสินค้าไม่ใช่ข้อมูลส่วนบุคคล)
  • ระบุตัวตนให้ชัดด้วย User-Agent string ที่เหมาะสม
  • การ scrape ร้าน Shopify ของตัวเองผ่าน Admin API นั้นทำได้สบายอยู่แล้ว

ถ้าอยากอ่านให้ลึกขึ้น ลองดูโพสต์ ของเรา

สรุปและประเด็นสำคัญ

public /products.json ของ Shopify ทำให้การดึงข้อมูลอีคอมเมิร์ซง่ายมาก ๆ เวิร์กโฟลว์คือ: เติม /products.json → ดึงด้วย Python → ไล่ pagination ด้วย ?limit=250&page= → flatten ด้วย pandas → export เป็น CSV หรือ Excel

สิ่งที่คู่มือนี้ให้มากกว่าบทความอื่น:

  • อ้างอิงฟิลด์แบบครบถ้วน: รู้เลยว่ามีข้อมูลอะไรให้ใช้บ้าง (มากกว่า 40 ฟิลด์ใน product, variant และ image) ก่อนเขียนโค้ดแม้แต่บรรทัดเดียว
  • endpoint เพิ่มเติม: /collections.json และ /meta.json ช่วยให้ได้ข้อมูลระดับหมวดหมู่และ metadata ของร้าน ซึ่งบทความอื่นมักไม่พูดถึง
  • เทคนิคระดับ production: การใช้ session ซ้ำ, exponential backoff, User-Agent headers และ ?limit=250 เพื่อรับมือ rate limit ของโลกจริง
  • การ export CSV/Excel ที่ถูกต้อง: flatten ข้อมูลระดับ variant ด้วย pandas ไม่ใช่ dump JSON ดิบ ๆ อย่างเดียว
  • ทางเลือกแบบ no-code: สำหรับคนที่อยากได้ความเร็วมากกว่าความยืดหยุ่นของโค้ด

ถ้าคุณต้องการดึงข้อมูล Shopify แบบครั้งเดียวหรือแบบทำซ้ำโดยไม่เขียนโค้ด ลองใช้ ได้เลย—Shopify Scraper template จัดการทุกอย่างตั้งแต่ pagination ไปจนถึง export ให้ครบ สำหรับ data pipeline แบบกำหนดเอง หรือการ scrape หลายร้านในสเกลใหญ่ สคริปต์ Python ในคู่มือนี้ให้คุณควบคุมได้เต็มที่

แวะดู ของเราเพื่อดูวิดีโอสาธิต หรืออ่านคู่มือเพิ่มเติมเกี่ยวกับ และ สำหรับเทคนิคที่ใกล้เคียงกัน

ลองใช้ Thunderbit สำหรับการ scrape Shopify

คำถามที่พบบ่อย

ใช้ products.json scrape ร้าน Shopify ทุกแห่งได้ไหม

ร้าน Shopify ส่วนใหญ่จะเปิด endpoint นี้ไว้เป็นค่าเริ่มต้น—จากการทดสอบประมาณ 71% จะคืน JSON ที่ใช้งานได้ บางร้านที่ตั้งค่าเองหรือมีระบบป้องกันเพิ่มเติม (Cloudflare, headless setup) อาจได้ 404 หรือบล็อก request ได้ วิธีเช็กเร็วที่สุดคือเปิด {store-url}/products.json ในเบราว์เซอร์ ถ้าเห็น JSON ก็ใช้ได้

การ scrape ร้าน Shopify ถูกกฎหมายไหม

ข้อมูลสินค้าสาธารณะ เช่น ราคา ชื่อสินค้า รูปภาพ และคำอธิบาย โดยทั่วไปเข้าถึงได้ และบรรทัดฐานทางกฎหมายอย่าง hiQ v. LinkedIn ก็สนับสนุนการ scrape ข้อมูลที่เปิดเผยต่อสาธารณะ แต่ก็ควรตรวจ Terms of Service ของร้านนั้น ๆ และกฎหมายท้องถิ่นเสมอ อย่า scrape ข้อมูลส่วนบุคคลหรือลูกค้า และต้องเคารพ rate limit

scrape ร้าน Shopify ได้กี่สินค้า

ไม่มีข้อจำกัดตายตัวในแง่จำนวนรวม Pagination ด้วย ?limit=250&page= ช่วยให้คุณดึงทั้งแค็ตตาล็อกได้หมด สำหรับร้านใหญ่มาก ๆ (25,000+ สินค้า) ควรใช้ session ซ้ำและเว้นช่วงเวลาเพื่อลดโอกาสโดน rate limit และ /meta.json จะบอกจำนวนสินค้าล่วงหน้าให้รู้ว่าต้องใช้กี่หน้า

ต่างกันอย่างไรระหว่าง products.json กับ Shopify Admin API

/products.json เป็น endpoint สาธารณะ—ไม่ต้องยืนยันตัวตน เป็นข้อมูลสินค้าที่อ่านได้อย่างเดียว ใครก็เข้าถึงได้ ส่วน Admin API ต้องใช้ access token ของเจ้าของร้าน และให้ข้อมูลออเดอร์ จำนวนสต็อก ข้อมูลลูกค้า และสิทธิ์เขียน หากคุณต้องการข้อมูลยอดขายหรือจำนวนสต็อกจริง ๆ ต้องใช้ Admin API (ซึ่งแปลว่าคุณต้องเป็นเจ้าของร้านหรือได้รับอนุญาต)

ไม่ใช้ Python จะ scrape Shopify ได้ไหม

ได้แน่นอน เครื่องมืออย่าง ช่วยให้คุณ scrape ร้าน Shopify ผ่าน Chrome extension ได้โดยไม่ต้องเขียนโค้ด มันจัดการ pagination ให้อัตโนมัติ และ export ไปยัง CSV, Excel, Google Sheets, Airtable หรือ Notion ได้โดยตรง สำหรับนักพัฒนาที่ถนัดภาษาอื่น endpoint /products.json เดิมก็ใช้ได้กับ JavaScript, Ruby, Go—ทุกภาษาที่ส่ง HTTP request และ parse JSON ได้

เรียนรู้เพิ่มเติม

สารบัญ

ลองใช้ Thunderbit

ดึงลีดและข้อมูลอื่น ๆ ได้ใน 2 คลิก ขับเคลื่อนด้วย AI

รับ Thunderbit ใช้ฟรี
ดึงข้อมูลด้วย AI
ส่งข้อมูลไปยัง Google Sheets, Airtable หรือ Notion ได้อย่างง่ายดาย
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week