Guide complet sur le web scraping avec PHP

Auteur :

Réagir :

Commenter

PHP ne sert pas qu’à créer des sites dynamiques. Il peut aussi devenir un allié pour collecter des données en ligne.

Grâce à des bibliothèques spécialisées, vous pouvez facilement mettre en place un scraper efficace. Voyons ensemble comment faire.

PHP facilite le web scraping, permettant de récupérer et d'analyser rapidement des données directement depuis les sites web.
PHP facilite le web scraping, permettant de récupérer et d’analyser rapidement des données directement depuis les sites web. ©Christina pour Alucare.fr

Prérequis pour faire du scraping avec PHP

Avant de commencer, assurez-vous :

  • ✅ D’avoir des bases en programmation avec PHP.
  • ✅ D’avoir des notions en HTML et CSS afin de cibler les données à extraire.
  • ✅ De savoir utiliser Composer. C’est un outil pour gérer les dépendances de PHP pour installer les bibliothèques de scraping comme Guzzle, Symfony DomCrawler ou Goutte.
  • ✅ D’avoir un serveur web local pour exécuter votre code (XAMPP, WAMP ou MAMP).
  • ✅ D’avoir un éditeur de code pour écrire vos scripts PHP.

Quels sont les outils indispensables pour le web scraping avec PHP ?

PHP seul ne suffit pas. Voici les bibliothèques qui rendent le scraping rapide et efficace.

1. Guzzle : Le Client HTTP

Guzzle est la bibliothèque la plus utilisée pour envoyer des requêtes HTTP. Pour l’installer avec Composer, ouvrez votre terminal, placez-vous dans le dossier de votre projet, puis tapez la commande :

composer require guzzlehttp/guzzle

Composer télécharge la bibliothèque et la rend utilisable directement dans votre code.

Voici un exemple de code simple pour récupérer le contenu d’une URL :

<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client();

// L'URL cible
$url = 'https://exemple.com';

try {
    // On envoie la requête GET
    $response = $client->request('GET', $url);

    // On récupère le code HTTP
    $statusCode = $response->getStatusCode();

    // On récupère le contenu de la page
    $content = $response->getBody()->getContents();

    echo "Code HTTP : " . $statusCode . PHP_EOL;
    echo "Contenu de la page :" . PHP_EOL;
    echo $content;

} catch (\Exception $e) {
    echo "Erreur : " . $e->getMessage();
}

2. Symfony DomCrawler et Goutte : L’Extraction de Données

Pour parcourir et analyser le HTML, deux bibliothèques sont très utilisées :

  • Symfony DomCrawler qui permet de naviguer dans le HTML avec des sélecteurs CSS et de cibler des éléments précis.
  • Goutte qui est un wrapper de Guzzle et DomCrawler, il simplifie énormément le processus de scraping.

Exemple avec Symfony DomCrawler :

<?php
require 'vendor/autoload.php';

use GuzzleHttp\Client;
use Symfony\Component\DomCrawler\Crawler;

$client = new Client();
$response = $client->request('GET', 'https://exemple.com');

$html = $response->getBody()->getContents();
$crawler = new Crawler($html);

// Sélection par classe
$crawler->filter('.ma-classe')->each(function ($node) {
    echo $node->text() . PHP_EOL;
});

// Sélection par ID
$crawler->filter('#mon-id')->each(function ($node) {
    echo $node->text() . PHP_EOL;
});

// Sélection par balise
$crawler->filter('h1')->each(function ($node) {
    echo $node->text() . PHP_EOL;
});

Exemple avec Goutte

<?php
require 'vendor/autoload.php';

use Goutte\Client;

$client = new Client();
$crawler = $client->request('GET', 'https://exemple.com');

// Sélection par classe
$crawler->filter('.ma-classe')->each(function ($node) {
    echo $node->text() . PHP_EOL;
});

// Sélection par ID
$crawler->filter('#mon-id')->each(function ($node) {
    echo $node->text() . PHP_EOL;
});

// Sélection par balise
$crawler->filter('p')->each(function ($node) {
    echo $node->text() . PHP_EOL;
});

