Lire flux RSS distant

Que faire?

Vous pouvez sélectionner 1 option
 
 
Voir les résultats
Eléphant du PHP | 299 Messages

25 mars 2007, 02:02

Bonjour,

Je viens de passer de nombreuses heures à coder une classe de lecture de flux RSS. J'avais commencé par une methode très simple mais qui ne marchait pas tout le temps : simplexml puis je me suis tourné vers une methode moins fine.
J'aimerais votre avis sur ces deux méthodes et notamment, est il utile de faire un switch sur ses deux méthodes pour choisir la méthode bourine par défaut puis simplexml si le fichier RSS le permet.



Merci à vous :)
Modifié en dernier par pirquessa le 27 mars 2007, 23:04, modifié 1 fois.

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

25 mars 2007, 11:47

Bonjour,

Normalement, SimpleXML fonctionne plutôt bien sur les flux RSS...
Tu peux nous donner un exemple de flux sur lequel tu as rencontré des problèmes et nous décrire ceux-ci en détail?
Quand tout le reste a échoué, lisez le mode d'emploi...

Eléphant du PHP | 299 Messages

25 mars 2007, 11:57

Je rencontre des problème avec simple xml pour des flux comme cela:

http://www.langamers.ch/langamers/news.xml
http://www.zeden.net/zedenfeed.xml
http://www.journaldugamer.com/rss_base.php

Leur point commun, mettre l'élément date dans une balise dc:date plutôt que pubDate... Mon script t'arrive pas à lire cet élément :(

l'élément de mon tableau de retour correspondant à la date est toujours vide alors que je peux récupérer le champ dc:date avec mon autre script...

Pour le moment j'appelle le script de cette manière qui me fait utiliser les deux script car je suppose que simpleXML est plus rapide. Vrai? Faux ?
$methode = ($this->date=="pubDate") ? "simplexml" : "basique";
$rss = $fichier_rss->lire_rss($nb_news,$methode);

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

25 mars 2007, 14:27

Si tu fais une recherche sur Google sur

Code : Tout sélectionner

+"simplexml_load_file" +namespace
...tu trouveras pas mal d'articles sur le sujet.

Pour résumer le peu que je sais sur ce sujet particulier, SimpleXML "gomme" les namespaces donc il faut le spécifier explicitement si on veut récupérer un nœud appartenant à un namespace. Comme d'habitude j'utilise XPath pour faire le boulot à ma place :
$rss = simplexml_load_file('http://www.langamers.ch/langamers/news.xml');
foreach ($rss->xpath('//item') as $item)
{
	if (isset($item->pubDate))
	{
		$date = $item->pubDate;
	}
	elseif ($dates = $item->xpath('dc:date[1]'))
	{
		$date = $dates[0];
	}
	else
	{
		$date = '???';
	}

	echo $item->title, ' (', $date, ") \n";
}
$item représente successivement chaque nœud item du document, sur lequel j'effecture une recherche grâce à XPath. Si pubDate existe c'est ce que j'utilise, sinon je remets un coup de XPath pour sélectionner le premier nœud dc:date descendant du item en cours (d'où le $item->xpath()). À noter que j'aurais pu tout faire à la fois en disant à XPath de sélectionner tous les nœuds pubDate ou dc:date avec
$item->xpath('pubDate | dc:date');

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

25 mars 2007, 14:34

Au fait, j'ai remarqué que tu utilisais un truc bizarre pour limiter le nombre de nœuds à traiter, tu pourrais simplement utiliser l'index retourné par foreach ou encore utiliser XPath pour limiter le nombre de nœuds. Du coup, la boucle devient (en condensant)
$rss = simplexml_load_file('http://www.langamers.ch/langamers/news.xml');
foreach ($rss->xpath('//item[position() <= 3]') as $item)
{
	echo $item->title, ' (', (($dates = $item->xpath('pubDate | dc:date')) ? $dates[0] : '???'), ") \n";
}

Eléphant du PHP | 299 Messages

25 mars 2007, 14:52

j'essaie ca très bientot donc :)
Merci de ton aide.

Question rapidité des deux méthodes, tu as un avis ?
Modifié en dernier par pirquessa le 25 mars 2007, 16:04, modifié 1 fois.

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

25 mars 2007, 15:19

Mon avis est que les deux méthodes doivent avoir un ordre de grandeur comparable. Le truc avec "$rss->channel->{$this->item}[$i]->{$objet}" est plutôt lent parce que chaque -> et chaque [] sont évalués à chaque itération de la boucle, c'est pour ça que foreach est mille fois préférable, et plus lisible aussi. (SimpleXML a été fait pour ça). preg_split() n'est pas spécialement rapide non plus.

