poster un article sur wordpress avec python et api rest
5/5 - (2 votes)

Pour commencer, qu’est-ce que l’API Rest de WordPress et à quoi elle sert ?

L’API REST de WordPress, c’est la baguette magique pour les devs qui veulent piloter leur site sans se frotter à l’interface habituelle. Avec cette API, t’as le pouvoir de faire à peu près tout ce que tu veux, et ce, de façon programmée.

En clair ? Tu peux concocter des articles, les retoucher, les balancer à la corbeille, orchestrer les commentaires, gérer la troupe des utilisateurs, et même tweaker les paramètres de ton site, le tout en maniant les classiques requêtes HTTP.

Imagine que tu veuilles automatiser la publication d’articles, synchroniser du contenu entre plusieurs sites, ou même créer une appli qui se base sur ton site WordPress. L’API REST rend tout ça possible, et ce, de manière super fluide et flexible. Tu envoies des requêtes à des URL spécifiques de ton site, et hop, tu reçois des réponses en JSON, un format facile à manier, même dans tes scripts.

C’est un outil puissant qui ouvre des portes à une personnalisation et une automatisation de malade, transformant ton site WordPress en véritable plateforme dynamique. Tu commences à voir le potentiel ?

 

Le code Python pour t’authentifier et poster ton article

On va faire simple et efficace, et on commence tout de suite !

import requests
from requests.auth import HTTPBasicAuth

D’abord, on importe le module requests. C’est lui qui va nous permettre de faire des requêtes HTTP super facilement. HTTPBasicAuth est un helper de requests pour gérer l’authentification avec un nom d’utilisateur et un mot de passe, juste ce qu’il nous faut pour parler à WordPress.

# Remplacez par l'URL de votre site WordPress, votre nom d'utilisateur et votre mot de passe
url = 'https://ton.fr/wp-json/wp/v2/posts'
username = 'ton identifiant'
password = 'ton mot de passe'

Ici, on prépare le terrain. url c’est l’adresse où on va envoyer notre requête pour créer un post. Ça pointe directement sur l’API REST de WordPress. Change username et password par tes propres infos pour que ça marche avec ton site.

# Post data
post_data = {
    'title': 'Titre article',
    'content': 'Ton contenu.',
    'status': 'publish'
}

post_data, c’est le contenu de ton article. Tu mets le titre dans title, le corps de l’article dans content, et status à ‘publish’ pour le publier directement. Si tu veux juste le mettre en brouillon, tu mettrais ‘draft’.

# Make a POST request to create a new post
response = requests.post(
    url,
    auth=HTTPBasicAuth(username, password),
    json=post_data
)

C’est là que la magie opère. On envoie une requête POST à WordPress avec nos données. L’authentification est gérée par HTTPBasicAuth qui prend nos identifiants.

# Check the response
if response.status_code == 201:
    print("Post successfully published!")
    print("Post URL:", response.json()['link'])
else:
    print("Failed to publish the post. Status code:", response.status_code)
    print("Error message:", response.text)

Enfin, on vérifie la réponse de l’API. Si le code de statut HTTP est 201, c’est que tout s’est bien passé et l’article est publié. On peut même récupérer l’URL du post publié. Si ça foire, on affiche le code d’erreur et le message pour comprendre le souci.

 

Le code complet :

import requests
from requests.auth import HTTPBasicAuth

# Remplacez par l'URL de votre site WordPress, votre nom d'utilisateur et votre mot de passe
url = 'https://tonsite.fr/wp-json/wp/v2/posts'
username = 'ton identifiant'
password = 'ton mot de passe'

# Post data
post_data = {
    'title': 'Titre article',
    'content': 'Ton contenu.',
    'status': 'publish'
}

# Make a POST request to create a new post
response = requests.post(
    url,
    auth=HTTPBasicAuth(username, password),
    json=post_data
)

# Check the response
if response.status_code == 201:
    print("Post successfully published!")
    print("Post URL:", response.json()['link'])
else:
    print("Failed to publish the post. Status code:", response.status_code)
    print("Error message:", response.text)

 

Erreur « Failed to publish the post. Status code: 401 »

Failed to publish the post. Status code: 401
Error message: {"code":"rest_cannot_create","message":"D\u00e9sol\u00e9, vous n\u2019avez pas l\u2019autorisation de cr\u00e9er des contenus sous cet identifiant.","data":{"status":401}}

Ce fameux code d’erreur 401, un classique ! Ça veut dire « Non autorisé ». Ton script Python essaie de publier un article, mais WordPress lui dit : « Eh, minute papillon, qui t’es pour faire ça ? ».

 

La fonction PHP pour corriger l’erreur 401

Tu vas devoir intégrer cette fonction dans le functions.php de ton thème enfant ou te créer un plugin avec cette fonction. Car n’oublies pas que si tu ajoutes ça dans le thème de base, ton code disparaitra lors de la prochaine mise à jour.

add_filter('determine_current_user', function ($user) {
    if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) {
        $username = $_SERVER['PHP_AUTH_USER'];
        $password = $_SERVER['PHP_AUTH_PW'];
        $user = wp_authenticate($username, $password);
        if (is_wp_error($user)) {
            return null;
        }
        wp_set_current_user($user->ID);
        return $user->ID;
    }
    return $user;
});

 

Explication de la fonction

