Automatically exported from code.google.com/p/planningalerts
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

150 lines
4.3 KiB

  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4. use CGI qw(:cgi);
  5. use HTML::TreeBuilder;
  6. use LWP::UserAgent;
  7. use XML::Writer;
  8. # The master URLs for the Christchurch planning search
  9. our $SearchURL = "http://webapps.christchurch.gov.uk/PlanningApplications/pages/ApplicationSearch.aspx";
  10. our $InfoURL = "http://webapps.christchurch.gov.uk/PlanningApplications/pages/ApplicationDetails.aspx?Authority=Christchurch%20Borough%20Council&Application=";
  11. # We're a CGI script...
  12. my $query = CGI->new();
  13. # Get the date to fetch
  14. my $date = $query->param("day") . "/" . $query->param("month") . "/" . $query->param("year");
  15. # Construct an LWP user agent
  16. our $UA = LWP::UserAgent->new(env_proxy => 1);
  17. # Post the URL to get an initial blank form
  18. my $page = do_post();
  19. # Do the search
  20. $page = do_post($page,
  21. {"DetailedSearch:TextBox_DateRaisedFrom" => $date,
  22. "DetailedSearch:TextBox_DateRaisedTo" => $date,
  23. "QuickSearchApplicationNumber:Button_SearchApplicationNumber" => "Search"});
  24. # Output an HTTP response header
  25. print $query->header(-type => "text/xml");
  26. # Create an XML output stream
  27. my $Writer = XML::Writer->new(DATA_MODE => 1);
  28. # Output the XML header data
  29. $Writer->xmlDecl("UTF-8");
  30. $Writer->startTag("planning");
  31. $Writer->dataElement("authority_name", "Christchurch Council");
  32. $Writer->dataElement("authority_short_name", "Christchurch");
  33. $Writer->startTag("applications");
  34. # Output any applications on the first page
  35. output_applications($page);
  36. # Loop over any additional results pages
  37. while (my $link = $page->look_down("_tag" => "a", "id" => "MatchingApplications_ResultsNavigationTop_LinkButton_Next"))
  38. {
  39. # Fetch this page...
  40. $page = do_post_back($page, 'MatchingApplications$ResultsNavigationTop$LinkButton_Next', '');
  41. # ...and output the applications from it
  42. output_applications($page);
  43. }
  44. # Finish off XML output
  45. $Writer->endTag("applications");
  46. $Writer->endTag("planning");
  47. $Writer->end();
  48. exit 0;
  49. # Fake up what the doPostBack javascript function in the page does...
  50. sub do_post_back
  51. {
  52. my $previous = shift;
  53. my $target = shift;
  54. my $argument = shift;
  55. $target =~ s/\$/:/g;
  56. my $args = {
  57. "__EVENTTARGET" => $target,
  58. "__EVENTARGUMENT" => $argument,
  59. };
  60. return do_post($previous, $args);
  61. }
  62. # Make a POST request
  63. sub do_post
  64. {
  65. my $previous = shift;
  66. my $args = shift || {};
  67. if (defined($previous))
  68. {
  69. my $viewstate = $previous->look_down("_tag" => "input", "name" => "__VIEWSTATE");
  70. # my $eventvalidation = $previous->look_down("_tag" => "input", "name" => "__EVENTVALIDATION");
  71. $args->{"__VIEWSTATE"} = $viewstate->attr("value");
  72. # $args->{"__EVENTVALIDATION"} = $eventvalidation->attr("value");
  73. }
  74. my $response = $UA->post($SearchURL, $args);
  75. die $response->status_line unless $response->is_success;
  76. return HTML::TreeBuilder->new_from_content($response->content);
  77. }
  78. # Output applications from a results page
  79. sub output_applications
  80. {
  81. my $page = shift;
  82. # Find the result table
  83. my $table = $page->look_down("_tag" => "table", "class" => "searchresults");
  84. # No results means no results table
  85. if (defined($table))
  86. {
  87. # Process each row of the results
  88. foreach my $row ($table->look_down("_tag" => "tr"))
  89. {
  90. my $class = $row->attr("class") || "";
  91. next if $class eq "searchresultsheader";
  92. my @cells = $row->look_down("_tag" => "td");
  93. my $reference = $cells[0]->as_trimmed_text;
  94. my $date = $cells[1]->as_trimmed_text;
  95. my $address = $cells[2]->as_trimmed_text;
  96. my $description = $cells[3]->as_trimmed_text;
  97. my $postcode;
  98. if ($address =~ /\s+([A-Z]+\d+\s+\d+[A-Z]+)$/)
  99. {
  100. $postcode = $1;
  101. }
  102. $Writer->startTag("application");
  103. $Writer->dataElement("council_reference", $reference);
  104. $Writer->dataElement("address", $address);
  105. $Writer->dataElement("postcode", $postcode);
  106. $Writer->dataElement("description", $description);
  107. $Writer->dataElement("info_url", $InfoURL . $reference);
  108. $Writer->dataElement("comment_url", $InfoURL . $reference);
  109. $Writer->dataElement("date_received", $date);
  110. $Writer->endTag("application");
  111. }
  112. }
  113. return;
  114. }