Retour au blog
Guides
Raluca Penciuc3 mars 202310 min de lecture

Comment extraire des données du site Idealista : guide complet (mise à jour 2023)

Comment extraire des données du site Idealista : guide complet (mise à jour 2023)

Prérequis

Avant de commencer, assurons-nous de disposer des outils nécessaires.

Tout d'abord, téléchargez et installez Node.js depuis le site officiel, en veillant à utiliser la version à support à long terme (LTS). Cela installera également automatiquement Node Package Manager (NPM), que nous utiliserons pour installer d'autres dépendances.

Pour ce tutoriel, nous utiliserons Visual Studio Code comme environnement de développement intégré (IDE), mais vous pouvez utiliser n'importe quel autre IDE de votre choix. Créez un nouveau dossier pour votre projet, ouvrez le terminal et exécutez la commande suivante pour configurer un nouveau projet Node.js :

npm init -y

Cela créera un fichier package.json dans le répertoire de votre projet, qui stockera des informations sur votre projet et ses dépendances.

Ensuite, nous devons installer TypeScript et les définitions de types pour Node.js. TypeScript offre un typage statique facultatif qui aide à prévenir les erreurs dans le code. Pour ce faire, exécutez dans le terminal :

npm install typescript @types/node --save-dev

Vous pouvez vérifier l'installation en exécutant :

npx tsc --version

TypeScript utilise un fichier de configuration appelé tsconfig.json pour stocker les options du compilateur et d'autres paramètres. Pour créer ce fichier dans votre projet, exécutez la commande suivante :

npx tsc -init

Assurez-vous que la valeur de « outDir » est définie sur « dist ». De cette façon, nous séparerons les fichiers TypeScript des fichiers compilés. Vous trouverez plus d'informations sur ce fichier et ses propriétés dans la documentation officielle de TypeScript.

Maintenant, créez un répertoire « src » dans votre projet, ainsi qu'un nouveau fichier « index.ts ». C'est là que nous conserverons le code de scraping. Pour exécuter du code TypeScript, vous devez d'abord le compiler ; afin de ne pas oublier cette étape supplémentaire, nous pouvons utiliser une commande personnalisée.

Rendez-vous dans le fichier « package.json » et modifiez la section « scripts » comme suit :

"scripts": {

    "test": "npx tsc && node dist/index.js"

}

Ainsi, lorsque vous exécuterez le script, il vous suffira de taper « npm run test » dans votre terminal.

Enfin, pour extraire les données du site web, nous utiliserons Puppeteer, une bibliothèque de navigateur sans interface graphique pour Node.js qui vous permet de contrôler un navigateur web et d’interagir avec des sites web par programmation. Pour l’installer, exécutez cette commande dans le terminal :

npm install puppeteer

C'est fortement recommandé si vous souhaitez vous assurer de l'exhaustivité de vos données, car de nombreux sites web contiennent aujourd'hui du contenu généré dynamiquement. Si vous êtes curieux, vous pouvez consulter la documentation de Puppeteer avant de continuer pour découvrir toutes ses capacités.

Localisation des données

Maintenant que votre environnement est configuré, nous pouvons commencer à nous intéresser à l'extraction des données. Pour cet article, j'ai choisi d'extraire la liste des maisons et appartements disponibles dans une région de Tolède, en Espagne : https://www.idealista.com/pt/alquiler-viviendas/toledo/buenavista-valparaiso-la-legua/.

Nous allons extraire les données suivantes de chaque annonce sur la page :

  • l'URL ;
  • le titre ;
  • le prix ;
  • les détails (nombre de pièces, superficie, etc.) ;
  • la description

Vous pouvez voir toutes ces informations mises en évidence sur la capture d'écran ci-dessous :

Idealista property listings page with browser devtools highlighting HTML for title, price, and description fields

En ouvrant les outils de développement sur chacun de ces éléments, vous pourrez repérer les sélecteurs CSS que nous utiliserons pour localiser les éléments HTML. Si vous débutez dans le fonctionnement des sélecteurs CSS, n'hésitez pas à consulter ce guide pour débutants.

Extraction des données

Pour commencer à écrire notre script, vérifions que l'installation de Puppeteer s'est bien déroulée :

