• 0

PHP - Making it faster


Question

Hi Im a total amateur at PHP : )

Ive created a script that pulls weather data from a website.

$get_dundee = file_get_contents('http://api.wunderground.com/weatherstation/WXCurrentObXML.asp?ID=IDUNDEE2');
$find_temp_dundee = strpos($get_dundee, '<temp_c>');
$temp_dundee = substr($get_dundee, $find_temp_dundee, 20);

$get_status_dundee = file_get_contents('http://www.wunderground.com/global/stations/03163.html');
$find_status_dundee = strpos($get_status_dundee, '<div class="b" style="font-size: 14px;">');
$status_dundee = substr($get_status_dundee, $find_status_dundee, 60);

echo $temp_dundee;
echo $status_dundee;

This works but I was wondering if there is a way to make it work faster / more seamlessly.

Link to comment
Share on other sites

22 answers to this question

Recommended Posts

  • 0

OK, just looked and yes, the XML doesn't contain the textual description of the weather (eg. "Partly cloudy")...

So why not grab BOTH from the HTML page? It does contain the text as well as the temperature...?

Link to comment
Share on other sites

  • 0

I don't about faster, or even simpler, but... Actually, I cant really think of why I did it this way. :blush:

function get_yahoo_weather($code, $units = 'c', $endpoint = 'http://weather.yahooapis.com/forecastrss'){

	$xml = new SimpleXMLElement(
 	sprintf(
 	'%s?w=%s&u=%s',
 	$endpoint,
 	$code,
 	$units
 	),
 	null,
 	true
	);

	if(false === ($xml instanceof SimpleXMLElement)){
 	return false;
	}

	$nodes = array(
 	array(
 	'xpath' 	=> '//yweather:location/@city',
 	'attribute' => 'city',
 	'name' 	=> 'city'
 	),
 	array(
 	'xpath' 	=> '//yweather:condition/@text',
 	'attribute' => 'text',
 	'name' 	=> 'status'
 	),
 	array(
 	'xpath' 	=> '//yweather:condition/@temp',
 	'attribute' => 'temp',
 	'name' 	=> 'temp'
 	)
	);

	$return = array();

	foreach($nodes as $node){
 	$result = array_shift(
 	$xml->xpath($node['xpath'])
 	);
 	$return[$node['name']] = (string)$result[$node['attribute']];
	}

	return $return;
}

print_r(
	get_yahoo_weather(
 	'18637'
	)
);

/*
	Array
	(
 	[city] => Dundee
 	[status] => Partly Cloudy
 	[temp] => 8
	) 
*/

Strange, my enter key isn't working on Neowin! Weird indeed. The code highlighting is pretty poor too whilst I'm whining! :p

Link to comment
Share on other sites

  • 0

Ok thanks for that but can you please include how to print out individual parts of the array : )

The output currently is : Array ( [city] => Dundee [status] => Partly Cloudy [temp] => 8 )

How would I print out Partly Cloudy and 8?

Link to comment
Share on other sites

  • 0

Something along the lines of:

$weather = get_yahoo_weather('18637');
echo $weather['status'];
echo $weather['temp'];

Untested, but should work with the above function.

Link to comment
Share on other sites

  • 0

@ Mouldy That gives me the temperature again =)

Yeah, 'cause that's exactly what you asked for. You really need to learn the absolute basics of PHP. We're talking about simple array access here.
Link to comment
Share on other sites

  • 0

@ boogerjones I agree but I find reading tutorials sometimes really not helpful, I learn how to do it best when it's done and I can see exactly what syntax is used. I'm not lazy it's just how I learn things :)

Link to comment
Share on other sites

  • 0

Wait...I'm confused. You asked how to output something like "Partly Cloudy and 8" and the code I posted does that. What's the problem exactly?

@ boogerjones I agree but I find reading tutorials sometimes really not helpful, I learn how to do it best when it's done and I can see exactly what syntax is used. I'm not lazy it's just how I learn things :)

Very few people can learn how to program from reading alone. The idea of tutorials isn't to just read them. You have to do them too. If you're not doing tutorials and instead skim-read them and expect to be spoon-fed the exact syntax to do exactly what you want, I'd say that is pretty lazy. The non-lazy way would be to do a few tutorials, then apply what you've learnt into different situations that better fit exactly what you want to do.

Link to comment
Share on other sites

  • 0

@ Mouldy Everyone is entitled to their opinion =)

Sorry for not making this clearer. What I want is to print out the status of the weather, for example Cloudy or something like that. Then with an if statement I'll use that information to change an image (pretty sure I can do this myself). The problem is that I'm not sure as to how to get a variable to equal the status. I'm not exactly sure what to look for in terms of tutorials either, what would you call it.

Trying to learn :)

Link to comment
Share on other sites

  • 0

You want to get the status for Dundee?

