Automatisoi markkinatutkimuksesi: Shopifyn selaaminen Pythonilla

Viimeksi päivitetty April 16, 2026

Shopifyn /products.json-päätepiste on yksi verkkokauppadatan huonosti vartioiduimmista aarteista. Lisää se minkä tahansa Shopify-kaupan URL-osoitteen loppuun, niin saat takaisin jäsenneltyä JSON-dataa — ilman API-avaimia, ilman tunnistautumista ja ilman sitä, että sinun täytyy penkoa läpi monimutkaista HTML:ää.

Työskentelen -tiimissä, joten mietin koko ajan, miten ihmiset hakevat dataa verkosta. Shopify-datan poiminta nousee esiin kerta toisensa jälkeen: myyntitiimit seuraavat kilpailijoiden hintoja, verkkokaupan operatiiviset tiimit vertailevat tuotevalikoimia ja hankintatiimit etsivät uusia toimittajia. Kun Shopifylla on ja alusta kattaa noin , poimittavaa tuotetietoa on valtavasti.

Tämä opas käy läpi koko prosessin: mitä päätepiste palauttaa, miten satojen tai tuhansien tuotteiden läpikäynti onnistuu, miten vältät estot rate limit -rajojen keskellä ja miten Shopifyn sisäkkäinen JSON muunnetaan siistiksi CSV- tai Excel-tiedostoksi pandasilla. Mukana ovat myös päätepisteet, joista muut eivät juuri puhu (/collections.json, /meta.json), sekä vaihtoehto ilman koodausta niille, jotka haluavat ohittaa Pythonin kokonaan.

Mikä Shopifyn /products.json-päätepiste on, ja miksi se tekee datan poiminnasta helppoa?

Jokaisella Shopify-kaupalla on julkinen päätepiste osoitteessa {store-url}/products.json, joka palauttaa jäsenneltyä tuotetietoa. Ei API-avaimia. Ei OAuthia. Ei minkäänlaista tunnistautumista. Lisää vain /products.json kaupan URL-osoitteen loppuun, niin saat JSON-taulukon koko katalogin tuotteista.

Kokeile vaikka heti: avaa selaimessa tai . Näet siistiä, jäsenneltyä JSONia, jossa on tuotteen nimi, hinta, versiot, kuvat, tunnisteet — kaikki.

Verrattuna vaihtoehtoon: Shopifyn HTML-teemojen purkaminen on työlästä, koska rakenne on monitasoinen, kauppakohtaisesti vaihteleva ja muuttuu aina, kun kauppias päivittää teemansa. Tästä olisi kyse:

HTML-lähestymistapa (vaivalloinen):

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-lähestymistapa (selkeä):

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 voittaa johdonmukaisuudessa, luotettavuudessa ja helpossa käsiteltävyydessä. Päätepiste tukee myös kahta keskeistä kyselyparametria — ?limit= (enintään 250 tuotetta per sivu, oletuksena 30) ja ?page= sivutukseen — ja käytämme niitä laajasti alla olevassa koodissa.

Tärkeä ero: kyseessä on julkinen verkkokaupan päätepiste, ei . Admin API vaatii kaupan omistajan tunnisteet ja antaa pääsyn tilauksiin, varastotasoihin ja asiakastietoihin. Julkinen /products.json-päätepiste tarjoaa vain tuotetietoa, jota kuka tahansa voi lukea. Kerron eron tarkemmin myöhemmin, koska tästä syntyy paljon hämmennystä foorumeilla.

Huomio: kaikki Shopify-kaupat eivät paljasta tätä päätepistettä. Omissa testeissäni noin 71 % kaupoista palautti kelvollisen JSONin (esim. allbirds.com, gymshark.com, colourpop.com, kyliecosmetics.com toimivat), mutta osa räätälöidyistä toteutuksista palauttaa 404:n (hiutdenim.co.uk, bombas.com). Nopea tarkistus on helppo: käy osoitteessa {store-url}/products.json selaimessa ja katso, mitä saat.

Miksi Shopify kannattaa scrapeata Pythonilla? Tärkeimmät liiketoiminnan käyttötapaukset

Miksi nähdä vaivaa? ROI:n takia. käyttää nyt automatisoitua hintaseurantaa kilpailija-analyysiin, kun osuus oli vain 34 % vuonna 2020. Ja tutkimusten mukaan . Tässä datassa on siis oikeaa rahaa.

Yleisimmät käyttötapaukset, joita näen:

KäyttötapausKenelle hyödyksiMitä saat
Kilpailijoiden hintaseurantaVerkkokaupan operatiiviset tiimitSeuraa hinnanmuutoksia, alennuksia ja vertailuhintoja kilpailijoiden katalogeissa
Tuotetutkimus ja hankintaHankinta / tuotevalikoiman hallintaVertaa ominaisuuksia, versioita, materiaaleja ja saatavuutta
Liidien generointiMyyntitiimitPoimi kauppakatalogeista toimittajanimet, bränditiedot ja yhteystiedot
Markkina- ja kategoriatutkimusMarkkinointitiimitYmmärrä tuotemix, tunnisteet, kokoelmien rakenne ja asemointi
Varasto- ja saatavuusseurantaToimitusketjutiimitSeuraa varianttikohtaista saatavuutta (available: true/false) ajan mittaan
Uusien tuotteiden tunnistusTuotetiimitSeuraa created_at-aikaleimoja ja huomaa kilpailijoiden uudet lanseeraukset