import puppeteer from 'puppeteer';

async function scrapeIdealistaData(idealista_url: string): Promise<void> {

    

    // Launch Puppeteer

    const browser = await puppeteer.launch({

        headless: false,

    	  args: ['--start-maximized'],

    	  defaultViewport: null

    })

    // Create a new page

    const page = await browser.newPage()

    // Navigate to the target URL

    await page.goto(idealista_url)

    // Close the browser

    await browser.close()

}

scrapeIdealistaData("https://www.idealista.com/pt/alquiler-viviendas/toledo/buenavista-valparaiso-la-legua/")

Ici, nous ouvrons une fenêtre de navigateur, créons une nouvelle page, accédons à notre URL cible, puis fermons le navigateur. Par souci de simplicité et pour faciliter le débogage visuel, j'ouvre la fenêtre de navigateur en mode non headless et en plein écran.

Comme toutes les annonces ont la même structure et les mêmes données, nous pouvons extraire toutes les informations de la liste complète des propriétés dans notre algorithme. Après avoir exécuté le script, nous pouvons parcourir tous les résultats et les compiler en une seule liste.

Pour obtenir l'URL de toutes les propriétés, nous localisons les éléments d'ancrage ayant la classe « item-link ». Ensuite, nous convertissons le résultat en un tableau JavaScript et mappons chaque élément à la valeur de l'attribut « href ».

// Extract listings location

const listings_location = await page.evaluate(() => {

    const locations = document.querySelectorAll('a.item-link')

    const locations_array = Array.from(locations)

    return locations ? locations_array.map(a => a.getAttribute('href')) : []

})

console.log(listings_location.length, listings_location)

Ensuite, pour les titres, nous pouvons utiliser le même élément d'ancrage, sauf que cette fois-ci, nous allons extraire son attribut « title ».

// Extract listings titles

const listings_title = await page.evaluate(() => {

    const titles = document.querySelectorAll('a.item-link')

    const titles_array = Array.from(titles)

    return titles ? titles_array.map(t => t.getAttribute('title')) : []

})

console.log(listings_title.length, listings_title)

Pour les prix, nous localisons les éléments « span » possédant deux noms de classe : « item-price » et « h2-simulated ». Il est important d’identifier les éléments de la manière la plus unique possible, afin de ne pas altérer votre résultat final. Ils doivent également être convertis en tableau, puis mappés à leur contenu textuel.

// Extract listings prices

const listings_price = await page.evaluate(() => {

    const prices = document.querySelectorAll('span.item-price.h2-simulated')

    const prices_array = Array.from(prices)

    return prices ? prices_array.map(p => p.textContent) : []

})

console.log(listings_price.length, listings_price)

Nous appliquons le même principe pour les détails des propriétés, en analysant les éléments « div » portant le nom de classe « item-detail-char ».

// Extract listings details

const listings_detail = await page.evaluate(() => {

    const details = document.querySelectorAll('div.item-detail-char')

    const details_array = Array.from(details)

    return details ? details_array.map(d => d.textContent) : []

})

console.log(listings_detail.length, listings_detail)

Et enfin, la description des propriétés. Ici, nous appliquons une expression régulière supplémentaire pour supprimer tous les caractères de nouvelle ligne inutiles.

// Extract listings descriptions

const listings_description = await page.evaluate(() => {

    const descriptions = document.querySelectorAll('div.item-description.description')

    const descriptions_array = Array.from(descriptions)

    return descriptions ? descriptions_array.map(d => d.textContent.replace(/(\r\n|\n|\r)/gm, "")) : []

})

console.log(listings_description.length, listings_description)

Vous devriez maintenant disposer de 5 listes, une pour chaque donnée que nous avons extraite. Comme je l’ai mentionné précédemment, nous devons les regrouper en une seule. De cette manière, les informations que nous avons recueillies seront beaucoup plus faciles à traiter par la suite.

// Group the lists

const listings = []

for (let i = 0; i < listings_location.length; i++) {

    listings.push({

        url: listings_location[i],

        title: listings_title[i],

        price: listings_price[i],

        details: listings_detail[i],

        description: listings_description[i]

    })

}

console.log(listings.length, listings)

Le résultat final devrait ressembler à ceci :

