Scraping magasins Carrefour

Hola todos,

Je suis sur un sujet de récupération d’un listing des magasins Carrefour + le d’infos possibles sur chaque magasin.

On à une map sur le site qui recense tous les magasins et dans les requêtes j’ai toutes les infos qui m’intéressent :

A savoir :

  • store id
  • name
  • address
  • contact
  • user_properties

Malheureusement, je ne trouve pas de moyen que tous les magasins soient affichés en requête dans le navigateur pour extraire ça.

Avez-vous des idées à me suggérer sur la manière de procéder ?

Merci !

Salut,

check cette requête :

curl 'https://api.woosmap.com/stores/search?key=woos-26fe76aa-ff24-3255-b25b-e1bde7b7a683&lat=45.371420&lng=4.3727410&max_distance=5000&stores_by_page=40&limit=40&page=1&query=(user.banner%3A%22CARREFOUR%22%20OR%20(user.banner%3A%22CARREFOUR%20MARKET%22%20OR%20user.banner%3A%22MARKET%22)%20OR%20user.banner%3A%22CARREFOUR%20CONTACT%22%20OR%20user.banner%3A%22CARREFOUR%20CITY%22%20OR%20user.banner%3A%22CARREFOUR%20EXPRESS%22%20OR%20user.banner%3A%22CARREFOUR%20MONTAGNE%22%20OR%20user.banner%3A%22BON%20APP%22)' \
  -H 'accept: */*' \
  -H 'accept-language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' \
  -H 'cache-control: no-cache' \
  -H 'origin: https://www.carrefour.fr' \
  -H 'pragma: no-cache' \
  -H 'priority: u=1, i' \
  -H 'referer: https://www.carrefour.fr/' \
  -H 'sec-ch-ua: "Not A(Brand";v="8", "Chromium";v="132", "Google Chrome";v="132"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: cross-site' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36'

En modifiant les paramètres (notamment stores_by_page=40, limit=40, max_distance=5000 ou alors le page=1) tu devrais pouvoir tout récupérer.

Salut Paul,

Yes j’ai déjà pensé à cette solution + essayé mais je n’ai pas l’accès à l’api :confused:

Capture d’écran 2025-01-31 à 17.16.44

Il faut très probablement ajouter un header referer correct à la requête, on ne peut pas y accéder en cliquant juste sur le lien.

Edit : je viens de capter que c’est noté dans le detail de la réponse en plus
image

Ok, je galère un peu dès lors que ça devient un peu plus technique, je vais essayer de me débrouiller avec tes réponses + du GPT, merci!

J’arrive à générer du resultat sur Postman mais pas tous les résultats.

Le pb > je ne peux afficher que 300 stores par page mais il n’y a qu’une page.

J’essaye de jouer avec les coordonnées géo pour couvrir toute la france mais ça semble pas fonctionner.

Tu as une idée pour que je puisse avancer ?

Merci

Cool. Modifie la pagination maintenant : page=2 et ainsi de suite !
Pour les coordonnées, je prendrais celles du centre de la France et je jouerai sur le max_distance pour étendre la zone de recherche.

Parfait j’ai réussi.

Et au passage gagné un peu de compétence sur le sujet de l’appel en requêtes, merci Paul :call_me_hand:

1 « J'aime »

Merci pour vos tips !

Je complète avec ce que j’ai appris en faisant l’exercice moi-même aujourd’hui.

On récupère la liste des magasins depuis cette page : https://www.carrefour.fr/magasin

Quand on clique sur un magasin, on obtient un truc comme ça:

Dans la query correspondante, on peut jouer avec deux paramètres :

  1. La max_distance. Perso je l’ai mise à 5000000
  2. Le « stores_per_page ». On peut l’augmenter jusqu’à 300.

Et pour extraire automatiquement avec du Python (code généré par Mistral):

import requests
import csv

# Define the API endpoint and parameters
url = "https://api.woosmap.com/stores/search"
api_key = "woos-26fe76aa-ff24-3255-b25b-e1bde7b7a683"
latitude = 47.221201
longitude = 2.0652771
max_distance = 5000000  # Use the original distance
stores_per_page = 300  # Use the original limit

# Define the query parameters
query = (
    "(user.banner:\"CARREFOUR\" OR "
    "(user.banner:\"CARREFOUR MARKET\" OR user.banner:\"MARKET\") OR "
    "user.banner:\"CARREFOUR CONTACT\" OR "
    "user.banner:\"CARREFOUR CITY\" OR "
    "user.banner:\"CARREFOUR EXPRESS\" OR "
    "user.banner:\"CARREFOUR MONTAGNE\" OR "
    "user.banner:\"BON APP\")"
)

# Function to fetch data from the API
def fetch_data(page):
    params = {
        "key": api_key,
        "lat": latitude,
        "lng": longitude,
        "max_distance": max_distance,
        "stores_by_page": stores_per_page,
        "limit": stores_per_page,
        "page": page,
        "query": query
    }

    headers = {
        "accept": "*/*",
        "referer": "https://www.carrefour.fr/"
    }

    response = requests.get(url, headers=headers, params=params)
    if response.status_code == 200:
        return response.json()
    else:
        print(f"Failed to fetch data: {response.status_code}")
        print(f"Response: {response.text}")
        return None

# Function to extract relevant data and save to CSV
def save_to_csv(all_stores, filename="carrefour_stores.csv"):
    if not all_stores:
        return

    # Write to CSV
    keys = all_stores[0].keys()
    with open(filename, "w", newline="", encoding="utf-8") as output_file:
        dict_writer = csv.DictWriter(output_file, fieldnames=keys)
        dict_writer.writeheader()
        dict_writer.writerows(all_stores)
    print(f"Data saved to {filename}")

# Fetch the first page to determine the total number of pages
first_page_data = fetch_data(1)
if not first_page_data:
    print("Failed to fetch the first page data.")
else:
    total_pages = first_page_data.get("pagination", {}).get("pageCount", 1)
    print(f"Total pages to fetch: {total_pages}")

    # Fetch data for all pages and consolidate into one list
    all_stores = []
    for page in range(1, total_pages + 1):
        data = fetch_data(page)
        if data:
            for feature in data.get("features", []):
                properties = feature.get("properties", {})
                store_data = {
                    "store_id": properties.get("store_id"),
                    "name": properties.get("name"),
                    "phone": properties.get("contact", {}).get("phone"),
                    "website": properties.get("contact", {}).get("website"),
                    "address": properties.get("address", {}).get("lines", [""])[0],
                    "city": properties.get("address", {}).get("city"),
                    "zipcode": properties.get("address", {}).get("zipcode"),
                    "banner": properties.get("user_properties", {}).get("banner"),
                    "latitude": feature.get("geometry", {}).get("coordinates", [None, None])[1],
                    "longitude": feature.get("geometry", {}).get("coordinates", [None, None])[0]
                }
                all_stores.append(store_data)

    # Save all stores to a single CSV file
    save_to_csv(all_stores)

A la fin, il suffit de vérifier qu’on a tout en comparant avec l’annuaire « classique »:
https://www.carrefour.fr/magasin/liste

1 « J'aime »