A Ruby gem to get planning applications data from UK council websites.
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.
 
 
 

116 lines
3.1 KiB

  1. require 'csv'
  2. module UKPlanningScraper
  3. class Authority
  4. attr_reader :name, :tags, :url
  5. @@authorities = []
  6. def initialize(name, url, tags)
  7. @name = name
  8. @url = url
  9. @tags = tags
  10. end
  11. def scrape(params, options = {})
  12. default_options = {
  13. delay: 10,
  14. }
  15. options = default_options.merge(options) # The user-supplied options override the defaults
  16. # Validated within the last n days
  17. # Assumes that every scraper/system can do a date range search
  18. if params[:validated_days]
  19. params[:validated_to] = Date.today
  20. params[:validated_from] = Date.today - (params[:validated_days] - 1)
  21. end
  22. # Received within the last n days
  23. # Assumes that every scraper/system can do a date range search
  24. if params[:received_days]
  25. params[:received_to] = Date.today
  26. params[:received_from] = Date.today - (params[:received_days] - 1)
  27. end
  28. # Decided within the last n days
  29. # Assumes that every scraper/system can do a date range search
  30. if params[:decided_days]
  31. params[:decided_to] = Date.today
  32. params[:decided_from] = Date.today - (params[:decided_days] - 1)
  33. end
  34. # Select which scraper to use based on the URL
  35. if @url.match(/search\.do\?action=advanced/i)
  36. apps = UKPlanningScraper.scrape_idox(@url, params, options)
  37. elsif @url.match(/generalsearch\.aspx/i)
  38. apps = UKPlanningScraper.scrape_northgate(@url, params, options)
  39. else
  40. # Not supported
  41. raise SystemNotSupportedError.new("Planning system not supported for #{@name} at URL: #{@url}")
  42. end
  43. # Post processing
  44. apps.each do |app|
  45. app[:authority_name] = @name
  46. end
  47. apps # Single point of successful exit
  48. end
  49. def tagged?(tag)
  50. @tags.include?(tag)
  51. end
  52. def self.all
  53. @@authorities
  54. end
  55. # List all the tags in use
  56. def self.tags
  57. tags = []
  58. @@authorities.each { |a| tags << a.tags }
  59. tags.flatten.uniq.sort
  60. end
  61. def self.named(name)
  62. authority = @@authorities.find { |a| name == a.name }
  63. raise AuthorityNotFound if authority.nil?
  64. authority
  65. end
  66. # Tagged x
  67. def self.tagged(tag)
  68. found = []
  69. @@authorities.each { |a| found << a if a.tags.include?(tag) }
  70. found
  71. end
  72. # Not tagged x
  73. def self.not_tagged(tag)
  74. found = []
  75. @@authorities.each { |a| found << a unless a.tags.include?(tag) }
  76. found
  77. end
  78. # Authorities with no tags
  79. def self.untagged
  80. found = []
  81. @@authorities.each { |a| found << a if a.tags.empty? }
  82. found
  83. end
  84. def self.load
  85. # Don't run this method more than once
  86. return unless @@authorities.empty?
  87. # FIXME hardcoded file path
  88. CSV.foreach(File.join(File.dirname(__dir__), 'uk_planning_scraper', 'authorities.csv')) do |line|
  89. @@authorities << Authority.new(
  90. line[0].strip,
  91. line[1].strip,
  92. line[2..-1].map { |e| e.strip }.sort)
  93. end
  94. end
  95. end
  96. end
  97. UKPlanningScraper::Authority.load