Jean-Francois Ortolo
2008-07-22 20:46:59 UTC
Bonjour
Je fais du chargement de données de sites externes par des fonctions
de socket telles que fsockopen, suivie de fputs ( pour la requête )
puis de fgets ( pour le header ), puis de fread pour les données.
J'utilise les fonctions données par un Américain sur les commentaires
de la fonction fsockopen(), dans le PHP Manual.
En gros, voici le code:
$fp = fsockopen($host, 80, &$errno, &$errstr, 300);
// test sur $fp en cas d'erreur.
// pour fixer le timeout sur les données
stream_set_timeout($fp, 3000);
// le header est en mode HTTP 1.1 obligatoire,
// le serveur n'accepte que cela.
$send = $contenu_de_l_header;
fputs($fp, $send);
unset($send);
$send = '';
do
{
$send .= fgets($fp, 4096);
}while( strpos($send, "\r\n\r\n") === false)
// Première fonction de l'Américain,
// pour détecter les contenus chunked,
// et permettre la décompression si besoin
// lors de la lecture des données.
$info=decode_header($send);
unset($send);
$send = '';
while(!feof($fp))
{
// il faut un fread pour interpréter le contenu
// brut en binaire.
$send .= fread($fp, 16384);
}
fclose($fp);
// Deuxième fonction de l'Américain,
// elle interprète les contenus chunked ou compressés,
// et les restitue suivant ce qu'indique le contenu
// de l'header.
$send = decode_body($info, $send);
// Enfin, on met le contenu
// dans une array.
unset($var);
$var = split("[\n]", $send);
// Et voila, le contenu de la page html
// est dans la variables indicée, ligne par ligne.
// ***********************************************
Donc, voici mon problème:
Tout se passe comme si les données dans certains cas ( aléatoires )
n'alimentaient pas correctement la variable $var, qui ne contient pas
la balise <head>, détectée par eregi("<head>", $donnee)
Cependant, j'ai mis un timeout de 300 secondes à l'ouverture du
socket ( d'ailleurs c'est sûr que le socket est ouvert, car le
traitement d'erreur ne détecte rien ), ce qui largement suffisant car le
paramètre $host est en réalité l'adresse ip en dur, qui est correcte.
De plus j'ai spécifié un time out pour les données de 3000 secondes,
soit 50 minutes, et d'ailleurs le timeout apparent réel, est de l'ordre
de 3 ou 4 minutes.
Je lance ces chargements de manière répétitive pour différentes pages
du même site, et à peu près une fois sur 7 ou 8 ( aléatoire ), la balise
<head> n'est pas détectée dans la variable indicée $var[]
Je parcours la variables $var avec un indice de 0 à (count($var) -
1), ce qui devrait être correct.
Je fais subir à chaque lignes rencontrées, une conversion de
utf-8vers iso-8859-15 avec la fonction decode faite de cette manière:
function decode($var) {
$send = ereg_replace("\r$", "", $var);
$send1 = iconv("UTF-8",
"ISO-8859-15//TRANSLIT//IGNORE", $send);
$send2 = str_replace(chr(189), "oe", $send1);
$send3 = str_replace("\r", "", $send2);
return($send3);
}
Donc en gros, à chaque lecture de ligne:
unset($donnee);
$donne = decode($var[$k]);
Donc, je fais:
$trouve = false;
for($i = 0; $i < count($var); $i++)
{
unset($donnee);
$donnee = decode($var[$i]);
// pour sortir de la boucle
if(eregi("<\/html>", $donnee))
break;
// pour débuter le traitement
if(eregi("<head>", $donnee))
$trouve = true;
if($trouve)
{
// Traitement...
}
}
Le problème, c'est que dans certains cas, le traitement ne se fait
pas du tout.
Il ne devrait pas y avoir de problème, les données sont des pages
html en utf-8, qui devraient bien être traduites en iso par la fonction
decode(). D'ailleurs pour un autre site du même genre, çà marche.
D'où vient l'erreur ? ;)
Merci beaucoup de vos réponses.
Bien à vous.
Amicalement.
Jean-François Ortolo
Je fais du chargement de données de sites externes par des fonctions
de socket telles que fsockopen, suivie de fputs ( pour la requête )
puis de fgets ( pour le header ), puis de fread pour les données.
J'utilise les fonctions données par un Américain sur les commentaires
de la fonction fsockopen(), dans le PHP Manual.
En gros, voici le code:
$fp = fsockopen($host, 80, &$errno, &$errstr, 300);
// test sur $fp en cas d'erreur.
// pour fixer le timeout sur les données
stream_set_timeout($fp, 3000);
// le header est en mode HTTP 1.1 obligatoire,
// le serveur n'accepte que cela.
$send = $contenu_de_l_header;
fputs($fp, $send);
unset($send);
$send = '';
do
{
$send .= fgets($fp, 4096);
}while( strpos($send, "\r\n\r\n") === false)
// Première fonction de l'Américain,
// pour détecter les contenus chunked,
// et permettre la décompression si besoin
// lors de la lecture des données.
$info=decode_header($send);
unset($send);
$send = '';
while(!feof($fp))
{
// il faut un fread pour interpréter le contenu
// brut en binaire.
$send .= fread($fp, 16384);
}
fclose($fp);
// Deuxième fonction de l'Américain,
// elle interprète les contenus chunked ou compressés,
// et les restitue suivant ce qu'indique le contenu
// de l'header.
$send = decode_body($info, $send);
// Enfin, on met le contenu
// dans une array.
unset($var);
$var = split("[\n]", $send);
// Et voila, le contenu de la page html
// est dans la variables indicée, ligne par ligne.
// ***********************************************
Donc, voici mon problème:
Tout se passe comme si les données dans certains cas ( aléatoires )
n'alimentaient pas correctement la variable $var, qui ne contient pas
la balise <head>, détectée par eregi("<head>", $donnee)
Cependant, j'ai mis un timeout de 300 secondes à l'ouverture du
socket ( d'ailleurs c'est sûr que le socket est ouvert, car le
traitement d'erreur ne détecte rien ), ce qui largement suffisant car le
paramètre $host est en réalité l'adresse ip en dur, qui est correcte.
De plus j'ai spécifié un time out pour les données de 3000 secondes,
soit 50 minutes, et d'ailleurs le timeout apparent réel, est de l'ordre
de 3 ou 4 minutes.
Je lance ces chargements de manière répétitive pour différentes pages
du même site, et à peu près une fois sur 7 ou 8 ( aléatoire ), la balise
<head> n'est pas détectée dans la variable indicée $var[]
Je parcours la variables $var avec un indice de 0 à (count($var) -
1), ce qui devrait être correct.
Je fais subir à chaque lignes rencontrées, une conversion de
utf-8vers iso-8859-15 avec la fonction decode faite de cette manière:
function decode($var) {
$send = ereg_replace("\r$", "", $var);
$send1 = iconv("UTF-8",
"ISO-8859-15//TRANSLIT//IGNORE", $send);
$send2 = str_replace(chr(189), "oe", $send1);
$send3 = str_replace("\r", "", $send2);
return($send3);
}
Donc en gros, à chaque lecture de ligne:
unset($donnee);
$donne = decode($var[$k]);
Donc, je fais:
$trouve = false;
for($i = 0; $i < count($var); $i++)
{
unset($donnee);
$donnee = decode($var[$i]);
// pour sortir de la boucle
if(eregi("<\/html>", $donnee))
break;
// pour débuter le traitement
if(eregi("<head>", $donnee))
$trouve = true;
if($trouve)
{
// Traitement...
}
}
Le problème, c'est que dans certains cas, le traitement ne se fait
pas du tout.
Il ne devrait pas y avoir de problème, les données sont des pages
html en utf-8, qui devraient bien être traduites en iso par la fonction
decode(). D'ailleurs pour un autre site du même genre, çà marche.
D'où vient l'erreur ? ;)
Merci beaucoup de vos réponses.
Bien à vous.
Amicalement.
Jean-François Ortolo