Python on tähän työhön luonteva valinta. käyttää Pythonia ensisijaisena kielenään, ja ekosysteemi — requests HTTP-kutsuihin, pandas datan käsittelyyn, httpx asynkroniseen käyttöön — tekee URL-osoitteesta taulukoksi -polun rakentamisesta suoraviivaista alle 80 rivillä koodia.

Täydellinen products.json-kenttäviite: mitä kaikki kentät tarkoittavat

Useimmat oppaat näyttävät vain title, id ja handle, ja siirtyvät siitä eteenpäin. Shopifyn JSON-vastaus sisältää kuitenkin yli 40 kenttää tuotteissa, varianteissa, kuvissa ja optioissa. Kun tiedät, mitä on tarjolla ennen scraping-koodin kirjoittamista, vältät sen, että joudut tekemään kaiken uusiksi myöhemmin.

Tämä viite perustuu live-vastauksiin osoitteesta /products.json, jotka haettiin 16.4.2026. Rakenne on sama kaikissa kaupoissa, jotka paljastavat tämän päätepisteen.

Tuotetason kentät

KenttäTietotyyppiEsimerkkiarvoLiiketoiminnallinen käyttö
idKokonaisluku123456789Yksilöllinen tuotetunniste deduplikointiin
titleMerkkijono"Classic Blue Jeans"Tuotenimi katalogeihin ja vertailuihin
handleMerkkijono"classic-blue-jeans"URL-slug — rakenna tuotesivun linkit muodossa {store}/products/{handle}
body_htmlMerkkijono (HTML) tai null

Our best-selling...

Tuotekuvaus sisällön analyysiin ja SEO-tutkimukseen
vendorMerkkijono"Hiut Denim"Brändi-/toimittajan nimi liidien hankintaan tai sourcingiin
product_typeMerkkijono"Jeans"Luokituskenttä markkina-analyysiin
created_atISO DateTime"2024-01-15T10:30:00-05:00"Seuraa, milloin tuotteet lisättiin (uudet lanseeraukset)
updated_atISO DateTime"2025-03-01T08:00:00-05:00"Havaitse viimeaikaiset muutokset katalogissa
published_atISO DateTime"2024-01-16T00:00:00-05:00"Tiedä, milloin tuote julkaistiin verkkokaupassa
tagsMerkkijonotaulukko["organic", "women", "straight-leg"]Avainsana-/tagianalyysi SEO:hon, luokitteluun ja trendien tunnistamiseen
variantsObjektitaulukko(katso varianttikentät alempaa)Hinta, SKU ja saatavuus varianttitasolla
imagesObjektitaulukko(katso kuvakentät alempaa)Tuotekuvien URL-osoitteet katalogeihin ja visuaaliseen analyysiin
optionsObjektitaulukko[{"name": "Size", "values": ["S","M","L"]}]Ymmärrä tuotteen konfiguraatio (koko, väri, materiaali)

Varianttitason kentät (sisäkkäin jokaisen tuotteen alla)

KenttäTietotyyppiEsimerkkiKäyttötapaus
idKokonaisluku987654321Yksilöllinen varianttitunniste
titleMerkkijono"32 / Blue"Variantin näyttönimi
skuMerkkijono"HD-BLU-32"SKU-tunniste varastonhallintajärjestelmiin
priceMerkkijono"185.00"Hintaseuranta (huomaa: kyseessä on merkkijono, muunna luvuksi laskutoimituksia varten)
compare_at_priceMerkkijono tai null"200.00"Alkuperäinen hinta — tärkeä alennusten seurannassa
availableTotuusarvotrueSaatavuus varastossa (ainoa julkinen varastoindikaattori)
weightLiukuluku1.2Kuljetus- ja logistiikka-analyysi
option1, option2, option3Merkkijono"32", "Blue", nullYksittäiset optioarvot
created_at, updated_atISO DateTimeVarianttikohtainen muutosten seuranta

Kuvaan liittyvät kentät

KenttäTietotyyppiEsimerkkiKäyttötapaus
idKokonaisluku111222333Yksilöllinen kuvatunniste
srcMerkkijono (URL)"https://cdn.shopify.com/..."Suora kuvan latauslinkki
altMerkkijono tai null"Front view of jeans"Alt-tekstin analyysi saavutettavuuden näkökulmasta
positionKokonaisluku1Kuvien järjestys
width, heightKokonaisluku2048, 2048Kuvan mitat

Mitä julkisessa päätepisteessä EI ole

Tärkeä sudenkuoppa: inventory_quantity EI ole saatavilla julkisissa /products.json-vastauksissa. Tämä kenttä poistettiin julkisista JSON-päätepisteistä joulukuussa 2017 turvallisuussyistä. Ainoa saatavuusindikaattori on variantin available-kenttä (true tai false). Todelliset varastomäärät saa vain todennetun Admin API:n kautta kaupan omistajan tunnuksilla.