If so, on the page it says this...

Current Conditions:

Clear, 2 C

You want to get only the "Clear" from the current conditions?

Link to comment
Share on other sites

  • 0

Best way is ultimately caching the data and updating it when needed. Think about how much work that file_get_contents does (establish TCP connection, send request, wait for response, reply and close connection). The simplest thing to do is to store that file you are retrieving locally, and reading from it instead of the site. Then, when a set amount of time passes, it will re-download that data and replace the file with new contents. This will make it run at the current speed for the unlucky person who gets there when an update is needed, but the rest will be blazing fast.

Link to comment
Share on other sites

  • 0

@ Zivan How would I do that, I didn't know PHP would do that

Here is a rather simple example, read the comments and I think you should understand, I am no expert, there might be a lot better ways to do this but I am pretty happy with the results.

Although, one might want to update the status more than once an hour, yahoo update their conditions far more often than that

<?php
$file_lastupdate = fopen("lastupdate.txt", "r+"); //opens the file lastupdate.txt and makes it accesable trough $file_lastupdate
$file_weathercache = fopen("weathercache.txt", "r+"); //opens the file weathercache.txt and makes it accesable trough $file_weathche.txt
$lastupdate = file_get_contents("lastupdate.txt"); //gets the contents of the fie lastupdate and saves the contents to $lastupdate

if(date(H)>$lastupdate) //compares the current hour to the one saved in the file lastupdate.txt, if the current hour is higher the cache will be updated
{
	$update_yahoo_weather = file_get_contents('http://weather.yahoo.com/scotland/tayside/dundee-18637/'); //gets the contents form yahoos servers
	$find_forecast = strpos($update_yahoo_weather, '<div id="yw-cond">')+18; //finds where on the site the content we want, the current conditions, start
	$find_status_end = strpos($update_yahoo_weather, '</div>', $find_forecast); //find where the crrent condition end
	$status_length = $find_status_end - $find_forecast; //calculates the length of the current conditions


	fwrite($file_weathercache, substr($update_yahoo_weather, $find_forecast, $status_length)); //uses the conditons starting position and length to get the current conditions from yahoo and save them to our local cache file
	fwrite ($file_lastupdate, date(H)); //writes the current hour to the files lastupdate.txt
}

$weathercache = file_get_contents("weathercache.txt"); //gets the content of the cachefile and savs to $weathercache
echo $weathercache; //types out the cached conditions
?>

Make sure you create the two files needed on the server first since this script wont do that for your.

If you want to know more about what PHP can do with files on the server take a look here http://www.w3schools.com/php/php_ref_filesystem.asp

Link to comment
Share on other sites

  • 0

Here is a rather simple example, read the comments and I think you should understand, I am no expert, there might be a lot better ways to do this but I am pretty happy with the results.

Although, one might want to update the status more than once an hour, yahoo update their conditions far more often than that

Closing the file with fclose could be smart. With file_get_contents can be expected possible timeout problems. Either setting timeout or using curl is almost must if the script is called from the public page directly. The updating could be done with cronjob, leaving only showing to the public page, that removes all the problems. Also, then using timeout settings is way safer and won't crash the accessed side of the site. Making better "spireding" with cURL don't have effect either and can be freely used.

Link to comment
Share on other sites

  • 0

you mean i should have flcose() at the end of the script?? ok, well i am kinda new to using files too, kinda assumed the would be like the connection to a database and be closed automatically at the end of the script

Link to comment
Share on other sites

  • 0

Here's what I'd do (using curl):

First create a simple function in another php file and use an include statement in the file(s) you wish to use it (I like to keep things clean and simple), here's a simple function I created.

function weatherCapture() {
	$ch = curl_init("http://weather.yahooapis.com/forecastrss?w=18637&u=c");
        curl_setopt($ch, CURLOPT_HEADER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
        $result = curl_exec ($ch);
        $data = strstr($result, '<?');

        $xml = new SimpleXMLElement($data);

        return $xml;
}

Then I'd use a few simple lines of code to select which information I'd want to be pulled from Yahoo and echo this info

$weather = weatherCapture();

$currentCondition = $weather->xpath("//yweather:condition");
$currentDescription = $currentCondition[0]["text"];
$currentTemperature = $currentCondition[0]["temp"];
$currentCode = $currentCondition[0]["code"];

echo "<p>$currentDescription</p>"; //This echos the current weather (sunny, cloudy, etc.)
echo "<p>$currentTemperature</p>"; //This echos the current temperature (3, 8, etc.)
echo "<img src=\"http://l.yimg.com/a/i/us/we/52/$currentCode.gif\" />"; //This uses the given code tag to use the correct Yahoo image

This is just a small example I put together, obviously there are many ways this can be done and much more can be done with the API, if you seek anymore help or other suggestions, just ask :)

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.