Utilise SimpleXML avec foreach, tu auras d'excellent résultats.

Eléphant du PHP | 299 Messages

25 mars 2007, 16:04

merci des conseils :)

Mammouth du PHP | 505 Messages

25 mars 2007, 18:55

Moi, je n'aime pas réinventer la roue, alors je te dirais plutot utilise par exemple, le zendFramework qui fait ca pour toi.

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

25 mars 2007, 20:19

Err, tu veux utiliser quoi à la place de quoi exactement ? Si tu parles de Zend_Feed, je trouve qu'il y a relativement peu d'intérêt à utiliser ça plutôt qu'un coup de SimpleXML. Par curiosité, j'ai téléchargé la dernière version du framework et créé ce script dans le dossier Zend pour mesurer la quantité de code supplémentaire à ajouter à son propre script pour charger un RSS:
include 'Zend/Feed/Rss.php';
$feed = new Zend_Feed_Rss('http://www.langamers.ch/langamers/news.xml');

echo (array_sum(array_map('filesize', get_included_files())) >> 10), ' KiB parmis ', (count(get_included_files()) - 1), ' fichiers (', (memory_get_peak_usage() >> 10), ' KiB de RAM)';
Résultat : 169 KiB parmis 24 fichiers (1019 KiB de RAM) pour exécuter Zend_Feed_Rss :?

Ensuite j'ai essayé ça
$items = simplexml_load_file('http://www.langamers.ch/langamers/news.xml')->xpath('//item[position() <= 10]');

echo (array_sum(array_map('filesize', get_included_files())) >> 10), ' KiB parmis ', (count(get_included_files()) - 1), ' fichiers (', (memory_get_peak_usage() >> 10), ' KiB de RAM)';
0 KiB parmis 0 fichiers (62 KiB de RAM)

C'est vous qui voyez. :-({|=

Eléphant du PHP | 299 Messages

25 mars 2007, 20:26

le choix est vite fait :)

Mammouth du PHP | 505 Messages

26 mars 2007, 09:39

Présenté comme ca c'est sur...

Mais cela dépend qd meme du point de vue.

Si tu as un petit site et pas beaucoup de boulot dessus, ajouter ta propre gestion ne coute pas grand chose... Maintenant, si tu as plusieurs gros sites avec plusieurs dév qui bosse a pleins temps dessus, des demandes de plusieurs services pour faire évoluer ces sites, la avant de dire je vais gérer un truc tout seul, tu y regardes a 2 fois. Ca sera autant de code à maintenir.

Ensuite, faire des calculs comme ca brute de fonderie, ca signifie pas grand chose. Le ZF est un framework object, c'est sur, il y aura beaucoup de fichiers puisque il est concu par classe et packages. Mais si tu utilises une autre brique du meme framework (MVC par exemple), tu auras déja beaucoup de fichiers commun. Maintenant, dans la mesure ou ce n'est pas toi qui maintient le code, le fait qu'il y ait 10, 20 ou 100 fichiers importe au final assez peu, ce que je voie moi, c'est que le code sera certainement plus éprouvé car utiliser par beaucoup plus de monde et qu'en cas de bug, il sera très vite corrigé par la communauté.

Il faut aussi comparer ce qui est comparable... Le zend_feed, ce n'est pas seulement le chargemetn d'un flux rss tel que tu le représentes... il gère les flux rss et atoms, ainsi que les différents canaux si y en as dans le flux, permet de faire des modifs sur les flux, etc..

Pour finir, calculer la conso ram comme ca, c'est un peu légé. Les systèmes de cache existe (il y a en a meme un dans le ZF :) ) et la conso ram/cpu pour lire le flux devient négliable au regard de l'utilisation du flux. Cad que tu ne vas réellement utiliser le code du feed que lors du refresh du flux, le reste du temps, tu attaqueras le cache local.
PHP, sans cache d'op code et sans cache de page, ca mene pas loins. Meme avec un machine de guerre, tu as rapidement des problèmes. mais c'est un autre débat :)

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

26 mars 2007, 11:51

Je ne cherche pas à faire le procès du ZF ou des frameworks en général, mais j'essaie de promouvoir le bon outil pour la bonne tâche. Si tu veux créer un site complet dont le boulot est de gérer des RSS, Atom, etc... avec plusieurs canaux avec des tas d'options, etc... alors j'imagine que tu trouveras des trucs utiles dans le ZF.