Ennen kuin kirjoitat scraping-koodin, käy tämä taulukko läpi ja päätä, mitkä kentät ovat sinun käyttötapauksessasi olennaisia. Jos seuraat hintoja, tarvitset variants[].price, variants[].compare_at_price ja variants[].available. Jos teet liidien hankintaa, keskity kenttiin vendor, product_type ja tags. Suodata sen mukaan — CSV:stä tulee paljon siistimpi.

products.jsonin yli: kokoelmat, meta ja muut Shopify-päätepisteet

Mikään kilpailijan opas ei juuri mainitse näitä päätepisteitä. Ne ovat olennaisia tosissaan tehtävässä kilpailija-analyysissä.

/collections.json — kaikki kaupan kategoriat

Palauttaa kaikki kokoelmat eli kategoriat kaupassa otsikoineen, handleineen, kuvauksineen ja tuotelukumäärineen. Varmistin tämän zoologistperfumes.comissa, allbirds.comissa ja gymshark.comissa — kaikki palauttivat kelvollisen JSONin.

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}

Haluatko ymmärtää, miten kilpailija rakentaa kataloginsa? Tämä on se päätepiste.

/collections/{handle}/products.json — tuotteet kategorian mukaan

Palauttaa tuotteet suodatettuna tietyn kokoelman perusteella. Sama JSON-rakenne kuin /products.json-päätepisteessä, mutta rajattuna yhteen kategoriaan. Tämä on ratkaisevaa kategoriakohtaisessa scrapingissä — esimerkiksi jos haluat seurata vain kilpailijan “Sale”- tai “New Arrivals” -kokoelmaa.

/meta.json — kaupan metatiedot

Palauttaa kaupan nimen, kuvauksen, valuutan, maan ja — tässä se hyödyllinen osa — published_products_count-arvon. Sen avulla voit laskea etukäteen täsmälleen, montako sivua tarvitset: ceil(published_products_count / 250). Ei enää arvailua ja sivunumeroiden kasvattamista, kunnes saat tyhjän vastauksen.

Mitä päätepistettä kannattaa käyttää?

Mitä haluatPäätepisteTarvitaanko tunnistautuminen?
Kaikki tuotteet (julkiset)/products.jsonEi
Tuotteet tietystä kategoriasta/collections/{handle}/products.jsonEi
Kaupan metatiedot + tuotelukumäärä/meta.jsonEi
Kaikki kokoelmat (kategoriat)/collections.jsonEi
Tilaus-/myyntidata (vain oma kauppa)Admin API /orders.jsonKyllä (API-avain)
Varastomäärät (vain oma kauppa)Admin API /inventory_levels.jsonKyllä

Toistuva foorumikysymys — “Voinko scrapeata, montako yksikköä kilpailija on myynyt?” — saa lyhyen vastauksen: ei. Ei julkisista päätepisteistä. Myyntidata ja varastomäärät vaativat todennetun Admin API:n, joten tarvitset kaupan omistajan pääsyn. Julkiset päätepisteet tarjoavat vain tuoteluettelon.

shopify-data-access-methods.webp

Miten Shopify scrapeataan Pythonilla: vaiheittainen käyttöönotto

  • Vaikeustaso: Aloittelija
  • Aikaa kuluu: noin 15 minuuttia (asennus + ensimmäinen scrape)
  • Tarvitset: Python 3.11+, pip, terminaalin ja Shopify-kaupan URL-osoitteen

Vaihe 1: Asenna Python ja tarvittavat kirjastot

Varmista, että käytössäsi on Python 3.11 tai uudempi (pandas 3.0.x vaatii sen). Asenna sitten kaksi tarvitsemaamme kirjastoa:

1pip install requests pandas

Excel-vientiä varten tarvitset lisäksi:

1pip install openpyxl

Lisää skriptin alkuun nämä importit:

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

Kun ajat skriptin, import-virheitä ei pitäisi tulla. Jos pandas antaa versio-virheen, päivitä Python 3.12:een.

Vaihe 2: Hae tuotetiedot /products.json-päätepisteestä

Tässä on perustoiminto, joka ottaa kaupan URL-osoitteen, kutsuu päätepistettä ja palauttaa puretun JSONin:

1def fetch_products_page(store_url, page=1, limit=250):
2    """Hakee yhden tuotesivun Shopify-kaupasta."""
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", [])

Keskeiset yksityiskohdat:

  • limit=250 on Shopifyn sallima maksimi per sivu. Oletusarvo on 30, joten tämän asettaminen pienentää pyyntöjen kokonaismäärää jopa kahdeksasosaan.
  • User-Agent-otsake: aseta aina uskottava arvo. Pyynnöt ilman User-Agentia laukaisevat todennäköisemmin Shopifyn bottisuojaukset.
  • timeout=30: älä anna yksittäisen pyynnön jäädä roikkumaan loputtomiin.

Testaa tunnetulla kaupalla:

