Recuperation météo internet [c][vc.net]

Description

Bonjour,

Voila, mon code envoie une requete http a un serveur meteo (www.weather.Com), stocke une partie du code desiré dans un fichier, recupere ses infos, les trie et les affiche a l'ecran, c tout !
La ville choisie est Nimes, mais la liste est tres longue, j'ai mis cette ville car j'y habite, mettez la ville que vous voulez !

Source / Exemple :


#include <stdio.h>
#include <windows.h>
#include <winsock.h>///weather/local/FRXX0165

#pragma comment(lib, "ws2_32.lib")

enum {FAIL, SUCCESS};

#define NBRE_SEARCH 7

//Requete HTTP
char sCmdToSend[] = "GET http://fr.w3.weather.com/weather/local/FRXX0165 HTTP/1.1\r\nAccept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*\r\nAccept -Language: fr\r\nContent-Type: application/x-www-form-urlencoded\r\nAccept -Encoding: gzip , deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 98; DigExt)\r\nHost: fr.w3.weather.com\r\nReferer : http://fr.w2.weather.com/common/jump2_fr.html?/weather/tenday/FRXX0004\r\n\r\n";
char sGood_Buffer[] = "<!-- Begin Main Content Here-->";
char sEnd_Buffer[] = "<TD COLSPAN=\"3\" ALIGN=\"CENTER\" VALIGN=\"middle\">";
//Balise entourant les commandes de 2 à 8
char sBalise_Deb[] = "<TD CLASS=\"currentObsText\">";
char sBalise_End[] = "</TD>";
//Balise entourant les 2premiers resultats (Temp et temp ressentie, Temp n'est pas dans la
//liste des cmd car elle ne figure pas dans la source de la page
char sBalise_FirstDeb[] = "\"TOP\">&nbsp;";
char sBalise_FirstEnd[] = "°C";

char sSearch[NBRE_SEARCH][30] = {	"",							//NUMERIQUE
									"Temp. ressentie",			//NUMERIQUE
									"Vent",						//NON NUMERIQUE (je sais pas comment le dire !!)
									"Point de ros",				//NUMERIQUE
									"Humidit",					//NUMERIQUE
									"Visibilit",				//NUMERIQUE
									"Pression barom" };			//NON NUMERIQUE (en effet, les données a recuperer sont numeriques mais j'ai eu quelques difficultés à cause d'un 'à' recalcitrant...
		

char sCmdFound[NBRE_SEARCH][40];

char sFile[] = "c:\\fuck.htm";

int iInitWinsock(void);
int iTreatCmd();
int iRequete(SOCKET);
char *sSearchIn(char *, const char *, const char *, const char *, int, int);
int iIsNumeric(char);

//Initialisation de Winsock
int iInitWinsock() 
{
	WORD		wVersionRequested;
	WSADATA		wsaData;
	int			iReturn = 0;

	wVersionRequested = MAKEWORD(2, 0);
	
	if (iReturn = WSAStartup(wVersionRequested, &wsaData)) {
		printf("Erreur lors de l'initialisation de winsock...\n");
		system("PAUSE");
		return FAIL; 
	}

	return SUCCESS;
}

int main(int argc, char **argv)
{
	struct		sockaddr_in sinAddr;
	struct		hostent *hstServIP;			//Stocke l'IP du serveur
	SOCKET		sckActiv;
	int			iReturn = 0;
	int			i = 0, j = 0;
	
	if (iReturn = iInitWinsock()) {										//Initialisation de winsock
		printf("Initialisation de winsock effectu\202e...\n");
	}

	sckActiv = socket(AF_INET, SOCK_STREAM, 0);							//Creation du socket

	if (!(hstServIP = gethostbyname("fr.w3.weather.com"))) {			//Recuperation de l'addresse IP du serveur
		printf("Erreur lors de la r\202solution du nom de domaine...\n");
		system("PAUSE");
		return FAIL;
	}

	sinAddr.sin_addr.s_addr = *((u_long *)hstServIP->h_addr_list[0]);	//"Stockage" de l'adresse IP convertie en unsigned long (u_long)
	sinAddr.sin_port = htons(80);										//Port 80 = HTTP
	sinAddr.sin_family = AF_INET;										//AF_INET = Protocole TCP/IP
	
	while (iReturn = connect(sckActiv, (const struct sockaddr *)&sinAddr, sizeof(sinAddr))) {	//Connexion du socket au serveur			
			printf("Impossible de se connecter au serveur...\n");
	}	
	printf("Connexion avec le serveur \202tablie...\n");

	iRequete(sckActiv);													//Envoi de la requetre HTTP et puis "stockage" d'une partie de la source dans un fichier
	iTreatCmd();														//Traite les infos contenus le fichier et stocke ces infos dans sCmdFound

	printf("M\202t\202o a N\214mes : \n");
	for (i = 0; i < NBRE_SEARCH; ++i) {
		switch (i) {
			case 0:		
				sprintf(sSearch[i], "Temp\202rature : %s Degr\202s C" , sCmdFound[i]);
				break;
			case 1: 
				sprintf(sSearch[i], "Temp. ressentie : %s Degr\202s C", sCmdFound[i]);
				break;
			case 2:
				sprintf(sSearch[i], "Vent : %s", sCmdFound[i]);
				break;
			case 3:
				sprintf(sSearch[i], "Point de ros\202e : %s Degr\202s C", sCmdFound[i]);
				break;
			case 4:		
				sprintf(sSearch[i], "Humidit\202 : %s%%" , sCmdFound[i]);
				break;
			case 5: 
				sprintf(sSearch[i], "Visibilit\202 : %s km", sCmdFound[i]);
				break;
			case 6:
				sprintf(sSearch[i], "Pression barom\202trique : %s", sCmdFound[i]);
				break;
		}
		printf("%s\n", sSearch[i]);
	}

	closesocket(sckActiv);								//Fermeture du socket que l'on peut preceder de la fonction shutdown, mais ce n'est pas obligatoire...shutdown permet de "mettre en veille" la socket
	WSACleanup();										//Ferme Winsock

	system("PAUSE");
	return SUCCESS;

}
// <TD CLASS="currentObsText">....</TD>

