You are here

weather_es_parser.inc in Weather_es 6.2

Same filename and directory in other branches
  1. 5 weather_es_parser.inc
  2. 6 weather_es_parser.inc

Gets the data from the AEMET web

The module is compatible with Drupal 6.x

@author José Mª Sirvent

File

weather_es_parser.inc
View source
<?php

/**
 * Weather_es shows the weather forecast of 8112 cities of Spain using the AEMET web information.
 * Copyright (C) 2008 José Mª Sirvent <drupal@hykrion.com>
 *
 * This file is part of the Drupal weather_es module.
 * It is based on the Weather module which was written in 2006 by
 * Tobias Toedter <t.toedter@gmx.net>.
 *
 * Weather_es is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Weather_es is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Weather_es; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

/**
 * @file
 * Gets the data from the AEMET web
 *
 * The module is compatible with Drupal 6.x
 *
 * @author José Mª Sirvent
 */

/**
 * Clean the data and save it
 */
function _weather_es_aemet($wuid, $city_cod, $lan, $city_nam) {

  // Raw data of AEMET
  $aemet = -1;
  $array_text = _weather_es_retrieve_data($wuid, $city_cod, $lan, $city_nam);
  if ($array_text != -1) {
    for ($i = 0; $i < sizeof($array_text[0][0]); $i++) {

      // Data type
      preg_match_all('/<th.+th>/U', $array_text[0][0][$i], $captured_th);
      preg_match('/>.+</', $captured_th[0][0], $data);
      $data_lon = strlen($data[0]);
      $ori_data_type[] = substr($data[0], 1, $data_lon - 2);

      // Dates
      if (preg_match('/abbr="Fec\\."|abbr="Dat."/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<th.+th>/U', $array_text[0][0][$i], $captured_th);
        for ($j = 1; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/>.+</', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          $ori_str = substr($data[0], 1, $data_lon - 2);
          $htm_str = htmlentities($ori_str);
          $days[] = $htm_str;
        }
      }
      elseif (preg_match('/abbr="[ap]m\\."/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<th.+th>/U', $array_text[0][0][$i], $captured_th);
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/>.+</', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          $ampm[] = substr($data[0], 1, $data_lon - 2);
        }
      }
      elseif (preg_match('/abbr="Cielo"/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<td.+td>/U', $array_text[0][0][$i], $captured_th);

        // Images
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/[0-9]{2}.gif/', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          $sky_img[] = substr($data[0], 0, $data_lon - 4);
        }

        // Text
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/alt=".+"/', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          $sky_txt[] = substr($data[0], 5, $data_lon - 6);
        }
      }
      elseif (preg_match('/abbr="Pro\\."/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<td.+td>/U', $array_text[0][0][$i], $captured_th);
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/>[0-9]{1,3}/', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          $rain[] = substr($data[0], 1, $data_lon);
        }
      }
      elseif (preg_match('/abbr="Cot\\."/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<td.+td>/U', $array_text[0][0][$i], $captured_th);
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/>[0-9]{1,4}/', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          if (sizeof($data[0]) != 0) {
            $snow[] = substr($data[0], 1, $data_lon);
          }
          else {
            $snow[] = 9999;
          }
        }
      }
      elseif (preg_match('/abbr="Max\\."/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<td.+td>/U', $array_text[0][0][$i], $captured_th);
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/>[0-9]{1,4}/', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          $tmax[] = substr($data[0], 1, $data_lon);
        }
      }
      elseif (preg_match('/abbr="Min\\."/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<td.+td>/U', $array_text[0][0][$i], $captured_th);
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/>-?[0-9]{1,4}/', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          $tmin[] = substr($data[0], 1, $data_lon);
        }
      }
      elseif (preg_match('/abbr="Vie\\."/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<td.+td>/U', $array_text[0][0][$i], $captured_th);
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/alt=".+"/', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          $win_dir[] = substr($data[0], 5, $data_lon - 6);
        }
      }
      elseif (preg_match('/abbr="km\\/h\\."/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<td.+td>/U', $array_text[0][0][$i], $captured_th);
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/>[0-9]{1,4}/', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          $win_spd[] = substr($data[0], 1, $data_lon);
        }
      }
      elseif (preg_match('/abbr="UV"/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<td.+td>/U', $array_text[0][0][$i], $captured_th);
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/[0-9]{1,2}</', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          if ($data_lon != 0) {
            $ui[] = substr($data[0], 0, $data_lon - 1);
          }
          else {
            $ui[] = 99;
          }
        }
      }
      elseif (preg_match('/abbr="Aviso"/', $array_text[0][0][$i], $abbr)) {
        preg_match_all('/<td.+td>/U', $array_text[0][0][$i], $captured_th);
        for ($j = 0; $j < sizeof($captured_th[0]); $j++) {
          preg_match('/alt=".+?"/', $captured_th[0][$j], $data);
          $data_lon = strlen($data[0]);
          $ori_rsk[] = substr($data[0], 5, $data_lon - 6);
        }
      }
    }
    if (!isset($snow)) {
      for ($i = 0; $i < 7; $i++) {
        $snow[$i] = 9999;
      }
    }
    for ($i = 2; $i < sizeof($ori_data_type); $i++) {
      $htm_str = htmlentities($ori_data_type[$i]);
      $htm_str = strtr($htm_str, array(
        '&amp;' => '&',
      ));
      $data_type[] = $htm_str;
    }
    for ($i = 0; $i < sizeof($ori_rsk); $i++) {
      $htm_str = htmlentities($ori_rsk[$i]);
      $rsk[] = $htm_str;
    }
    $aemet = array(
      $days,
      $ampm,
      $data_type,
      $sky_img,
      $sky_txt,
      $rain,
      $snow,
      $tmax,
      $tmin,
      $win_dir,
      $win_spd,
      $ui,
      $rsk,
    );
  }
  return $aemet;
}