1products = fetch_products_page("https://allbirds.com")
2print(f"Noudettuja tuotteita: {len(products)}")
3print(f"Ensimmäinen tuote: {products[0]['title']}")

Näet jotakin tämän kaltaista: Noudettuja tuotteita: 250 ja ensimmäisen tuotteen nimen.

Vaihe 3: Käsittele sivutus, jotta saat kaikki tuotteet talteen

Yksi pyyntö palauttaa korkeintaan 250 tuotetta. Useimmissa kaupoissa on enemmän (Allbirdsillä yli 1 420). Siksi sinun täytyy kiertää sivuja, kunnes saat tyhjän vastauksen.

1def scrape_all_products(store_url, delay=1.0):
2    """Scrapeaa kaikki tuotteet Shopify-kaupasta sivutuksen avulla."""
3    all_products = []
4    page = 1
5    while True:
6        print(f"Haetaan sivua {page}...")
7        products = fetch_products_page(store_url, page=page, limit=250)
8        if not products:
9            print(f"Ei enempää tuotteita. Yhteensä: {len(all_products)}")
10            break
11        all_products.extend(products)
12        print(f"  Saatiin {len(products)} tuotetta (yhteensä nyt: {len(all_products)})")
13        page += 1
14        # Ole kohtelias: odota pyyntöjen välissä
15        time.sleep(delay + random.uniform(0, 0.5))
16    return all_products

Kun products palautuu tyhjänä, olet päässyt loppuun.

time.sleep()-odotus satunnaisella jitterillä pitää sinut Shopifyn epävirallisen rate limitin alapuolella (~2 pyyntöä sekunnissa).

Vinkki: jos haet ensin /meta.json-päätepisteen, tiedät jo tuotteiden kokonaismäärän ja voit laskea tarkasti tarvittavien sivujen määrän: pages = ceil(product_count / 250). Näin vältät yhden ylimääräisen tyhjän pyynnön loppupäässä.

Vaihe 4: Puretaan ja valitaan tarvittavat kentät

Kun sinulla on kaikki tuotteet Python-listana sanakirjoja, poimi vain ne kentät, jotka oikeasti tarvitset. Tässä esimerkissä haetaan yleisimmät kentät hintaseurantaa varten:

1def extract_product_data(products):
2    """Poimii tärkeät kentät tuotteista ja litistää variantit."""
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

Tämä luo yhden rivin per variantti — erittäin hyödyllinen muoto hintavertailuun, koska yksi tuote kuten “Classic Blue Jeans” voi sisältää 12 varianttia (6 kokoa × 2 väriä), joista jokaisella on oma hinta ja saatavuustila.

Vie Shopify-data CSV- ja Excel-muotoon pandasilla

Moni muu Shopify-scraping-opas dumppaa raakaa JSONia tiedostoon ja on tyytyväinen siihen. Kehittäjälle se voi riittää. Mutta verkkokauppa-analyytikolle, joka tarvitsee taulukon perjantaihin mennessä, siitä ei ole iloa.

Ongelma on siinä, että Shopifyn JSON on sisäkkäinen. Yksi tuote voi sisältää tusinan variantteja, joilla jokaisella on oma hinta, SKU ja saatavuus. Tämän litistäminen riveiksi ja sarakkeiksi vaatii hieman pandas-työtä.

Muunna sisäkkäinen JSON siistiksi taulukoksi

Kaksi vaihtoehtoa käyttötapauksesta riippuen:

Vaihtoehto A: yksi rivi per variantti (paras hintaseurantaan ja varaston seurantaan)

1# Käyttäen Step 4:n extract_product_data-funktiota
2products = scrape_all_products("https://allbirds.com")
3rows = extract_product_data(products)
4df = pd.DataFrame(rows)
5print(f"DataFramen koko: {df.shape}")
6print(df.head())

Tämä antaa litteän taulukon, jossa jokainen rivi on ainutlaatuinen tuote-variantti-yhdistelmä. Kauppa, jossa on 500 tuotetta ja keskimäärin 4 varianttia per tuote, tuottaa noin 2 000 rivin DataFramen.

Vaihtoehto B: yksi rivi per tuotekooste (paras katalogin yleiskatsaukseen)

1def summarize_products(products):
2    """Yksi rivi per tuote ja min/max-hinta varianttien mukaan."""
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

Vie CSV-, Excel- ja Google Sheets -muotoon

1# CSV-vienti (käytä utf-8-sig:tä, jotta Excel käsittelee erikoismerkit oikein)
2df.to_csv("shopify_products.csv", index=False, encoding="utf-8-sig")
3# Excel-vienti (vaatii openpyxl-kirjaston)
4df.to_excel("shopify_products.xlsx", index=False, engine="openpyxl")
5print("Viety tiedostoihin shopify_products.csv ja shopify_products.xlsx")

Google Sheetsiin voit käyttää gspread-kirjastoa service accountin kanssa, mutta rehellisesti sanottuna useimmissa tapauksissa CSV:n vienti ja lataus Google Driveen on nopeampaa ja yksinkertaisempaa.

