Seohackers netlinking

Accélérer vos scripts php grâce au multithreading

Ecrit par Maxime le Jeudi 2 septembre 2010 à 13:43 - Catégorie Scripts PHP

Lecteur de SeoBlackOut, Tiger m’a fait le plaisir de publier ce premier article qui je l’espère vous plaira. Nous avons mis en place dans ma boite qui crée des boutiques en ligne ce script qui permet de multithreader des scripts php.

Imaginez le cas suivant : Vous souhaitez créer un script qui extrait des données du web. Si vous êtes très BlackHat ce sera pour extraire des digg-likes et des blogs à spammer, ou comme chez Vaisonet ce sera plutôt un script pour faire des relevés de prix sur les boutiques en ligne des concurrents de vos clients … C’est toujours plus sympathique que de le faire à main.

Dans tous les cas, vous ne voulez par faire quelque chose d’agressif et vous temporisez le tout. Vous avez donc certainement quelque chose comme cela :

$sites = array('www.siteA.fr', 'www.siteB.fr', 'www.siteC.fr', )
foreach($sites as $site)
{
 //Votre fonction d'extraction
 extraction($site);
 
 //La tempo pour passer sous les radars
 sleep(15);
}

Si vous voulez accélérer les choses, le seul moyen est de lancer toutes les extractions en parallèle.  C’est facile à faire avec peu de paramètre, mais remplacez 3 sites exemples par 30 à faire tous les jours, c’est vite pénible !

L’idée est donc d’exécuter chaque élément de la boucle foreach dans un thread distinct en même temps que les autres.

Mauvaise nouvelle, php ne sait pas vraiment faire cela, il faut utiliser autre chose. De nombreux langages le permettent : C, C++, Java, etc … J’ai choisi Python. C’est un langage qui n’est pas compilé, rapide à coder et vous le verrez facile à comprendre.

Mais je vois déjà une objection pointer à l’horizon : pourquoi ne pas tout coder en Python ? Ce serait clairement la solution la plus pertinente techniquement, je suis parfaitement d’accord. Mais dans les faits, les cordonniers sont les plus mal chaussés : on traine de vieux bouts de code php issu d’une ancienne application web, ou on fait des extractions plus complexe en Perl avec Talend par exemple.

Et oui, avec le script qui arrive, vous pourrez aussi multithreader des scripts Perl !

Bref, cet outil vous permettra de recycler vos vieux bouts de code ;)

Préalable sur Python

Il vous faut Python 3 installé sur votre poste : http://www.python.org/

Python 3 contient un éditeur très commode : IDLE que je vous encourage à utiliser. Et deux astuces : attention à l’identation avec Python. Mettez l’extension py pour un script Python classique et pyw pour un script se lançant sans fenêtre. Je le recommande pour ce script.

Si vous souhaitez diffuser votre script Python et qu’il fonctionne sans avoir à installer Python, tournez vous vers py2exe (Utilisateurs avancés  : imaginez ce que l’on peut faire en distribuant les calculs via un exe …).

Multithreader PHP grâce à Python

# Limititation : les threads d'utilisent qu'un coeur d'un processeur multicoeur
# Ce n'est pas gênant pour l'utilisation escomptée, sachant que la puissance de
# calcul n'est pas le facteur limitant, celui-ci étant la latence réseau.
# Auteur : Maxime Varinard - Vaisonet - http://www.vaisonet.com
# Vous pouvez librement ré-utiliser ce script, mais un petit backlink avec une belle
# ancre de votre choix contenant e-commerce serait un beau remerciement ;)
import threading, os
from tkinter import *
 
th = 0
 
def lancement(param):
    global th
    th = th + 1
    # la ligne ci-dessous est à adapter pour lancer les bons programmes/scripts
    script = '"c:/Program Files/xampp/php/php.exe" c:/Users/Maxime/Desktop/sleep.php ' + param
    os.system(script)
    th = th - 1
 
# On peut lancer manuellement des scripts, hors boucle for (par exemple un script perl)
a = threading.Thread(None, lancement, None, ('1',))
b = threading.Thread(None, lancement, None, ('5',))
a.start()
b.start()
 
# On lance la boucle des threads
# Le tableau li contient les paramètres à passer au script. Il lancera en parallèle les scripts
# avec les différents paramètres.
li = ['www.siteA.fr', 'www.siteB.fr', 'www.siteC.fr']
for s in li:
    s = threading.Thread(None, lancement, None, (s,))
    s.start()
 
# Le thread qui surveille la fin d'exécution des autres threads
# Permet de signaler la fin d'exécution des scripts lancés s'ils n'ont pas de fenêtres
def alert():
    global th
    while th > 0:
        # On ne fait rien
        continue
    fen = Tk()
    fen.title('Outils Vaisonet')
    tex = Label(fen, text='Les tâches sont terminées !', width=45, height=3)
    tex.pack()
    bou = Button(fen, text='Ok', command = fen.destroy)
    bou.pack()
    fen.mainloop()
    print("fini", th)
 
EA = threading.Thread(None, alert, None)
EA.start()

Le script est bien commenté, mais voici quelques explications complémentaires pour son intégration avec php. Il faut sortir la boucle foreach de votre script php pour l’intégrer dans le script Python. On appelle ensuite votre script php en ligne de commande. Cela veut donc dire qu’il faut savoir utiliser $argv pour passer le paramètre. Voici un exemple, mon fichier sleep.php de test