int iRequete(SOCKET sckOpen) 
{
	FILE		*fSave;				
	char		sPacket[8192];		//8192octets = limite de la taille d'un packet
	char		*sBuffer = NULL;	//Pointeur sur sPacket 
	char		*sRet_Str = NULL;	//Pointeur char pour retour fonction strstr
	int			iRecup_Buf = 0;		//Flag indiquant si le prog soit stocker le packet (sPacket) dans le fichier
	int			iReturn = 0;		//Nbre d'octets recus par la fonction recv

	send(sckOpen, sCmdToSend, sizeof sCmdToSend, 0);	//Envoie de la requete http	
	fSave = fopen(sFile, "w");							//Ouvre le fichier en mode ecriture

	while (iReturn = recv(sckOpen, sPacket, sizeof sPacket, 0)) {	//Tant ke recv n'est pas nul (donc kon recoit un packet)
		sBuffer = sPacket;											//	sBuffer pointe maintenant sur sPacket
		if (!iRecup_Buf) {											//	Si iRecup_Buf est nul
			if (sRet_Str = strstr(sBuffer, sGood_Buffer)) {			//		Si dans le packet se trouve la "balise" sGood_Buffer (permettant de couper la source au nivo des infos interessantes)
				iRecup_Buf = 1;										//			Mise a 1 du flag iRecup_Buf permettant de "dire" au prog kil doit recuperer les packets suivants
				sBuffer = sRet_Str;									//			sBuffer pointe alors sur la balise sGood_Buffer (dont l'adresse a été renvoyée par strstr)
				fputs(sBuffer, fSave);								//			Ecriture dans le fichier du packet
			}														//		Fin si
		} else {													//	Fin Si, Sinon	(si iRecup_Buf n'est pas nul donc ke la balise de depart (sGood_Buffer) a été trouvé)	
			if (sRet_Str = strstr(sBuffer, sEnd_Buffer)) {			//		Si la balise de fin (sEnd_Buffer) est presente dans le packet
				sRet_Str[0] = 0;									//			Mettre a zero le premier caractere de la chaine renvoyée par strstr permet de "couper la chaine" a la balise de fin (Pour ne conserver ke les infos necessaires)
				iRecup_Buf = 0;										//			Mettre a zero iRecup_Buf pour signaler ke le prog ne doit plus recuperer de packet (ayant trouve le dernier)
			}														//		Fin Si
			fputs(sBuffer, fSave);									//		Peu importe que la balise de fin soit trouvée, il faut, si iRecup_Buf n'est pas nul, ecrire le packet dans le fichier
		}															//	Fin Si
		memset(sPacket, 0, sizeof sPacket);							//	Mettre zero tous les octets de sPacket
		sBuffer = NULL;												//	sBuffer ne pointe plus sur rien
	}																//Fin while
	fclose(fSave);													//Fermer le fichier

	return SUCCESS;
}

