Wie man Shopify-Shops mit Python scrapen kann

Vereinfachen Sie die Extraktion von Shopify-Daten durch die Nutzung von products.json und effektiven Scraping-Methoden.
9 min lesen
How to Scrape Shopify blog image

Auf den ersten Blick stellen Shopify-Shops eine der schwierigsten Herausforderungen bei der Datenextraktion dar. Das unten abgebildete Produkt stellt ein typisches Shopify-Angebot dar. Die Daten sind so verschachtelt wie es nur geht.

<div class="site-box-content product-holder"><a href="/collections/ready-to-ship/products/the-eira-straight-leg" class="product-item style--one alt color--light   with-secondary-image " data-js-product-item="">

  <div class="box--product-image primary" style="padding-top: 120.00048000192001%"><img src="//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=640" alt="The Eira - Organic Ecru" srcset="//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=360 360w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=420 420w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=480 480w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=640 640w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=840 840w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=1080 1080w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=1280 1280w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=1540 1540w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=1860 1860w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=2100 2100w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=2460 2460w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-01_91c15dbe-7412-47b6-8f76-bdb434199203.jpg?v=1731517834&amp;width=2820 2820w" sizes="(max-width: 768px) 50vw, (max-width: 1024px) and (orientation: portrait) 50vw, 25vw " loading="lazy" class="lazy lazyloaded" data-ratio="0.8" width="3200" height="4000" onload="this.classList.add('lazyloaded')"><span class="lazy-preloader " aria-hidden="true"><svg class="circular-loader" viewBox="25 25 50 50"><circle class="loader-path" cx="50" cy="50" r="20" fill="none" stroke-width="4"></circle></svg></span></div><div class="box--product-image secondary" style="padding-top: 120.00048000192001%"><img src="//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=640" alt="The Eira - Organic Ecru" srcset="//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=360 360w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=420 420w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=480 480w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=640 640w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=840 840w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=1080 1080w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=1280 1280w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=1540 1540w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=1860 1860w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=2100 2100w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=2460 2460w,//hiutdenim.co.uk/cdn/shop/files/Hiut-EiraEcru-02.jpg?v=1731517834&amp;width=2820 2820w" sizes="(max-width: 768px) 50vw, (max-width: 1024px) and (orientation: portrait) 50vw, 25vw " loading="lazy" class="lazy lazyloaded" data-ratio="0.8" width="3200" height="4000" onload="this.classList.add('lazyloaded')"></div><div class="caption">

    <div>
      <span class="title"><span class="underline-animation">The Eira - Organic Ecru</span></span>
      <span class="price text-size--smaller"><span style="display:flex;flex-direction:row">$285.00</span></span>

    </div><quick-view-product class="quick-add-to-cart">
          <div class="quick-add-to-cart-button">
            <button class="product__add-to-cart" data-href="/products/the-eira-straight-leg" tabindex="-1">
              <span class="visually-hidden">Add to cart</span>
              <span class="add-to-cart__text" style="height:26px" role="img"><svg width="22" height="26" viewBox="0 0 22 26" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M6.57058 6.64336H4.49919C3.0296 6.64336 1.81555 7.78963 1.7323 9.25573L1.00454 22.0739C0.914352 23.6625 2.17916 25 3.77143 25H18.2286C19.8208 25 21.0856 23.6625 20.9955 22.0739L20.2677 9.25573C20.1844 7.78962 18.9704 6.64336 17.5008 6.64336H15.4294M6.57058 6.64336H15.4294M6.57058 6.64336V4.69231C6.57058 2.6531 8.22494 1 10.2657 1H11.7343C13.775 1 15.4294 2.6531 15.4294 4.69231V6.64336" stroke="var(--main-text)" style="fill:none!important" stroke-width="1.75"></path><path d="M10.0801 12H12.0801V20H10.0801V12Z" fill="var(--main-text)" style="stroke:none!important"></path><path d="M15.0801 15V17L7.08008 17L7.08008 15L15.0801 15Z" fill="var(--main-text)" style="stroke:none!important"></path></svg></span><span class="lazy-preloader add-to-cart__preloader" aria-hidden="true"><svg class="circular-loader" viewBox="25 25 50 50"><circle class="loader-path" cx="50" cy="50" r="20" fill="none" stroke-width="4"></circle></svg></span></button>
          </div>
        </quick-view-product></div><div class="product-badges-holder"></div></a></div>

Es ist nicht unmöglich, Daten aus dem obigen HTML zu extrahieren, aber es gibt einen einfacheren Weg.

Shopify Landing Pages

Die Landing Page https://hiutdenim.co.uk/ enthält zwar einige Produktinformationen, aber sie sind relativ begrenzt. Scrollen Sie weit genug nach unten, und Sie werden fündig.