[

  {

    url: '/pt/inmueble/99004556/',

    title: 'Apartamento em ronda de Buenavista, Buenavista-Valparaíso-La Legua, Toledo',

    price: '750€/mês',

    details: '\n3 quart.\n115 m² área bruta\n2º andar exterior com elevador\nOntem \n',

    description: 'Apartamento para alugar na Ronda Buenavista, em Toledo.Três quartos e duas casas de banho, sala, cozinha, terraço, garagem e arrecadação....'

  },

  {

    url: '/pt/inmueble/100106615/',

    title: 'Moradia em banda em Buenavista-Valparaíso-La Legua, Toledo',

    price: '1.000€/mês',

    details: '\n4 quart.\n195 m² área bruta\nOntem \n',

    description: 'Magnífica casa geminada para alugar com 3 andares, 4 quartos aconchegantes, 3 banheiros, sala ampla e luminosa, cozinha totalmente equipa...'

  },

  {

    url: '/pt/inmueble/100099977/',

    title: 'Moradia em banda em calle Francisco Ortiz, Buenavista-Valparaíso-La Legua, Toledo',

    price: '800€/mês',

    details: '\n3 quart.\n118 m² área bruta\n10 jan \n',

    description: 'O REMAX GRUPO FV aluga uma casa mobiliada na Calle Francisco Ortiz, em Toledo.Moradia geminada com 148 metros construídos, distribuídos...'

  },

  {

    url: '/pt/inmueble/100094142/',

    title: 'Apartamento em Buenavista-Valparaíso-La Legua, Toledo',

    price: '850€/mês',

    details: '\n4 quart.\n110 m² área bruta\n1º andar exterior com elevador\n10 jan \n',

    description: 'Apartamento muito espaçoso para alugar sem móveis, cozinha totalmente equipada.Composto por 4 quartos, 1 casa de banho, terraço.Calefaç...'

  }

]

Contourner la détection des bots

Si vous exécutez votre script au moins deux fois au cours de ce tutoriel, vous avez peut-être déjà remarqué cette page agaçante :

Idealista anti-bot verification page showing a puzzle image with daisies and a slider prompt

Idealista utilise DataDome comme protection anti-bot, qui intègre un test CAPTCHA GeeTest. Vous devez déplacer les pièces du puzzle jusqu’à ce que l’image soit complète, puis vous devriez être redirigé vers votre page cible.

Vous pouvez facilement mettre votre script Puppeteer en pause jusqu'à ce que vous ayez résolu le défi à l'aide de ce code :

await page.waitForFunction(() => {

    const pageContent = document.getElementById('main-content')

    return pageContent !== null

}, {timeout: 10000})

Cela indique à notre script d'attendre 10 secondes qu'un sélecteur CSS spécifié apparaisse dans le DOM. Cela devrait vous laisser suffisamment de temps pour résoudre le CAPTCHA et laisser la navigation se terminer.

Idealista blocked access page stating suspicious usage was detected and access has been blocked

… À moins que la page Idealista ne vous bloque de toute façon.

À ce stade, le processus est devenu plus complexe et difficile, et vous n’avez même pas encore fait évoluer votre projet.

Comme je l'ai mentionné précédemment, Idealista est protégé par DataDome. Ils collectent de multiples données de navigateur pour générer et vous associer à une empreinte digitale unique. S'ils ont des soupçons, vous recevez le défi CAPTCHA ci-dessus, qui est assez difficile à résoudre automatiquement.

Parmi les données de navigateur collectées, on trouve :

  • les propriétés de l'objet Navigator (deviceMemory, hardwareConcurrency, languages, platform, userAgent, webdriver, etc.)
  • des vérifications de timing et de performances
  • WebGL
  • WebRTC analyse d'adresse IP
  • l'enregistrement des mouvements de la souris
  • incohérences entre l'User-Agent et votre système d'exploitation
  • et bien d'autres encore.

Une façon de surmonter ces défis et de continuer à effectuer du scraping à grande échelle consiste à utiliser une API de scraping. Ce type de services offre un moyen simple et fiable d'accéder aux données de sites web tels qu'Idealista.com, sans avoir à développer et à maintenir votre propre scraper.