echo "toto" . $argv[1];
sleep(30);

Et si vraiment vous voulez tenter de faire du mutlithreading avec php, faites un tour du côté de stream_select.
La solution avec cURL pose parfois des problèmes, mais vous pouvez essayer : Multithreading avec Curl et PHP

Ce n’est pas l’astuce SEO Black Hat de la mort qui tue, mais je suis sûr que vous trouverez des applications qui vous seront utiles ;)
Bon code.

Commentaires (12)

Catégorie: Scripts PHP


12 Commentaires

Commentaire par Screu

Jeudi, 2 septembre , 2010 à 14:03

Et faire avec ça c’est pas possible :
http://www.reflectiv.net/blog/multi-threading-en-php5/

??

Commentaire par Maxime

Jeudi, 2 septembre , 2010 à 14:24

@Screu Si bien sûr, même si à mon sens la compréhension du code est plus délicate. Attention tout de même, PCNTL ne fonctionne que sous Unix. Le script Python de cet article peut tourner sur à peu prêt toutes les plateformes.

Commentaire par Jérôme

Jeudi, 2 septembre , 2010 à 15:02

Effectivement, pcntl est fait pour ça, et l’avantage du script python est vraiment la portabilité.

Commentaire par Maxime G.

Jeudi, 2 septembre , 2010 à 15:22

Ou sinon, un script bash qui lance les scripts avec la commande détachante « & »

Remplacer 4 par le nombre de core ou plus si vous avez de l’accès réseau (ce qui est un peu bloquant).
Ça tourne en parallèle, et c’est natif.
Par contre faut gérer la concurrence (pour pas qu’il fasse 4 fois la même chose)

#!/bin/bash

cd "$(dirname "$0")"
cmd='php update-feed.php'
for i in $(seq 1 4)
do
(eval $cmd) &
sleep 1 #optionnel
done

Commentaire par Olivier

Jeudi, 2 septembre , 2010 à 16:17

Salut Maxime,
Merci pour ton partage.
Cependant je crois que tu te compliques un peu la vie :D . Il n’y a pas besoin de faire du multi-thread pour le cas de figure que tu as exposé : le multi requête via Curl en PHP est suffisant (cf http://php.net/manual/en/function.curl-multi-exec.php)

Commentaire par beunwa

Vendredi, 3 septembre , 2010 à 9:21

Excellent, une raison de plus de me mettre à python ! Merci

Commentaire par Ths

Lundi, 6 septembre , 2010 à 14:35

Pour ceux qui ne peuvent pas installer Python, et qui n’ont pas de dual core:

http://www.onlineaspect.com/2009/01/26/how-to-use-curl_multi-without-blocking/

Commentaire par BlackMelvyn

Jeudi, 9 septembre , 2010 à 9:57

Et moi qui vient d’installer Python sur mon mac, voilà tout de suite de quoi me motiver :D

Pour le multi-threading en PHP, j’ai un joli snippet qu’il faut que je te montre, on en discute bientôt ;)

Merci pour le script en tout cas

Commentaire par salon dejardin

Samedi, 11 septembre , 2010 à 10:42

Ca fait longtemps que je veux prendre le temps de me mettre à Python, et bien voilà l’occasion rêvé !
Bien que le niveau est peut-être un peu élevé pour une première… ^^

En tous cas merci, je vais étudier ca de prêt ! ;)

Commentaire par skar

Dimanche, 17 octobre , 2010 à 0:26

Juste une question, peut on m’expliquer le but de la « temporisation » entre 2 parsings ?
Qu’entends tu par « La tempo pour passer sous les radars » ?

Moi je « curl » à la brutale et je me porte bien… Si tu pouvais m’expliquer le pourquoi du comment :D

merci.

Commentaire par lolo

Jeudi, 11 novembre , 2010 à 2:29

« Ce n’est pas l’astuce SEO Black Hat de la mort qui tue » => détrompe toi, ça va m’être grandement utile :) ))
MERCI !

Commentaire par Giloux

Mercredi, 24 novembre , 2010 à 11:04

Salut,

Et dire que je me plaignais de ne pas trouver de code en python pour la seo !!

Tu as raison, le multithreading est très puissant pour gagner beaucoup de temps quand on effectue des tâches où il y a beaucoup d’attente (comme la récupération d’url).

Fais attention tout de même à ne pas lancer trop de threads en même temps, ça pourrait poser un pb de ressources sur ta machine. Le mieux est d’utiliser un pool de threads qui dépilent tous une liste de tâches; tu peux ainsi maîtriser la charge. La classe python qui a tout ce qu’il faut pour faire ça est la Queue.

Si tu veux un exemple d’utilisation tu peux aller voir ici (je l’ai codé avec mes petits doigts ;-) ): http://python-seo.blooh.net/2010/11/16/thread-pool-en-python/

Les commentaires sont fermés pour cet article.



SEO BLACKOUT

Site web dédié aux techniques de référencement et de positionnement de sites web sur Google.

Certaines parties du site sont en accès restreint, ces espaces sont réservés à la SEO Black Hat Team.


Don't Be Evil !