3. Autres bibliothèques et outils

Pour aller plus loin, voici d’autres options :

  • 🔥 PHP-Scraper : c’est une bibliothèque PHP qui facilite l’extraction d’informations depuis des pages web en gérant les complexités du HTML et des sélecteurs. Elle est très utilisée par les développeurs dans leurs projets via Composer.
# Installation avec Composer
composer require fabpot/goutte
  

<?php
require 'vendor/autoload.php';

use Goutte\Client;

$client = new Client();

// Exemple : récupérer le titre d'une page
$crawler = $client->request('GET', 'https://example.com');
$title = $crawler->filter('title')->text();

echo "Titre de la page : " . $title;
  
  • 🔥 Bright Data : c’est une plateforme professionnelle pour la collecte de données à grande échelle avec des proxys intégrés.
Bright Data : l'outil de web scraping le plus complet.
Bright Data : l’outil de web scraping le plus complet. ©Christina pour Alucare.fr
  • 🔥 ScraperAPI : c’est un service de scraping web basé sur le cloud, accessible via une API. Au lieu d’utiliser des bibliothèques locales pour faire tout le travail, vous envoyez une simple requête à l’API de ScraperAPI en spécifiant l’URL de la page à scraper.

Comment créer un web scraper simple en PHP ?

Voici un tuto pour créer un scraper fonctionnel en PHP :

Étape 1 : Installation des dépendances

Utilisez Composer pour installer Goutte grâce au commande :


composer require fabpot/goutte

Étape 2 : Récupérer le contenu d’une page

Faites une requête HTTP GET et récupérez le contenu HTML de la page en utilisant Goutte avec la commande :

<?php
require 'vendor/autoload.php';

use Goutte\Client;

$client = new Client();

// URL cible (ex.: page de blog)
$url = 'https://exemple.com/blog';

// Requête GET
$crawler = $client->request('GET', $url);

// Récupérer le HTML brut si besoin
$html = $crawler->html();
echo substr($html, 0, 500) . '...'; // aperçu

Étape 3 : Extraire les données

Une fois que vous avez récupéré le contenu HTML de la page, l’objectif est d’extraire des données spécifiques.

👉 Voici un exemple de code PHP pour scraper les titres d’une page de blog avec Goutte, en utilisant un sélecteur CSS pour cibler les balises <h2> dans les éléments <article>.

<?php
require 'vendor/autoload.php';

use Goutte\Client;

$client = new Client();
$url = 'https://exemple.com/blog'; // Remplacez par l'URL de votre page cible

// Faire une requête GET pour récupérer la page
$crawler = $client->request('GET', $url);

// Sélectionner les éléments <h2> dans <article> avec le sélecteur CSS
$titres = [];

$crawler->filter('article h2')->each(function ($node) use (&$titres) {
    // Récupérer le texte du titre
    $titres[] = trim($node->text());
});

// Afficher les titres extraits
print_r($titres);
?>

Dans cet exemple :

  • Nous utilisons le sélecteur CSS 'article h2' pour cibler les titres des articles dans les balises <h2> à l’intérieur des balises <article>.
  • Le texte de chaque titre est extrait avec la méthode text(), et nous l’ajoutons au tableau $titres.
  • Les titres sont ensuite affichés avec print_r($titres);.

Les sélecteurs CSS (ou XPath) peuvent également être utilisés pour extraire des attributs d’éléments HTML. Par exemple, si chaque titre de blog est un lien dans une balise <a>, nous pouvons extraire l’attribut href pour obtenir les URL des articles.

👉 Voici un exemple avec Goutte pour extraire les liens des articles :

<?php
require 'vendor/autoload.php';

use Goutte\Client;

$client = new Client();
$url = 'https://exemple.com/blog'; // Remplacez par l'URL de votre page cible

// Faire une requête GET pour récupérer la page
$crawler = $client->request('GET', $url);

// Sélectionner les liens dans les titres
$titres = [];