Tuotantokelpoinen Python-scraping: rate limitit, uudelleenyritykset ja estojen kiertäminen

Perusskripti toimii pienten kauppojen kanssa hyvin. Mutta entä kun scrappaat yli 5 000 tuotteiden kauppaa tai useita kauppoja peräkkäin? Silloin ongelmat alkavat.

Ymmärrä Shopifyn rate limitit ja estokäyttäytyminen

Shopifyn julkisilla JSON-päätepisteillä ei ole virallisesti dokumentoituja rate limitejä (toisin kuin Admin API:n leaky bucket -mallissa), mutta käytännön testit osoittavat seuraavaa:

  • Turvallinen nopeus: noin 2 pyyntöä sekunnissa per kauppa
  • Lievä yläraja: noin 40 pyyntöä minuutissa ennen rajoitusten aktivoitumista
  • HTTP 429: "Too Many Requests" — tavallinen rate limit -vastaus
  • HTTP 430: Shopify-tyyppinen koodi, joka viittaa turvatason estoon, ei pelkkään rate limit -tilanteeseen
  • HTTP 403 tai CAPTCHA-uudelleenohjaus: Joissakin kaupoissa lisäsuojausta Cloudflaren kautta

Pilvi-infrastruktuurista tulevat pyynnöt (AWS Lambda, Google Cloud Run) laukaisevat estoja erityisen herkästi, koska näiden IP-alueiden väärinkäyttöaste on korkea.

Tekniikat luotettavaan Shopify-datan poimintaan

Tässä eteneminen mallista “toimii omalla koneella” malliin “toimii tuotannossa”:

TasoTekniikkaLuotettavuus
Perusrequests.get() + ?page=Kaatuu suurissa katalogeissa, voi tulla estoja
Keskitasorequests.Session() + ?limit=250 + time.sleep(1) + uudelleenyritys 429:lleToimii useimmissa kaupoissa
EdistynytAsynkroninen httpx + kiertävä User-Agent + eksponentiaalinen backoffTuotantotasoinen, skaalaa yli 10K tuotteeseen

Keskitaso (suositus useimmille käyttäjille):

1import requests
2from requests.adapters import HTTPAdapter
3from urllib3.util.retry import Retry
4def create_session():
5    """Luo requests-session automaattisella uudelleenyrityksellä."""
6    session = requests.Session()
7    retries = Retry(
8        total=5,
9        backoff_factor=1,  # sleep: 0,5 s, 1 s, 2 s, 4 s, 8 s
10        status_forcelist=[429, 430, 500, 502, 503, 504],
11        respect_retry_after_header=True
12    )
13    session.mount("https://", HTTPAdapter(max_retries=retries))
14    session.headers.update({
15        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
16    })
17    return session

Retry-asetukset käsittelevät 429-vastaukset automaattisesti eksponentiaalisella backoffilla. backoff_factor=1 tarkoittaa, että odotusajat ovat 0,5 s → 1 s → 2 s → 4 s → 8 s uudelleenyritysten välillä. Session uudelleenkäyttö (requests.Session()) tuo myös yhteyspoolauksen, mikä vähentää kuormaa, kun samaan domainiin tehdään useita pyyntöjä.

User-Agentin kierrätys: jos scrappaat useita kauppoja, vaihda 3–5 realistisen selaimen User-Agent-merkkijonon välillä. Kyse ei ole huijaamisesta, vaan siitä, ettet näytä botilta, joka lähettää joka kerta samat otsakkeet.

Täydellinen toimiva Python-skripti Shopify-datan poimintaan ja CSV-vientiin

Tässä on koko valmis skripti, jonka voit kopioida sellaisenaan. Se on noin 75 riviä varsinaista koodia (kommenttien lisäksi), ja olen testannut sitä Allbirdsilla (1 420 tuotetta), ColourPopilla (yli 2 000 tuotetta) sekä Zoologist Perfumesilla (pieni katalogi).

