Ben Dodson

Freelance iOS, Apple Watch, and Apple TV Developer

Finding the next available driving test with Goutte PHP Scraper

Over the past week I’ve had a lot of fun working on some small scripts to aid my general day-to-day living. My wife is currently waiting to take her driving test but our local area only has one test instructor with a waiting list of over 6 months! Occassionally slots open up due to cancellations and so she has been logging into the Government website multiple times a day to check for a nearer date. Time for some automation!

To stop her having to constantly go to a website, I decided to knock up a quick PHP script that would basically pretend to be a browser, log in, go to the correct page, and rip out the next available appointment. It’s been a while since I wrote a script like this so I had a look around for something better than SimpleXML and found Goutte, a simple PHP Web Scraper. Within 10 minutes, my script was working. It looks something like this:

<?php

require 'vendor/autoload.php';

use Goutte\Client;

$licenseNumber = 'xxx'; // Driving License Number
$referenceNumber = 'xxx'; // Reference number for current test date as looking to rebook

$client = new Client();

$crawler = $client->request('GET', 'https://driverpracticaltest.direct.gov.uk/login');
$crawler->filter('h2')->each(function($node) {
	if ($node->text() == "Sorry, you can’t use this service right now") {
		echo 'Site is down.';exit; // Inexplicably, the site goes offline from 9pm-6am. It thinks it's an office!
	}
});

$form = $crawler->selectButton('Continue')->form();
$crawler = $client->submit($form, array('username' => $licenseNumber, 'password' => $referenceNumber));
$link = $crawler->selectLink('Change Date and time of test')->link();
$crawler = $client->click($link);
$form = $crawler->selectButton('Find available dates')->form();
$crawler = $client->submit($form, array('testChoice' => 'ASAP'));

$crawler->filter('.slotDateTime')->each(function ($node) {
	$date = $node->text();
	echo $date.' is the next available test slot.';
	// Here I check if it has changed since last time and send an email if it has and nearer than currently booked test. Left out for brevity.
    exit;
});

?>

As you can see, the code is pretty simple, readable, and powerful. Within minutes, I was able to jump through 3 pages without worrying about sessions, cookies, or any of the other nonsense that often occurred when dealing with this kind of scraping. I run this every 5 minutes on a FortRabbit server and we both get emailed if a closer test date appears. For just a few minutes work, this means better peace of mind as we don’t have to check manually and this checks far more frequently than we ever could. Now to wait and hope for a nearer test date…

The mobile web » « TransferWise