Titelseite eines Shopify-Shops

Auf den ersten Blick sieht es so aus, als müssten Sie jeden Link zu jedem Bereich scrapen und anschließend all diese verschiedenen Seiten abrufen und analysieren. Shopify-Shops folgen aufgrund des einzigartigen Seitenlayouts nicht den traditionellen Methoden des eCommerce-Scrapings. Es gibt jedoch einen anderen Weg.

Shopify JSON-Seiten

Sie haben die Überschrift richtig gelesen. Wir können alle Produkte des Shops standardmäßig als JSON-Objekt abrufen. Wir brauchen nicht einmal BeautifulSoup oder Selenium.

Wir müssen lediglich /products.json zu unserer URL hinzufügen. Jede Shopify-Website basiert auf einer products.json-Datei.

Shopify JSON-Seite

Wenn wir diese Inhalte abrufen können (was wir können), können wir alle Daten erhalten, die wir uns wünschen. Sobald wir sie haben, müssen wir nur noch entscheiden, welche Daten wir behalten wollen. Sie können dies für die Website, die wir hier verwenden, überprüfen.

Scraping Shopify in Python

Da wir nun wissen, wonach wir suchen, wird diese gewaltige Aufgabe weit weniger schwierig. Da wir es nur mit JSON-Daten zu tun haben, müssen wir nur eine Abhängigkeit installieren: Python Requests.

pip install requests

Einzelne Funktionen

Werfen wir einen Blick auf die einzelnen Codestücke. Wir haben drei separate Teile, aus denen der Scraper besteht.

Das ist unsere wichtigste Funktion. Sie führt die eigentliche Scraping-Logik aus.

def scrape_shopify(url, retries=2):
    """scrape a shopify store"""
    json_url = f"{url}products.json"
    items = []
    success = False
    while not success and retries > 0:
        response = requests.get(json_url)
        try:
            response.raise_for_status()
            products = response.json()["products"]
            for product in products:
                product_data = {
                    "title": product["title"],
                    "tags": product["tags"],
                    "id": product["id"],
                    "variants": product["variants"],
                    "images": product["images"],
                    "options": product["options"]
                }
                items.append(product_data)            
            success = True
        except requests.RequestException as e:
            print(f"Error during request: {e}, failed to get {json_url}")
        except KeyError as key_error:
            print(f"Failed to parse json: {key_error}")
        except json.JSONDecodeError as e:
            print(f"json error: {e}")
        except Exception as e:
            print(f"Unforeseen error: {e}")
        retries-=1
        print(f"Retries left: ", retries)
    return items
  • Zunächst fügen wir products.json an unsere URL an: json_url = f"{url}products.json".
  • Wir initialisieren ein leeres Array, items. Beim Scrapen unserer Elemente werden wir sie an dieses Array anhängen. Sobald das Scrapen beendet ist, geben wir das Array der geparsten Elemente zurück.
  • Solange wir eine gute Antwort erhalten, rufen wir die Taste "Produkte" auf, um alle unsere Produkte zu erhalten.
  • Wir ziehen verschiedene Daten von jedem Produkt, um ein Diktat, product_data, zu erstellen.
  • product_data wird an das Array angehängt.
  • Dieser Vorgang wird so lange wiederholt, bis alle Produkte auf der Seite analysiert wurden.

Wir haben jetzt eine Funktion, die unseren Scrape durchführt und ein Array von Produkten zurückgibt. Jetzt brauchen wir eine Funktion, die dieses Array von Produkten nimmt und in eine Datei schreibt. Wir könnten hier CSV verwenden, aber diese Struktur wird ziemlich verschachtelt, also werden wir JSON verwenden. Es unterstützt flexiblere Datenstrukturen für die spätere Verwendung und Analyse.

def json2file(json_data, filename):
    """save json data to a file"""
    try:
        with open(filename, "w", encoding="utf-8") as file:
            json.dump(json_data, file, indent=4)
            print(f"Data successfully saved: {filename}")
    except Exception as e:
        print(f"failed to write json data to {filename}, ERROR: {e}")

Das ist der eigentliche Code, den wir verwenden werden. Jetzt erstellen wir einen Hauptblock, um unseren Scraper auszuführen.

if __name__ == "__main__":
    shop_url = "https://hiutdenim.co.uk/"
    items = scrape_shopify(shop_url)

    json2file(items, "output.json")

Alles zusammenfügen

Wenn wir alles zusammenfügen, sieht unser Scraper wie folgt aus. Was wie ein kompliziertes Parsing-Projekt aussah, ist jetzt ein voll funktionsfähiger Scraper, der nur etwa 50 Zeilen Code benötigt.

import requests
import json