WebScrapingAPI est un exemple de ce type de produit. Son mécanisme de rotation de proxys permet d'éviter complètement les CAPTCHA, et sa base de connaissances étendue permet de randomiser les données du navigateur afin qu'il ressemble à un véritable utilisateur.

La configuration est rapide et facile. Il vous suffit de créer un compte pour recevoir votre clé API. Celle-ci est accessible depuis votre tableau de bord et sert à authentifier les requêtes que vous envoyez.

Dashboard quickstart guide showing three steps: API access key, API Playground, and integration into your application

Comme vous avez déjà configuré votre environnement Node.js, nous pouvons utiliser le SDK correspondant. Exécutez la commande suivante pour l'ajouter aux dépendances de votre projet :

npm install webscrapingapi

Il ne reste plus qu'à adapter les sélecteurs CSS précédents à l'API. La fonctionnalité puissante des règles d'extraction permet d'analyser les données sans modifications significatives.

import webScrapingApiClient from 'webscrapingapi';

const client = new webScrapingApiClient("YOUR_API_KEY");

async function exampleUsage() {

    const api_params = {

        'render_js': 1,

    	  'proxy_type': 'residential',

    	  'timeout': 60000,

    	  'extract_rules': JSON.stringify({

            locations: {

                selector: 'a.item-link',

                output: '@href',

                all: '1'

        	},

        	titles: {

                selector: 'a.item-link',

                output: '@title',

                all: '1'

        	},

        	prices: {

                selector: 'span.item-price.h2-simulated',

                output: 'text',

                all: '1'

        	},

        	details: {

                selector: 'div.item-detail-char',

                output: 'text',

                all: '1'

        	},

        	descriptions: {

                selector: 'div.item-description.description',

                output: 'text',

                all: '1'

        	}

        })

    }

    const URL = "https://www.idealista.com/pt/alquiler-viviendas/toledo/buenavista-valparaiso-la-legua/"

    const response = await client.get(URL, api_params)

    if (response.success) {

        // Group the lists

    	  const listings = []

    	  for (let i = 0; i < response.response.data.locations.length; i++) {

            listings.push({

                url: response.response.data.locations[i],

                title: response.response.data.titles[i],

                price: response.response.data.prices[i],

                details: response.response.data.details[i],

                description: response.response.data.descriptions[i].replace(/(\r\n|\n|\r)/gm, "")

        	})

    	  }

    	  console.log(listings.length, listings)

    } else {

        console.log(response.error.response.data)

    }

}

exampleUsage();

Conclusion

Dans cet article, nous vous avons montré comment extraire des données d'Idealista, un site web immobilier espagnol très populaire, à l'aide de TypeScript et de Puppeteer. Nous avons passé en revue le processus de configuration des prérequis et d'extraction des données, et nous avons abordé quelques moyens d'améliorer le code.

Le scraping d'Idealista peut fournir des informations précieuses aux entreprises et aux particuliers. En utilisant les techniques décrites dans cet article, vous pouvez extraire des données telles que les URL des biens immobiliers, les prix et les descriptions du site web.

De plus, si vous souhaitez éviter les mesures anti-bot et la complexité du processus de scraping, l'utilisation d'un scraper professionnel peut s'avérer plus efficace et fiable que de créer le vôtre.

En suivant les étapes et les techniques décrites dans ce guide, vous pouvez exploiter tout le potentiel du web scraping d'Idealista et l'utiliser pour répondre aux besoins de votre entreprise. Que ce soit pour des études de marché, la génération de prospects ou la création de nouvelles opportunités commerciales, le web scraping d'Idealista peut vous aider à garder une longueur d'avance sur la concurrence.

À propos de l'auteur
Raluca Penciuc, Développeur full-stack @ WebScrapingAPI
Raluca PenciucDéveloppeur full-stack

Raluca Penciuc est développeuse Full Stack chez WebScrapingAPI ; elle conçoit des robots de collecte de données, améliore les techniques de contournement et recherche des moyens fiables de réduire le risque de détection sur les sites cibles.

Commencez à créer

Prêt à faire évoluer votre système de collecte de données ?

Rejoignez plus de 2 000 entreprises qui utilisent WebScrapingAPI pour extraire des données Web à l'échelle de l'entreprise, sans aucun coût d'infrastructure.