$crawler->filter('article h2 a')->each(function ($node) use (&$titres) {
    $titre = trim($node->text());
    $lien = $node->attr('href'); // Extraire l'attribut href

    // Ajouter le titre et l'URL au tableau
    $titres[] = [
        'title' => $titre,
        'url'   => $lien,
    ];
});

// Afficher les résultats
print_r($titres);
?>

Dans cet exemple :

  • Nous sélectionnons les liens contenus dans les balises <a> à l’intérieur des balises <h2> dans les éléments <article>.
  • Nous récupérons l’attribut href de chaque lien avec la méthode attr('href').
  • Les titres et leurs URL sont ajoutés au tableau $titres, puis affichés avec print_r($titres);.

👉 Le tableau $titres contiendra des éléments avec à la fois le titre et le lien de chaque article. Voici un exemple du format des données retournées :

Array
(
    [0] => Array
        (
            [title] => Titre de l'article 1
            [url] => /article1
        )

    [1] => Array
        (
            [title] => Titre de l'article 2
            [url] => /article2
        )
)

Dans cet exemple :

  • Chaque élément du tableau est un tableau associatif avec deux clés : title pour le titre de l’article et url pour l’URL correspondante.
  • Les données extraites sont présentées sous forme de tableau à deux niveaux, chaque entrée contenant un titre et son lien associé.

Étape 4 : Structurer et stocker les données

Une fois les données extraites, il est important de les organiser correctement. Pour ce faire, nous allons les structurer dans un tableau PHP, puis les exporter dans un format structuré comme JSON ou CSV.

<?php
require 'vendor/autoload.php';

use Goutte\Client;

$client = new Client();
$url = 'https://exemple.com/blog'; // Remplacez par l'URL de votre page cible

// Faire une requête GET pour récupérer la page
$crawler = $client->request('GET', $url);

// Extraire les titres et les URLs dans un tableau structuré
$data = [];
$crawler->filter('article h2 a')->each(function ($node) use (&$data) {
    $data[] = [
        'title' => trim($node->text()), // Extraire le titre
        'url'   => $node->attr('href'), // Extraire l'attribut href (URL)
    ];
});

// Afficher les données extraites
print_r($data);
?>

Après que les données ont été organisées, vous pouvez les exporter en format JSON, ce qui est pratique pour des API ou pour une utilisation dans des applications web :

<?php
// Exporter les données en JSON
file_put_contents('export.json', json_encode($data, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE));

echo "Les données ont été exportées en JSON dans 'export.json'.";
?>

Le fichier export.json sera créé avec un format lisible, qui pourrait ressembler à ceci :

[
    {
        "title": "Titre de l'article 1",
        "url": "/article1"
    },
    {
        "title": "Titre de l'article 2",
        "url": "/article2"
    }
]

Si vous souhaitez exporter les données sous forme de tableau CSV, vous pouvez utiliser fputcsv pour écrire les données dans un fichier CSV :

<?php
// Exporter les données en CSV
$fp = fopen('export.csv', 'w');

// Ajouter l'en-tête (titres des colonnes)
fputcsv($fp, ['title', 'url']);

// Ajouter chaque ligne de données
foreach ($data as $row) {
    fputcsv($fp, [$row['title'], $row['url']]);
}

// Fermer le fichier
fclose($fp);

echo "Les données ont été exportées en CSV dans 'export.csv'.";
?>

Le fichier export.csv ressemblera à ceci :

title,url
Titre de l'article 1,/article1
Titre de l'article 2,/article2

Comment gérer les problèmes courants du web scraping en PHP ?

Lors d’une opération de web scraping en PHP, il est possible de rencontrer des problèmes. Voici les solutions pour les plus courants.

1. Gérer les erreurs

  • Erreurs de connexion

Parfois, la requête n’arrive même pas au serveur. Vous pouvez tomber sur “Pas de réseau”, “URL invalide”, “Serveur inaccessible”, etc. Dans ce cas, il faut prévoir un try/catch pour éviter que votre script s’arrête brutalement.

👉 Voici un exemple avec Guzzle :

<?php
// Chargez l'autoloader de Guzzle si nécessaire
require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