1import requests
2import pandas as pd
3import time
4import random
5from requests.adapters import HTTPAdapter
6from urllib3.util.retry import Retry
7def create_session():
8    """Luo session, jossa on uudelleenyritykset rate limitejä varten."""
9    session = requests.Session()
10    retries = Retry(
11        total=5,
12        backoff_factor=1,
13        status_forcelist=[429, 430, 500, 502, 503, 504],
14        respect_retry_after_header=True
15    )
16    session.mount("https://", HTTPAdapter(max_retries=retries))
17    session.headers.update({
18        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
19                      "AppleWebKit/537.36 (KHTML, like Gecko) "
20                      "Chrome/125.0.0.0 Safari/537.36"
21    })
22    return session
23def scrape_shopify(store_url, delay=1.0):
24    """Scrapeaa kaikki tuotteet Shopify-kaupasta /products.jsonin kautta."""
25    session = create_session()
26    all_products = []
27    page = 1
28    base_url = f"{store_url.rstrip('/')}/products.json"
29    while True:
30        print(f"  Sivu {page}...", end=" ")
31        resp = session.get(base_url, params={"limit": 250, "page": page}, timeout=30)
32        resp.raise_for_status()
33        products = resp.json().get("products", [])
34        if not products:
35            break
36        all_products.extend(products)
37        print(f"{len(products)} tuotetta (yhteensä: {len(all_products)})")
38        page += 1
39        time.sleep(delay + random.uniform(0, 0.5))
40    return all_products
41def flatten_to_variants(products):
42    """Litistää sisäkkäisen tuotteen JSONin yhdeksi riviksi per variantti."""
43    rows = []
44    for p in products:
45        base = {
46            "product_id": p["id"],
47            "title": p["title"],
48            "handle": p["handle"],
49            "vendor": p.get("vendor", ""),
50            "product_type": p.get("product_type", ""),
51            "tags": ", ".join(p.get("tags", [])),
52            "created_at": p.get("created_at", ""),
53            "updated_at": p.get("updated_at", ""),
54            "image_url": p["images"][0]["src"] if p.get("images") else "",
55        }
56        for v in p.get("variants", []):
57            row = {**base}
58            row["variant_id"] = v["id"]
59            row["variant_title"] = v.get("title", "")
60            row["sku"] = v.get("sku", "")
61            row["price"] = v.get("price", "")
62            row["compare_at_price"] = v.get("compare_at_price", "")
63            row["available"] = v.get("available", "")
64            rows.append(row)
65    return rows
66if __name__ == "__main__":
67    STORE_URL = "https://allbirds.com"  # Vaihda tähän kohdekauppasi
68    OUTPUT_CSV = "shopify_products.csv"
69    OUTPUT_EXCEL = "shopify_products.xlsx"
70    print(f"Scrapataan {STORE_URL}...")
71    products = scrape_shopify(STORE_URL)
72    print(f"\nScrapattuja tuotteita yhteensä: {len(products)}")
73    print("Muunnetaan varianttitason riveiksi...")
74    rows = flatten_to_variants(products)
75    df = pd.DataFrame(rows)
76    print(f"DataFrame: {df.shape[0]} riviä x {df.shape[1]} saraketta")
77    df.to_csv(OUTPUT_CSV, index=False, encoding="utf-8-sig")
78    df.to_excel(OUTPUT_EXCEL, index=False, engine="openpyxl")
79    print(f"\nViety tiedostoihin {OUTPUT_CSV} ja {OUTPUT_EXCEL}")

Aja se komennolla python scrape_shopify.py. Allbirdsilla tämä kestää noin 45 sekuntia ja tuottaa CSV:n, jossa on noin 5 000+ riviä (yksi per variantti). Pääte näyttää suunnilleen tältä:

1Scrapataan https://allbirds.com...
2  Sivu 1... 250 tuotetta (yhteensä: 250)
3  Sivu 2... 250 tuotetta (yhteensä: 500)
4  ...
5  Sivu 6... 170 tuotetta (yhteensä: 1420)
6Scrapattuja tuotteita yhteensä: 1420
7Muunnetaan varianttitason riveiksi...
8DataFrame: 5680 riviä x 14 saraketta
9Viety tiedostoihin shopify_products.csv ja shopify_products.xlsx

Ohita Python: scrapea Shopify kahdella klikkauksella Thunderbitillä (ei-koodillinen vaihtoehto)

Kaikki eivät halua asentaa Pythonia, korjailla import-virheitä tai ylläpitää scraping-skriptiä. Myyjälle, joka tarvitsee kilpailijahinnat huomisaamuun mennessä, Python on usein liioittelua.

Siksi rakennimme -ratkaisun — AI-verkkoscraperin Chrome-laajennuksena. Ei koodia, ei API-avaimia, ei ympäristön käyttöönottoa.

Miten Thunderbit scrapeaa Shopify-kauppoja

Thunderbitissä on erillinen Shopify Scraper -malli, joka on valmiiksi konfiguroitu Shopify-tuotesivuille. Asennat -laajennuksen, avaat Shopify-kaupan ja klikkaat “Scrape”. Malli poimii automaattisesti tuotteen nimet, kuvaukset, hinnat, varianttitiedot, kuvat ja toimittajatiedot.

Kaupoissa, joissa malli ei osu täysin kohdalleen (räätälöidyt teemat, poikkeava asettelu), Thunderbitin AI Suggest Fields -ominaisuus lukee sivun ja luo sarake-ehdotukset automaattisesti. Voit muokata niitä: nimetä sarakkeita uudelleen, lisätä kenttiä tai kirjoittaa ohjeita kuten “poimi vain tuotteet, joilla on compare_at_price asetettu”.

Muutama ominaisuus, joka vastaa suoraan Python-skriptin toimintoja:

  • Alisivujen scrapeaus: käy automaattisesti jokaisella tuotteen yksityiskohtasivulla ja rikastaa taulukkoa täydellisillä kuvauksilla, arvosteluilla tai varianttitiedoilla — sama asia, jonka Python-skripti tekee selaamalla sivuja, mutta ilman koodia.
  • Automaattinen sivutus: hoitaa klikkaamalla etenevän sivutuksen ja loputtoman scrollauksen ilman asetuksia.
  • Ajastettu scrapeaus: aseta toistuvat ajot (esim. “joka maanantai klo 9”) jatkuvaa hintaseurantaa varten — ilman cron-työtä tai palvelinta.
  • Ilmainen vienti CSV-, Excel-, Google Sheets-, Airtable- tai Notion-muotoon kaikilla suunnitelmilla.