Activation du filtre avec add_filter : C’est la clé de voûte qui te permet de jongler avec les données avant que WordPress ne mette son nez dedans. On utilise ici determine_current_user pour trouver l’identifiant de l’utilisateur actif.

Contrôle des identifiants : On vérifie que les variables $_SERVER['PHP_AUTH_USER'] et $_SERVER['PHP_AUTH_PW'] ne sont pas vides. Elles contiennent les infos indispensables d’authentification HTTP Basic envoyées par ton script Python.

Authentification à la rescousse : On lance wp_authenticate pour valider le couple nom d’utilisateur/mot de passe. Si ça matche,  c’est tout bon.

Quand ça coince, gestion des erreurs : Si wp_authenticate te renvoie une erreur, vérifie avec is_wp_error($user), on met tout en pause et on renvoie null.

Définir qui tient les rênes : Si tout est ok, on active wp_set_current_user pour confirmer officiellement l’identité de l’utilisateur avec son ID. Cet ID, on le renvoie pour que WordPress sache qui dirige la danse.

 

Pourquoi ajouter ce code dans functions.php ?

Le fichier functions.php dans ton thème WordPress, c’est le centre de commandement pour tes customisations. En y glissant des morceaux de code comme celui-là, tu fais évoluer le comportement de ton site pour le rendre plus flexible ou plus blindé, selon ce que tu cherches à faire.

Le hic, c’est que de base, WordPress n’est pas fan de l’authentification HTTP Basic pour son API REST quand les appels viennent de l’extérieur. Donc même si tu envoies les bons identifiants via ta requête, WordPress fait la sourde oreille et bloque l’entrée. Le snippet de code que tu rajoutes va régler ce souci en forçant WordPress à reconnaître et à accepter les identifiants envoyés par ton script Python.

 

Aller plus loin en ajoutant une image à la une avec un media intégré dans le contenu

import requests
from requests.auth import HTTPBasicAuth

# Remplacez par l'URL de votre site WordPress, votre nom d'utilisateur et votre mot de passe
url = 'https://tonsite.fr/wp-json/wp/v2/posts'
media_url = 'https://tonsite.fr/wp-json/wp/v2/media'  # URL pour l'upload de médias

username = 'ton identifiant'
password = 'ton mot de passe'

# Préparation de l'image à uploader
media_data = {
    'file': open('image.webp', 'rb'),  # Assurez-vous que le chemin vers votre image est correct
    'caption': 'Optional caption here'
}
# Upload de l'image
media_response = requests.post(
    media_url,
    auth=HTTPBasicAuth(username, password),
    files=media_data
)
# Vérification de la réponse de l'upload d'image
if media_response.status_code == 201:
    media_id = media_response.json()['id']
    print("Image successfully uploaded!")
    print("Media ID:", media_id)

    # Données de l'article avec image intégrée
    post_data = {
        'title': 'Titre article',
        'content': 'Ton contenu. <img src="{}" alt="Description">'.format(media_response.json()['source_url']),
        'status': 'publish',
        'featured_media': media_id  # Définir l'image uploadée comme image à la une
    }

    # Création de l'article
    response = requests.post(
        url,
        auth=HTTPBasicAuth(username, password),
        json=post_data
    )

    # Vérification de la réponse de création d'article
    if response.status_code == 201:
        print("Post successfully published!")
        print("Post URL:", response.json()['link'])
    else:
        print("Failed to publish the post. Status code:", response.status_code)
        print("Error message:", response.text)
else:
    print("Failed to upload image. Status code:", media_response.status_code)
    print("Error message:", media_response.text

 

Explications du processus :

  1. Préparation de l’image à uploader : Avant tout, tu prépares ton image. Tu ouvres le fichier en mode lecture binaire ('rb'), ce qui est crucial pour que l’image soit lue correctement lors de l’envoi.
  2. Upload de l’image : Ensuite, on envoie l’image au serveur WordPress. Note bien qu’on utilise l’URL dédiée aux médias (media_url). On passe aussi l’authentification HTTP Basic pour s’assurer que l’opération se fait en toute sécurité.
  3. Vérification de la réponse de l’upload d’image : On checke si l’image a bien été uploadée. Si media_response.status_code est 201, c’est que tout est bon. L’ID de l’image uploadée (media_id) est récupéré pour être utilisé par la suite.
  4. Intégration de l’image dans l’article : L’image est maintenant sur le serveur, alors on peut l’intégrer dans l’article. On utilise format() pour insérer l’URL de l’image directement dans le HTML du contenu de l’article. De plus, on associe cette image comme « image à la une » du post en passant son ID dans featured_media.

 

Pour ajouter la meta description

    # post_data['meta'] = {'_aioseop_description': 'Ta meta.'}  # Pour All in One SEO Pack
    # post_data['yoast_meta'] = {'yoast_wpseo_metadesc': 'Ta meta.'}  # Pour Yoast SEO
    # post_data['meta'] = {'rank_math_description': 'Ta meta.'}  # Pour Rank Math SEO

 

Intégration dans le code

# Données de l'article avec image intégrée
post_data = {
    'title': 'Ton titre',
    'content': 'Ton contenu. <img src="{}" alt="Description">'.format(media_response.json()['source_url']),
    'status': 'publish',
    'featured_media': media_id,  # Définir l'image uploadée comme image à la une
    'meta': {
        '_aioseop_description': 'Ta meta.'
    }
}