function make_request_with_guzzle() {
    // Créer une instance du client Guzzle
    $client = new Client();
    
    try {
        // Effectuer la requête GET
        $response = $client->request('GET', 'https://example.com/api/data');
        
        // Vérifiez si la requête a réussi
        if ($response->getStatusCode() === 200) {
            // Traitement de la réponse si succès
            $body = $response->getBody();
            echo "Données reçues : " . $body;
        }
        
    } catch (RequestException $e) {
        // Capture des erreurs de connexion et de requête
        if ($e->hasResponse()) {
            // Afficher le code d'erreur si disponible
            echo "Erreur de la requête : " . $e->getResponse()->getStatusCode();
        } else {
            // En cas d'échec de connexion (par exemple, serveur inaccessible)
            echo "Erreur de connexion : " . $e->getMessage();
        }
    }
}

// Appel de la fonction
make_request_with_guzzle();
?>
  • Codes de statut HTTP

Même si la connexion marche, le serveur peut répondre avec une erreur (404 = page introuvable, 500 = erreur internet, etc.). Vous pouvez tester le code de statut avec getStatusCode().

<?php
// Chargez l'autoloader de Guzzle si nécessaire
require 'vendor/autoload.php';

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

function make_request_with_guzzle() {
    // Créer une instance du client Guzzle
    $client = new Client();
    
    try {
        // Effectuer la requête GET
        $response = $client->request('GET', 'https://example.com/api/data');
        
        // Vérifiez le code de statut de la réponse
        $status_code = $response->getStatusCode();
        
        // Vérifiez si la requête a réussi
        if ($status_code === 200) {
            // Traitement de la réponse si succès
            $body = $response->getBody();
            echo "Réponse réussie avec le code : " . $status_code . "
";
            echo "Données reçues : " . $body;
        } elseif ($status_code === 404) {
            echo "Erreur 404 : Page non trouvée
";
        } elseif ($status_code === 500) {
            echo "Erreur 500 : Erreur interne du serveur
";
        } else {
            echo "Code de statut : " . $status_code . "
";
        }
        
    } catch (RequestException $e) {
        // Capture des erreurs de connexion et de requête
        if ($e->hasResponse()) {
            // Afficher le code d'erreur HTTP si disponible
            echo "Erreur HTTP : " . $e->getResponse()->getStatusCode() . "
";
        } else {
            // En cas d'échec de connexion (par exemple, serveur inaccessible)
            echo "Erreur de connexion : " . $e->getMessage();
        }
    }
}

// Appel de la fonction
make_request_with_guzzle();
?>
  • Erreurs de parsing 

Le parsing, c’est l’analyse du HTML par votre scraper. Si la page est mal formée, DomCrawler ou Goutte peuvent planter ou ne rien renvoyer.

Pour gérer ce genre d’erreur, il faut toujours vérifier que le contenu existe avant d’essayer de l’extraire. Utilisez des conditions (count(), filter()...) pour vous assurer que l’élément ciblé est bien présent. Puis, entourez le parsing dans un try/catch pour éviter que le script plante.

<?php
// Chargez l'autoloader de Guzzle et de Goutte si nécessaire
require 'vendor/autoload.php';

use Goutte\Client;
use Symfony\Component\DomCrawler\Crawler;

function scrape_website() {
    // Créer une instance du client Goutte
    $client = new Client();
    
    try {
        // Faire une requête GET à une page web
        $crawler = $client->request('GET', 'https://example.com');

        // Vérifier si l'élément cible existe avant d'essayer de l'extraire
        $elements = $crawler->filter('div.target-element');
        
        if ($elements->count() > 0) {
            // L'élément est présent, on peut l'extraire
            $content = $elements->first()->text();
            echo "Contenu extrait : " . $content;
        } else {
            // L'élément n'est pas trouvé
            echo "L'élément cible n'a pas été trouvé sur la page.";
        }
        
    } catch (Exception $e) {
        // Capture des erreurs de parsing
        echo "Erreur lors du parsing de la page : " . $e->getMessage();
    }
}