Python-skripti vs. Thunderbit: rehellinen vertailu

TekijäPython-skriptiThunderbit (ei-koodia)
Käyttöönottoaika15–60 min (ympäristö + koodi)noin 2 min (Chrome-laajennuksen asennus)
KoodaustarveKyllä (Python)Ei lainkaan
MuokattavuusRajatonAI-ehdotetut kentät + omat promptit
Sivutuksen käsittelyKoodattava itseAutomaattinen
VientimuodotKoodattava itse (CSV/Excel)CSV, Excel, Google Sheets, Airtable, Notion (ilmainen)
Ajastetut ajotCron-työ + hostingSisäänrakennettu ajastin
Rate limit -käsittelyUudelleenyritykset/backoff koodattava itseHoidetaan automaattisesti
Paras käyttötapaKehittäjät, suuret dataputketLiiketoimintakäyttäjät, nopeat poiminnat, toistuva seuranta

Käytä Pythonia, kun tarvitset täyden hallinnan tai integrointia laajempaan dataputkeen. Käytä Thunderbitia, kun tarvitset dataa nopeasti etkä halua ylläpitää koodia. Syvempään katsaukseen , olemme kirjoittaneet erillisen oppaan aiheesta.

python-vs-thunderbit-comparison.webp

Vinkkejä ja parhaat käytännöt Shopify-kauppojen scrapeamiseen

Nämä pätevät riippumatta työkalusta:

  • Käytä aina ?limit=250 pyyntöjen minimoimiseksi. Oletusarvo 30 tuotetta per sivu tarkoittaa 8 kertaa enemmän pyyntöjä samaan dataan.
  • Kunnioita kauppaa: lisää 1–2 sekunnin viiveet pyyntöjen väliin. Palvelimen kuormittaminen nopeilla pyyntösarjoilla on huonoa käytäntöä ja lisää estoja.
  • Tarkista robots.txt ensin: Shopifyn oletus-robots.txt EI estä /products.json-päätepistettä. Osa kaupoista kuitenkin lisää omia sääntöjään, joten varmista asia ennen laajamittaista scrapea.
  • Tallenna raakadata ensin paikallisesti ja käsittele vasta sitten. Jos parsintalogiikka muuttuu myöhemmin, sinun ei tarvitse scrapeata uudelleen. Yksinkertainen json.dump(all_products, open("raw_data.json", "w")) ennen litistämistä säästää paljon vaivaa.
  • Poista duplikaatit product.id:n perusteella: sivutuksen reunatapaukset voivat joskus palauttaa samoja tuotteita sivurajoilla. Nopea df.drop_duplicates(subset=["product_id", "variant_id"]) korjaa tämän.
  • Muunna price float-tyypiksi ennen laskemista. Shopify palauttaa hinnat merkkijonoina ("185.00"), ei numeroina.
  • Seuraa päätepisteen muutoksia: vaikka /products.json on ollut vakaa vuosia, Shopify voisi teoriassa rajoittaa sitä. Jos scraperi saa yhtäkkiä 404-virheitä, tarkista ensin kauppa käsin.

Lisää tietoa kestävien scraperien rakentamisesta löydät oppaastamme .

Lainsäädännölliset ja eettiset näkökohdat Shopify-datan poiminnassa

Lyhyt osio, mutta tärkeä.

/products.json-päätepiste tarjoaa julkisesti saatavilla olevaa tuotetietoa — samaa tietoa, jonka kuka tahansa näkee kauppaa selatessaan. Shopifyn käyttöehdoissa puhutaan “automaattisista menetelmistä” palvelujen käyttöön, mutta tämä viittaa alustaan itseensä (hallintapaneeliin, kassaan), ei julkiseen verkkokauppadataan. Shopify-kohtaisia scraping-kanteita ei ole jätetty vireille huhtikuuhun 2026 mennessä.

Keskeiset oikeustapaukset tukevat julkisen datan scrapeamista: hiQ v. LinkedIn vahvisti, että julkisesti saatavilla olevan datan scrapeaminen ei riko CFAA:ta, ja Meta v. Bright Data (2024) linjasi, että käyttöehtorajoitukset koskevat vain tilanteita, joissa käyttäjä on kirjautuneena.

Parhaat käytännöt:

  • scrapea vain julkisesti saatavilla olevaa tuotetietoa
  • älä scrapea henkilö- tai asiakastietoja
  • kunnioita robots.txt:ää ja rate limitejä
  • noudata GDPR:ää/CCPA:ta, jos käsittelet henkilötietoja (tuotekatalogidata ei ole henkilötietoa)
  • identifioi itsesi selkeällä User-Agent-merkkijonolla
  • oman Shopify-kaupan scrapeaminen Admin API:n kautta on aina sallittua