/**
 * Get the data from AEMET
 */
function _weather_es_retrieve_data($wuid, $city_cod, $lan, $cit_nam) {
  global $user;
  $response = -1;

  // Web direction example (until 2009/12/10): http://www.aemet.es/es/eltiempo/prediccion/localidades?l=03410&p=03
  // New web direction example: http://www.aemet.es/es/eltiempo/prediccion/localidades/jijona-xixona-03410
  // www.aemet.es: 193.144.152.138
  // Languages are: es, ca/va, gl, eu, en and fr.
  // This is what we get from the bad boys of aemet (30-01-2010)

  /*
  <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
  <html><head>
  <title>301 Moved Permanently</title>
  </head><body>
  <h1>Moved Permanently</h1>
  <p>The document has moved <a href="http://www.aemet.es/es/eltiempo/prediccion/localidades/Aramaio-01030">here</a>.</p>
  </body></html>
  */

  // Handle city name...
  $cit_nam = drupal_strtolower($cit_nam);
  $cit_nam = _weather_es_city_name($cit_nam);
  $page = '/' . $lan . '/eltiempo/prediccion/localidades/' . $cit_nam . '-' . $city_cod . '.htm';
  $url = 'http://www.aemet.es' . $page;

  //$url = 'http://localhost/josem/jijona-xixona-03410.htm';
  if (function_exists('fsockopen')) {
    $result = drupal_http_request($url);
    switch ($result->code) {
      case '200':
      case '304':

        // Get the table
        preg_match('/<table.+table>/s', $result->data, $captured);

        // Pass it to a string
        $data_string = implode(" ", $captured);
        $length = strlen($data_string);
        $position = strpos($data_string, "table>");
        $data_string = substr($data_string, 0, $position - $length);
        $clean_string = preg_replace('/[ \\f\\r\\t\\n]+/', ' ', $data_string);

        //preg_match_all('/<tr.+tr>/sU', $data_string, $captured_tr);
        preg_match_all('/<tr.+tr>/sU', $clean_string, $captured_tr);
        $response = array(
          $captured_tr,
        );
        break;
      case '301':
      case '302':
      case '307':
        $result = drupal_http_request('http://www.aemet.es' . $result->redirect_url);

        // Get the table
        preg_match('/<table.+table>/s', $result->data, $captured);

        // Pass it to a string
        $data_string = implode(" ", $captured);
        $length = strlen($data_string);
        $position = strpos($data_string, "table>");
        $data_string = substr($data_string, 0, $position - $length);
        $clean_string = preg_replace('/[ \\f\\r\\t\\n]+/', ' ', $data_string);

        //preg_match_all('/<tr.+tr>/sU', $data_string, $captured_tr);
        preg_match_all('/<tr.+tr>/sU', $clean_string, $captured_tr);
        $response = array(
          $captured_tr,
        );
        break;
      default:
        if ($user->uid) {
          drupal_set_message(t('fsockopen fail to open AEMET.'), 'error');
        }
    }
  }
  else {
    if ($user->uid) {
      drupal_set_message(t('Function fsockopen does not exist, you can\'t use this module...'), 'error');
    }
  }
  return $response;
}

/**
 * Get the user configuration
 */
function _weather_es_get_config($uid) {
  $sql = "SELECT cod_pro, cod_loc FROM {weather_es_config} WHERE uid = %d";
  $result = db_query($sql, $uid);
  while ($data = db_fetch_object($result)) {
    (string) ($cities[] = $data->cod_pro . $data->cod_loc);
  }
  return $cities;
}

/**
 * Get the diferent cities of the user
 */
function _weather_es_filter_cities($loc, $cit) {
  $user_cities = array();
  for ($i = 0; $i < sizeof($cit); $i++) {

    // Upper PHP 4.0.6

    //if (array_key_exist($cit[$i], $arrayOfKeys))
    if (key_exists($cit[$i], $loc)) {
      $user_cities[] = $loc[$cit[$i]];
    }
  }
  return $user_cities;
}