// Appel de la fonction
scrape_website();
?>

2. Contourner les limitations

Certains sites mettent en place des protections pour compliquer le scraping.

  • ❗Blocage par IP : vous pouvez utiliser des proxys comme ceux de la plateforme Bright Data.
  • JavaScript : par défaut, PHP ne peut pas exécuter le JavaScript. Pour ce faire, l’utilisation d’un navigateur sans tête (headless browser) est nécessaire.
  • Robots.txt : avant de scraper, il est important de vérifier ce fichier pour agir de manière légale et responsable.

FAQ

Le web scraping est-il légal ?

📌 La légalité du web scraping est un sujet complexe. En France comme ailleurs, tout dépend du cadre juridique, des données collectées et de la manière dont elles sont exploitées.

Quelle est la différence entre le web scraping et le web crawling ?

  • Le web scraping est le fait d’extraire des données précises sur un site.
  • Le web crawling est le fait de parcourir des pages pour les indexer.
Le web crawling consiste à explorer et découvrir automatiquement plusieurs sites web, tandis que le web scraping se concentre sur l'extraction de données précises d'une cible spécifique à l'aide de logiciels spécialisés.
Le web crawling consiste à explorer et découvrir automatiquement plusieurs sites web, tandis que le web scraping se concentre sur l’extraction de données précises d’une cible spécifique à l’aide de logiciels spécialisés. ©Christina pour Alucare.fr

Comment scraper un site qui nécessite une authentification (login) ?

Pour scraper un site qui nécessite une authentification, il faut simuler la connexion. Avec PHP, la solution la plus courante est Guzzle.

Vous envoyez les identifiants via une requête POST, puis gardez la session ouverte pour récupérer les pages protégées.

Comment gérer le scraping de sites avec des pages dynamiques chargées en AJAX ?

⚠ Pour rappel, PHP ne peut pas exécuter le code JavaScript côté client.

Pour scraper ce type de pages avec PHP, vous pouvez utiliser BrowserShot, une bibliothèque qui utilise un navigateur réel en arrière-plan (Headless Chrome/Chromium) pour charger la page et exécuter le JavaScript.

Une autre solution consiste à intégrer PHP avec des outils basés sur Node.js, comme Puppeteer pour générer le HTML rendu et récupérer ensuite les données depuis PHP.

Pour tout type de web scraping avec des pages dynamiques, vous pouvez aussi utiliser des outils spécialisés appelés headless browsers.

Existe-t-il des alternatives à PHP pour le web scraping ?

Oui, plusieurs langages sont populaires :

  • Python avec ses bibliothèques puissantes comme BeautifulSoup et Scrapy.
  • Node.js qui est très efficace pour le scraping de sites web dynamiques, en utilisant des bibliothèques comme Puppeteer ou Cheerio.
Le web scraping avec Python fonctionne en utilisant des bibliothèques comme BeautifulSoup ou Scrapy pour parcourir les pages web et extraire automatiquement les données souhaitées.
Le web scraping avec Python fonctionne en utilisant des bibliothèques comme BeautifulSoup ou Scrapy pour parcourir les pages web et extraire automatiquement les données souhaitées. ©Christina pour Alucare.fr

Comment programmer un “scraper” de manière éthique et responsable ?

Pour scraper de manière éthique, vous devez :

  1. ✔ Vérifier le fichier robots.txt du site pour connaître les règles.
  2. Limiter la fréquence de vos requêtes pour ne pas surcharger le serveur du site.
  3. Respecter les conditions d’utilisation du site.
  4. Ne pas collecter de données personnelles sensibles sans autorisation.

✅ En résumé, le web scraping est une pratique puissante, mais il doit être utilisé avec méthode et responsabilité.

👉 Et vous, avez-vous déjà créé un scraper en PHP ou avec un autre langage ? Partagez vos expériences en commentaire.

Vous avez trouvé cela utile ? Partagez-le avec un ami !


Alucare est un média indépendant et gratuit. Soutenez-nous en nous ajoutant à vos favoris Google News :

Publiez un commentaire sur le forum de discussion