Syvempään katsaukseen katso kirjoituksemme .

Yhteenveto ja tärkeimmät opit

Shopifyn julkinen /products.json-päätepiste tekee verkkokauppadatan poiminnasta poikkeuksellisen helppoa. Työnkulku on: lisää /products.json → hae Pythonilla → sivuta ?limit=250&page=-parametreilla → litistä pandasilla → vie CSV- tai Excel-muotoon.

Mitä tämä opas kattaa, mutta monet muut eivät:

  • Täydellinen kenttäviite: tiedät tarkalleen, mitä dataa on saatavilla (yli 40 kenttää tuotteissa, varianteissa ja kuvissa) ennen kuin kirjoitat ensimmäistäkään riviä koodia
  • Lisäpäätepisteet: /collections.json ja /meta.json antavat kategoriatason tiedot ja kaupan metatiedot, joita kilpailijaoppaat eivät yleensä käsittele
  • Tuotantokelpoiset tekniikat: session uudelleenkäyttö, eksponentiaalinen backoff, User-Agent-otsakkeet ja ?limit=250 todellisia rate limitejä varten
  • Oikea CSV-/Excel-vienti: pandasilla litistetty varianttitason data, ei pelkkää raakaa JSON-dumppia
  • Ei-koodillinen vaihtoehto: käyttäjille, jotka arvostavat nopeutta enemmän kuin koodin joustavuutta

Yksittäisiin tai toistuviin Shopify-datan noutoihin ilman koodia kokeile — Shopify Scraper -malli hoitaa kaiken sivutuksesta vientiin. Räätälöityihin dataputkiin tai useiden kauppojen laajamittaiseen scrapeamiseen tämän oppaan Python-skripti antaa täyden hallinnan.

Katso vaiheittaisia video-opastuksia varten tai tutustu oppaisiimme ja saadaksesi lisää vastaavia tekniikoita.

Kokeile Thunderbitia Shopify-scrapeamiseen

Usein kysytyt kysymykset

Voiko minkä tahansa Shopify-kaupan scrapeata products.json-päätepisteellä?

Useimmat Shopify-kaupat paljastavat tämän päätepisteen oletuksena — testeissäni noin 71 % palautti kelvollisen JSONin. Jotkin kaupat, joissa on räätälöityjä asetuksia tai lisäsuojauksia (Cloudflare, headless-ratkaisut), voivat palauttaa 404:n tai estää pyynnön. Nopea tarkistus: avaa {store-url}/products.json selaimessa. Jos näet JSONin, olet kunnossa.

Onko Shopify-kauppojen scrapeaminen laillista?

Julkinen tuotetieto (hinnat, nimet, kuvat, kuvaukset) on yleensä saatavilla, ja oikeustapaukset kuten hiQ v. LinkedIn tukevat julkisesti saatavilla olevan tiedon scrapeamista. Tarkista kuitenkin aina kyseisen kaupan käyttöehdot ja oman maasi lait. Älä scrapea henkilö- tai asiakastietoja, ja noudata rate limitejä.

Kuinka monta tuotetta Shopify-kaupasta voi scrapeata?

Kokonaismäärälle ei ole kovaa ylärajaa. Sivutus ?limit=250&page=-parametreilla antaa sinun hakea koko katalogin. Erittäin suurissa kaupoissa (25 000+ tuotetta) käytä session uudelleenkäyttöä ja viiveitä rate limit -ongelmien välttämiseksi. /meta.json-päätepiste kertoo tarkan tuotemäärän etukäteen, joten tiedät, montako sivua odottaa.

Mikä on ero products.json-päätepisteen ja Shopify Admin API:n välillä?

/products.json on julkinen päätepiste — ei tunnistautumista, vain luettavaa tuotetietoa, kaikkien saatavilla. Admin API vaatii kaupan omistajan tunnisteet ja tarjoaa tilaukset, varastomäärät, asiakastiedot sekä kirjoitusoikeudet. Jos tarvitset myyntidata tai todelliset varastomäärät, tarvitset Admin API -pääsyn (eli sinun täytyy olla kaupan omistaja tai saada lupa omistajalta).

Voinko scrapeata Shopifya ilman Pythonia?

Ehdottomasti. Työkalut kuten mahdollistavat Shopify-kauppojen scrapeamisen Chrome-laajennuksella ilman koodausta. Se hoitaa sivutuksen automaattisesti ja vie datan suoraan CSV-, Excel-, Google Sheets-, Airtable- tai Notion-muotoon. Kehittäjille, jotka suosivat muita kieliä, sama /products.json-päätepiste toimii myös JavaScriptillä, Rubylla, Go:lla — millä tahansa kielellä, joka osaa tehdä HTTP-pyyntöjä ja parsia JSONia.

Lisää luettavaa

Sisällysluettelo

Kokeile Thunderbitiä

Poimi liidejä ja muuta dataa vain 2 klikkauksella. AI:n voimalla.

Hanki Thunderbit Se on ilmaista
Poimi dataa AI:n avulla
Siirrä data helposti Google Sheetsiin, Airtableen tai Notioniin
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week