int iTreatCmd()
{
	FILE		*fCmd;
	char		*sLine = NULL;
	char		*sRet_Search = NULL;
	char		*sBalise_Dep = sBalise_FirstDeb;	//On initialise le pointeur de Balise de depart avec sBalise_FirstDeb car les 2 premiers commandes a trouver debutent par cette balise
	char		*sBalise_Arr = sBalise_FirstEnd;	//Et au final, sont finis par cette balise
	int			iReturn = 0;
	int			iNumeric = 1;						//Valeur passée en argument de la fonction sSearchIn ki permet de dire le les infos a recuperer sont de type numerik
	int			i = 0;	

	sLine = calloc(4608, sizeof(char));				//Alloue 4608octets au pointeur sLine, et initialise tous les octets a 0
	fCmd = fopen(sFile, "r");						//Ouvre le fichier en mode lecture
		
	iReturn = fread(sLine, sizeof(char), 4608, fCmd);	//Lis la totalité du fichier, iReturn renvoie le nombre d'octets lus
	sLine[iReturn] = 0;									//A l'élément iReturn, place le caractere de fin de chaine '\0' (ou 0)
		
	for (i = 0; i < NBRE_SEARCH; ++i) {						//Tant ke i est inferieur au nombre de commandes...
		if (i == 1) {										//Si i == commande("Temp. Ressentie")
			sBalise_Dep = strtok(sBalise_Dep, "\"TOP\">");	//	"Decouper" une partie de la balise sBalise_Dep car elle ne correspond pas a la balise de depart de cette commande
		} else if (i == 2 || i == 6) {						//Si i == commande("Vent" ou "Pression barométrique")
			iNumeric = 0;									//	Mettre a 0 le flag iNumeric permettant de dire a la fonction sSearchIn que les infos a recuperer sont numerik
			if (i == 2) {									//	Si et seulement si i == commande("Vent")
				sBalise_Dep = sBalise_Deb;					//		Changer les balise de depart 
				sBalise_Arr = sBalise_End;					//		Et de fin
			}												//	Fin Si	
		} else {											//Fin Si, Sinon (si i != 1, 2 ou 6)
			iNumeric = 1;									//		Mettre a 1 le flag iNumeric	
		}													//Fin Si
		if (sRet_Search = sSearchIn(sLine, sSearch[i], sBalise_Dep, sBalise_Arr, i, iNumeric)) {	//Si la fonction sSearchIn renvoie un pointeur non NULL
			sLine = sRet_Search;																	//	Faire pointer sLine sur la valeur de retour de sSearchIn (ki a été "decoupé" dans cette fonction ce qui permet de reduire le champ de recherche d'une commande)
		}																							//Fin Si
	} 
	sRet_Search = NULL;			//sRet_Search point sur du vent !
	fclose(fCmd);				//Fermer le fichier
	//free(sLine);*/			//J'alloue de la memoire dinamikement, mais le free ne marche po, je pense ke c du au fait ke je le fais pointer sur d'autres donnée...

	return SUCCESS;
}

char  *sSearchIn(char *sIn, const char *sCmd, const char *sBalise_D, const char *sBalise_E, int iNum_Cmd, int IsNumeric)
{
	char		*sRet_Str = NULL;
	char		*sDeb_Str = NULL;
	char		*sFin_Str = NULL;
	int			i = 0;
	
	if (sRet_Str = strstr(sIn, sCmd)) {							//Cherche la commande dans le fichier
		sIn = sRet_Str + strlen(sCmd);							//sIn "saute" la commande
		if (sDeb_Str = strstr(sIn, sBalise_D)) {				//Cherche la premiere balise
			sDeb_Str += strlen(sBalise_D);
			sIn = sDeb_Str;										//sIn "saute" la balise
			if (IsNumeric) {									//Si l'argument est IsNumeric > 0 alors rechercher les infos "numeriques"
				while (iIsNumeric(*sIn)) {						//Tant que les caracteres sont numeriques; les recuperer...
					sCmdFound[iNum_Cmd][i++] = sIn[0];
					sIn++;
				}
			} else {											//Si les données a recuperer ne sont pas numeriques
				if (sFin_Str = strstr(sIn, sBalise_E)) {		//Recherche de la balise de fin
					while (sFin_Str - sDeb_Str) {				
						sCmdFound[iNum_Cmd][i++] = sDeb_Str[0];	//Recuperation des infos
						sDeb_Str++;
					}
				}
			}
            sCmdFound[iNum_Cmd][i] = 0;
		}
	}

    return sIn;

}

//Teste si le caractere en argument est numerique ou pas
int iIsNumeric(char cInt)
{
	if (cInt >= '0' && cInt <='9') {		
		return SUCCESS;
	}
	return FAIL;
}

Conclusion :


C un code compilé avec VC.net, mais doit etre compatible avec gcc ou vc6, j'ai pas testé...C bien sur un code avec Winsock...
J'attends des remarques sur le prog lui mm, mais plus precisement sur la fonction sSearchIn et encore plu particulierement des boucles While, car je ne sais pas si la maniere dont j'ai traité le pb est bien, ou tres lente, enfin je veux savoir si ce ke j'ai fait est correct ou totalement a revoir...

Mettez des commentaires plz !!

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.