/**
 * Next data update. AEMET refresh the data at Spanish local time, about 07:00am
 *
 * Using this code your server will look for the AEMET data once a day but I think its too much
 * overhead to avoid getting the data from AEMET Web 6 times a day...
 */
function _weather_es_next_act() {
  $now = spanish_time();
  $hour = strftime('%H', $now);
  $dif = 7 - $hour;
  if ($dif >= 0) {
    $next_act_in = $dif;
  }
  else {
    $next_act_in = 24 - $hour + 7;
  }
  $ran = rand(0, 60) * 60;
  $next_act_in *= 3600;
  $next_act = $now + $next_act_in + $ran;
  return $next_act;
}

/**
 * Return the Spanish (peninsula) time
 */
function spanish_time() {

  // get the server time and change it to Spanish time
  if (function_exists('date_default_timezone_get')) {
    $server_time = date_default_timezone_get();
    date_default_timezone_set('Europe/Madrid');
  }
  else {
    $server_time = ini_get('date.timezone');
    ini_set('date.timezone', 'Europe/Madrid');
  }
  $now = time();

  // save the original server timezone
  if (function_exists('date_default_timezone_set')) {
    date_default_timezone_set('$server_time');
  }
  else {
    ini_set('date.timezone', '$server_time');
  }
  return $now;
}

/**
 * Redirect the user to his correct path
 */
function _weather_es_redirect($wuid) {

  // User cities list
  if ($wuid == 0) {
    $path = 'admin/settings/weather_es';
  }
  else {
    $path = 'user/' . $wuid . '/weather_es';
  }
  return $path;
}

/**
 * Available provinces
 */
function _weather_es_provincies() {
  $provincies = array(
    '00' => "---",
    '15' => "A Coruña",
    '01' => "Álava",
    '02' => "Albacete",
    '03' => "Alicante",
    '04' => "Almería",
    '33' => "Asturias",
    '05' => "Ávila",
    '06' => "Badajoz",
    '08' => "Barcelona",
    '09' => "Burgos",
    '10' => "Cáceres",
    '11' => "Cádiz",
    '39' => "Cantabria",
    '12' => "Castellón",
    '51' => "Ceuta",
    '13' => "Ciudad Real",
    '14' => "Córdoba",
    '16' => "Cuenca",
    '17' => "Girona",
    '18' => "Granada",
    '19' => "Guadalajara",
    '20' => "Guipúzcoa",
    '21' => "Huelva",
    '22' => "Huesca",
    '07' => "Illes Balears",
    '23' => "Jaén",
    '26' => "La Rioja",
    '35' => "Las Palmas",
    '24' => "León",
    '25' => "Lleida",
    '27' => "Lugo",
    '28' => "Madrid",
    '29' => "Málaga",
    '52' => "Melilla",
    '30' => "Murcia",
    '31' => "Navarra",
    '32' => "Ourense",
    '34' => "Palencia",
    '36' => "Pontevedra",
    '37' => "Salamanca",
    '38' => "Santa Cruz de Tenerife",
    '40' => "Segovia",
    '41' => "Sevilla",
    '42' => "Soria",
    '43' => "Tarragona",
    '44' => "Teruel",
    '45' => "Toledo",
    '46' => "Valencia",
    '47' => "Valladolid",
    '48' => "Vizcaya",
    '49' => "Zamora",
    '50' => "Zaragoza",
  );
  return $provincies;
}

/**
 * Available cities.
 */
function _weather_es_cities($pro) {
  $sql = "SELECT * FROM {weather_es_aemet} wea WHERE wea.cod_pro = %d";
  $result = db_query($sql, $pro);
  while ($row = db_fetch_array($result)) {
    $aemet_cod = $row['cod_pro'] . $row['cod_loc'];
    $cities[$aemet_cod] = $row['cit_nam'];
  }
  return $cities;
}

/**
 * Adopt the city-name to AEMET...
 */
function _weather_es_city_name($city) {
  $convert_to = array(
    'a',
    'e',
    'i',
    'o',
    'u',
    'n',
    '-',
    '-',
    '-',
    '-',
  );
  $convert_from = array(
    'á',
    'é',
    'í',
    'ó',
    'ú',
    'ñ',
    '/',
    ', ',
    ' ',
    '\'',
  );
  return str_replace($convert_from, $convert_to, $city);
}

Functions

Namesort descending Description
spanish_time Return the Spanish (peninsula) time
_weather_es_aemet Clean the data and save it
_weather_es_cities Available cities.
_weather_es_city_name Adopt the city-name to AEMET...
_weather_es_filter_cities Get the diferent cities of the user
_weather_es_get_config Get the user configuration
_weather_es_next_act Next data update. AEMET refresh the data at Spanish local time, about 07:00am
_weather_es_provincies Available provinces
_weather_es_redirect Redirect the user to his correct path
_weather_es_retrieve_data Get the data from AEMET