def json2file(json_data, filename):
    """save json data to a file"""
    try:
        with open(filename, "w", encoding="utf-8") as file:
            json.dump(json_data, file, indent=4)
            print(f"Data successfully saved: {filename}")
    except Exception as e:
        print(f"failed to write json data to {filename}, ERROR: {e}")

def scrape_shopify(url, retries=2):
    """scrape a shopify store"""
    json_url = f"{url}products.json"
    items = []
    success = False
    while not success and retries > 0:
        response = requests.get(json_url)
        try:
            response.raise_for_status()
            products = response.json()["products"]
            for product in products:
                product_data = {
                    "title": product["title"],
                    "tags": product["tags"],
                    "id": product["id"],
                    "variants": product["variants"],
                    "images": product["images"],
                    "options": product["options"]
                }
                items.append(product_data)            
            success = True
        except requests.RequestException as e:
            print(f"Error during request: {e}, failed to get {json_url}")
        except KeyError as key_error:
            print(f"Failed to parse json: {key_error}")
        except json.JSONDecodeError as e:
            print(f"json error: {e}")
        except Exception as e:
            print(f"Unforeseen error: {e}")
        retries-=1
    return items


if __name__ == "__main__":
    shop_url = "https://hiutdenim.co.uk/"
    items = scrape_shopify(shop_url)

    json2file(items, "output.json")

Die Rückkehrdaten

Unsere Daten werden in einem Array von JSON-Objekten zurückgegeben. Jedes Produkt enthält eine Liste von Varianten und Bildern. Diese wären in einer CSV-Datei nur schwer darstellbar. Der Ausschnitt, den Sie unten sehen, ist ein einzelnes Produkt aus unserem Scrape.

{
        "title": "The Valerie - Organic Denim",
        "tags": [
            "The Valerie",
            "Women"
        ],
        "id": 14874183401848,
        "variants": [
            {
                "id": 54902462808440,
                "title": "UK10-29 / 30",
                "option1": "UK10-29",
                "option2": "30",
                "option3": null,
                "sku": null,
                "requires_shipping": true,
                "taxable": true,
                "featured_image": null,
                "available": true,
                "price": "220.00",
                "grams": 0,
                "compare_at_price": null,
                "position": 1,
                "product_id": 14874183401848,
                "created_at": "2025-01-21T14:04:58+00:00",
                "updated_at": "2025-02-12T17:17:54+00:00"
            },
            {
                "id": 54902462939512,
                "title": "UK12-30 / 32",
                "option1": "UK12-30",
                "option2": "32",
                "option3": null,
                "sku": null,
                "requires_shipping": true,
                "taxable": true,
                "featured_image": null,
                "available": true,
                "price": "220.00",
                "grams": 0,
                "compare_at_price": null,
                "position": 2,
                "product_id": 14874183401848,
                "created_at": "2025-01-21T14:04:58+00:00",
                "updated_at": "2025-02-12T17:17:54+00:00"
            },
            {
                "id": 54902463070584,
                "title": "UK14-32 / 28",
                "option1": "UK14-32",
                "option2": "28",
                "option3": null,
                "sku": null,
                "requires_shipping": true,
                "taxable": true,
                "featured_image": null,
                "available": true,
                "price": "220.00",
                "grams": 0,
                "compare_at_price": null,
                "position": 3,
                "product_id": 14874183401848,
                "created_at": "2025-01-21T14:04:58+00:00",
                "updated_at": "2025-02-12T17:17:54+00:00"
            },
            {
                "id": 54902463496568,
                "title": "UK18-36 / 30",
                "option1": "UK18-36",
                "option2": "30",
                "option3": null,
                "sku": null,
                "requires_shipping": true,
                "taxable": true,
                "featured_image": null,
                "available": true,
                "price": "220.00",
                "grams": 0,
                "compare_at_price": null,
                "position": 4,
                "product_id": 14874183401848,
                "created_at": "2025-01-21T14:04:58+00:00",
                "updated_at": "2025-02-12T17:17:54+00:00"
            }
        ],
        "images": [
            {
                "id": 31828166443078,
                "created_at": "2024-06-17T12:05:49+01:00",
                "position": 1,
                "updated_at": "2024-06-17T12:05:50+01:00",
                "product_id": 14874183401848,
                "variant_ids": [],
                "src": "https://cdn.shopify.com/s/files/1/0065/4242/files/HDC_0723_JapanInd_Valerie_45_3_c547ba8a-681b-4486-8cd7-884000e43302.jpg?v=1718622350",
                "width": 4000,
                "height": 4000
            },
            {
                "id": 31828166541382,
                "created_at": "2024-06-17T12:05:49+01:00",
                "position": 2,
                "updated_at": "2024-06-17T12:05:51+01:00",
                "product_id": 14874183401848,
                "variant_ids": [],
                "src": "https://cdn.shopify.com/s/files/1/0065/4242/files/HDC_0723_JapanInd_Valerie_Back_2_5909adb3-c2ab-4810-8b66-a486e8d827a8.jpg?v=1718622351",
                "width": 4000,
                "height": 4000
            },
            {
                "id": 31828166508614,
                "created_at": "2024-06-17T12:05:49+01:00",
                "position": 3,
                "updated_at": "2024-06-17T12:05:51+01:00",
                "product_id": 14874183401848,
                "variant_ids": [],
                "src": "https://cdn.shopify.com/s/files/1/0065/4242/files/HDC_0723_JapanInd_Valerie_Front_3_4316907a-9fd8-4649-894c-4028877370e1.jpg?v=1718622351",
                "width": 4000,
                "height": 4000
            },
            {
                "id": 31828166475846,
                "created_at": "2024-06-17T12:05:49+01:00",
                "position": 4,
                "updated_at": "2024-06-17T12:05:51+01:00",
                "product_id": 14874183401848,
                "variant_ids": [],
                "src": "https://cdn.shopify.com/s/files/1/0065/4242/files/HDC_0723_JapanInd_Valerie_Side_2_ea21477b-c1ba-4c8a-b75e-75c6427b4977.jpg?v=1718622351",
                "width": 4000,
                "height": 4000
            }
        ],
        "options": [
            {
                "name": "Waist",
                "position": 1,
                "values": [
                    "UK10-29",
                    "UK12-30",
                    "UK14-32",
                    "UK18-36"
                ]
            },
            {
                "name": "Leg Length",
                "position": 2,
                "values": [
                    "30",
                    "32",
                    "28"
                ]
            }
        ]
    },