Maintenant, si tu veux juste charger 3 feeds (dont tu connais par avance le format) pour les afficher sur ta page d'accueil alors un coup de SimpleXML fera le boulot pour toi.
si tu utilises une autre brique du meme framework (MVC par exemple), tu auras déja beaucoup de fichiers commun
J'ai bien peur qu'il y ait beaucoup de fichiers supplémentaires, plutôt que communs. Regarde la liste de get_included_files(), à part 2 ou 3 interfaces et la classe d'exception tout le reste est dédié aux éléments du Feed et du client HTTP (en parlant de réinventer la roue... :roll:).
Il faut aussi comparer ce qui est comparable...
Je suis 100% d'accord, Zend_Feed fait des tas de trucs en plus, mais dans ce cas précis j'ai bien peur qu'il s'agisse de trucs que pirquessa n'utilisera pas.
Pour finir, calculer la conso ram comme ca, c'est un peu légé.
Ça a le mérite d'être un nombre, et j'adore les nombres. On l'interprète comme on veut mais je pense que ça donne une assez bonne indication de la mémoire utilisée. Ceci dit, 1 MiB c'est pas énorme non plus, même si ça ne compte pas la place prise par l'opcode cache.
Les systèmes de cache existe (il y a en a meme un dans le ZF :) )
Par curiosité, est-ce que le client "Http" du ZF utilise un cache de manière transparente ? Ou est-ce qu'il faut soi-même demander de mettre le flux en cache ?

J'en profite pour donner ma solution "à la main" :
$url = 'http://www.langamers.ch/langamers/news.xml';
$filepath = './cache/' . md5($url);

if (@filemtime($filepath) < time() - 300)
{
	copy($url, $filepath);
}

$items = simplexml_load_file($filepath)->xpath('//item[position() <= 10]');
(page cachée 300s dans le répertoire ./cache, évidemment pas de gestion d'une réponse 304 ou 226)

Pour finir je tiens à redire que je n'ai rien contre les frameworks en général, que j'aime bien la structure du ZF (une interface pour chaque sous-répertoire, etc...), et que j'apprécie sincèrement que titerm prenne le temps d'exposer son point de vue, que je respecte. :pouce:

Mammouth du PHP | 505 Messages

26 mars 2007, 12:18

Je ne pense pas qu'il y ait du cache transparent, mais le système de cache du ZF est bien foutu, vraiment simple a metre en oeurvre, et est capable de faire aussi bien du cache de page que du cache partiel, ou du cache de fonction, de classe etc... et il est capble de cache ou tu veux, soit dans un fichier, en ram (via apc, memcache ou zendplateforme) ou en BDD.

Ceci étant dit, je ne fais pas l'apologie du ZF non plus, je le trouve juste bien foutu et surtout vivant. Ce qui est un réel plus, tu signales un bug ou tu souhaites une evol, il y a une réaction rapide. la doc est pas trop mal foutu et surtout, il federe beaucoup de monde et donc, on peux espérer une bonne qualité de code.

Bon c'est sur que pour les feeds, si tu as un pb basique et bien définie, why not, mais j'ai trop l'habitude de faire les choses avec un point de vue industriel (deformation professionnel je suppose), mais j'ai tellement vue de cas ou on commence un truc en se disant, c pas mechant juste pour ca , ca ira.... puis le besoin evolue, le site aussi, ca monte, ca monte, et au final, on se retrouve avec un tas de nouille ingérable. Du coup, je concois systèmatiquement les choses de telle sorte qu'elle soit maintenable facilement, sutout le plus générique et evolutif possible. Avec le recul, je me rend compte que c'est payant. Le temps passé sur le début est souvent très largement rentabilisé par la suite...

le cache d'opcode ne consome pas grand chose(en ram), dans mon cas, 10 Mb pour plusieurs millier de fichier...

En revanche, 1Mb, c'est peu et beaucoup. Tjs dans une optique de serveur fortement chargé, ca peut etre énorme. C'est souvent la ram qui effondre le serveur bien avant la CPU...
Mais bon, la perf, c'est aussi mon dada et je m'egare...
Modifié en dernier par titerm le 26 mars 2007, 13:06, modifié 1 fois.

Eléphant du PHP | 299 Messages

26 mars 2007, 12:34


J'en profite pour donner ma solution "à la main" :
$url = 'http://www.langamers.ch/langamers/news.xml';
$filepath = './cache/' . md5($url);

if (@filemtime($filepath) < time() - 300)
{
	copy($url, $filepath);
}

$items = simplexml_load_file($filepath)->xpath('//item[position() <= 10]');
(page cachée 300s dans le répertoire ./cache, évidemment pas de gestion d'une réponse 304 ou 226)
Je ne pense pas avoir besoin de ca, je lit les flux rss pour les stocker dans une base de donnée...

Merci pour tout ce débat :)
Modifié en dernier par pirquessa le 26 mars 2007, 17:15, modifié 1 fois.