Poulegegevens van handbal.nl op eigen website tonen

Voor Westlandia heb ik vorig jaar een koppeling geschreven die competitie gegevens van handbal.nl kan tonen. Voor veel verenigingen is dit een gewenste functionaliteit om te hebben op de eigen site. De afgelopen tijd heb ik regelmatig wat vragen gekregen hoe ik dit op de site van Westlandia voor elkaar heb gekregen.

Als we de huidige site van Handbal.nl analyseren dan zien we op het moment dat we poules en uitslagen bekijken zijn AJAX request als:

http://www.handbal.nl/ajax/competition/show_program/6200

In deze URL zijn twee dynamisch element. Het laatste gedeelte is de poule id. Het ene laatste gedeelte beschrijft de mogelijke onderdelen die je kan ophalen. Dit zijn de mogelijkheden:

  • show_standing | Stand
  • show_program | programma
  • show_result | uitslagen

Met deze kennis kunnen we vrij eenvoudig een simpel script maken om de juiste informatie per poule op te halen. Overigens hebben we bij de site van Westlandia voor iedere team een eigen pagina waar de poule ID geregistreerd staat.


namespace Services\Competition;

/**
* Description of Collector
*
* @author Paul de Raaij <paul@paulderaaij.nl>
*/
class Collector {
const BASE_URL = "http://www.handbal.nl/ajax/competition/";
const CACHE_LIFETIME_MILLISECS = 3000;

private $cachePath = null;

public function __construct() {
      $this->cachePath = JPATH_SITE . '/cache/com_ivejo/competitions/';
}

public function collectRanking($competitionId) {
      return $this->collectDataFromExternalSite(self::BASE_URL . "show_standing/" . $competitionId . "/", $this->generateIdentifier($competitionId, 'show_standing'));
}

public function collectProgram($competitionId) {
      return $this->collectDataFromExternalSite(self::BASE_URL . "show_program/" . $competitionId . "/", $this->generateIdentifier($competitionId, 'show_program'));
}

public function collectResults($competitionId) {
      return $this->collectDataFromExternalSite(self::BASE_URL . "show_result/" . $competitionId . "/", $this->generateIdentifier($competitionId, 'show_result'));
}

private function generateIdentifier($competition, $action) {
      return $action . '_' . $competition;
}

private function collectDataFromExternalSite($url, $identifier) {
      $filename = $this->cachePath . '/' . $identifier . '.chc';

      if ($this->cacheFolderExists()) {
            if (!file_exists($filename) || $this->lastUpdatedDiff($filename) > self::CACHE_LIFETIME_MILLISECS) {
                  $ch = curl_init();
                  curl_setopt($ch, CURLOPT_URL, $url);
                  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                  if (strpos($identifier, 'show_program') !== false) {
                      curl_setopt($ch, CURLOPT_POSTFIELDS, array('date_from' => date("d-m-Y"),
'date_to' => date("d-m-Y", strtotime("+1 year"))));
                  }
                  $returnData = curl_exec($ch);
                  curl_close($ch);
                  $result = $this->formatResultData($returnData, $identifier);

                  if ($result == null) {
                      return file_get_contents($filename);
                  }

                  file_put_contents($filename, $result);
                  return $result;
          }
    }

    return file_get_contents($filename);
}

private function formatResultData($data, $identifier) {
    if (strpos($identifier, 'show_standing') !== false) {
        preg_match_all('/<div id="content_standings_" class="cf clear">.*?<script type="text\/javascript">/s', $data, $matches, PREG_PATTERN_ORDER);
    } else {
        preg_match_all('/<div class="cf clear" id="content_(.*)">.*?<script type="text\/javascript">/s', $data, $matches, PREG_PATTERN_ORDER);
    }

    if (isset($matches[0][0])) {
        $html = strip_tags($matches[0][0], '<table><thead><th><tr><td><div><strong><br>');
    }

    return $html;
}

private function lastUpdatedDiff($path) {
    return time() - filemtime($path);
}

private function cacheFolderExists() {
    if (!is_dir($this->cachePath)) {
        mkdir($this->cachePath, 0644, true);
    }
    return true;
}
}

Om de server van handbal.nl nog wat te sparen heb ik caching ingebouwd die enige tijd de resultaten vasthoud. Mocht de server van handbal.nl plat liggen dan pakken we automatisch het resultaat uit de cache en kunnen wij altijd informatie laten zien.

Overigens zie je dat we de response nog wat strippen van HTML zodat we het netjes kunnen weergeven.

Met behulp van dit script hebben wij op de site van Westlandia een koppeling naar handbal.nl. Pagina’s zoals: http://www.westlandia.nl/component/ivejo/?task=team.dashboard