Fortgeschrittene Techniken

Die Welt ist nicht perfekt, und es ist möglich, dass Sie mit dem obigen Scraper auf Schwierigkeiten stoßen. Vielleicht müssen Sie mehrere Seiten scrapen, oder Ihr Scraper wird manchmal blockiert.

Paginierung

Wenn Sie größere Shops durchsuchen, stoßen Sie oft auf Shops mit paginierten Ergebnissen. Um die Paginierung zu handhaben, benötigen wir zunächst die maximale Anzahl der Ergebnisse pro Seite. Wir können den folgenden Abfrageparameter hinzufügen: page=, um unsere Ergebnisseiten zu steuern.

Wir können unsere Scraping-Funktion leicht abändern, um eine Seite in der URL und die Seitenzahl zu übernehmen.

def scrape_shopify(url, retries=2):
    """scrape a shopify store"""
    json_url = f"{url}products.json"

Dann können wir unseren Hauptteil anpassen, um diese Änderungen widerzuspiegeln.

if __name__ == "__main__":
    shop_url = "https://www.allbirds.com/"
    PAGES = 3

    for page in range(PAGES):
        items = scrape_shopify(shop_url, page=page+1)

        json2file(items, f"page{page}output.json")

Proxy-Integration

Manchmal müssen Sie einen Proxy-Dienst verwenden, um zu verhindern, dass Ihr Scraper blockiert wird. Mit unseren Shopify-Proxys ist es so einfach wie das Erstellen einer URL mit Ihren Anmeldedaten.

PROXY_URL = "http://brd-customer-<YOUR-USERNAME>-zone-<YOUR-ZONE>:<YOUR-PASSWORD>@brd.superproxy.io:33335"
proxies = {
    "http": PROXY_URL,
    "https": PROXY_URL
}
response = requests.get(json_url, proxies=proxies, verify="brd.crt")

Andere Lösungen von Bright Data

Bright Data bietet leistungsstarke, schlüsselfertige Alternativen, die es überflüssig machen, komplexe Scraper von Grund auf zu erstellen. Nutzen Sie unseren vollständig optimierten Shopify Scraper für eine nahtlose Datenextraktion oder greifen Sie auf unsere umfangreiche Bibliothek mit vorerfassten Datensätzen zu, die in verschiedenen Formaten verfügbar sind, um Ihre Projekte sofort zu starten.

Schlussfolgerung

Das Scraping eines Shopify-Shops muss keine unmögliche Aufgabe sein. Indem Sie einfach die API mit products.json nutzen, können Sie schnell eine große Menge an detaillierten Produktdaten sammeln. Sie müssen nicht einmal einen HTML-Parser verwenden! Wenn Sie möchten, können Sie die Entwicklungszeit mit einem unserer vorgefertigten Scraper verkürzen, oder Sie können sofort mit unseren Datensätzen arbeiten.

Alle unsere Produkte werden mit einer kostenlosen Testversion geliefert, melden Sie sich jetzt an!