Skip to content

Commit

Permalink
Merge pull request #438 from PhilDB-cloud/master
Browse files Browse the repository at this point in the history
feat: Add Mid and East Antrim
  • Loading branch information
dp247 authored Nov 26, 2023
2 parents 5b5c178 + 141aca7 commit a58b159
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Feature: Test each council output matches expected results
| MalvernHillsDC | None | None |
| ManchesterCityCouncil | None | None |
| MertonCouncil | None | None |
| MidAndEastAntrimBoroughCouncil | http://selenium:4444 | local |
| MidSussexDistrictCouncil | None | None |
| MiltonKeynesCityCouncil | None | None |
| NeathPortTalbotCouncil | http://selenium:4444 | local |
Expand Down
10 changes: 9 additions & 1 deletion uk_bin_collection/tests/input.json
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,14 @@
"wiki_name": "Merton Council",
"wiki_note": "Follow the instructions [here](https://myneighbourhood.merton.gov.uk/Wasteservices/WasteServicesSearch.aspx) until you get the \"Your recycling and rubbish collection days\" page then copy the URL and replace the URL in the command (the Address parameter is optional)."
},
"MidAndEastAntrimBoroughCouncil": {
"postcode": "100 Galgorm Road",
"skip_get_url": true,
"url": "https://www.midandeastantrim.gov.uk/resident/waste-recycling/collection-dates/",
"web_driver": "http://selenium:4444",
"wiki_name": "Mid and East Antrim Borough Council",
"wiki_note": "Pass the house name/number plus the name of the street with the postcode parameter, wrapped in double quotes. Check the address in the web site first. This version will only pick the first SHOW button returned by the search or if it is fully unique. The search is not very predictable (e.g. house number 4 returns 14,24,4,44 etc.)."
},
"MidSussexDistrictCouncil": {
"house_number": "OAKLANDS",
"postcode": "RH16 1SS",
Expand Down Expand Up @@ -674,4 +682,4 @@
"url": "https://waste-api.york.gov.uk/api/Collections/GetBinCollectionDataForUprn/",
"wiki_name": "York Council"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
from bs4 import BeautifulSoup
import time
from dateutil.relativedelta import relativedelta
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException

from uk_bin_collection.uk_bin_collection.common import *
from uk_bin_collection.uk_bin_collection.get_bin_data import \
AbstractGetBinDataClass

class CouncilClass(AbstractGetBinDataClass):
"""
Concrete classes have to implement all abstract operations of the
base class. They can also override some operations with a default
implementation.
"""

def parse_data(self, page: str, **kwargs) -> dict:
page = "https://www.midandeastantrim.gov.uk/resident/waste-recycling/collection-dates/"

# Assign user info
user_postcode = kwargs.get("postcode")
# not used: user_paon = kwargs.get("paon")
web_driver = kwargs.get("web_driver")

# Create Selenium webdriver
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = create_webdriver(web_driver)

driver.get(page)

time.sleep(5)
number=0
driver.switch_to.frame(number)
# Enter postcode in text box and wait
inputElement_pc = driver.find_element(
By.ID, "txtAjaxSearch"
)
inputElement_pc.send_keys(user_postcode)

time.sleep(5)

# Submit address information and wait - selecting the top one only
# if it is an exact match then it will go straight to the results
try:
button = driver.find_element(
By.XPATH, '//*[@id="show-button-0"]'
)
driver.execute_script("arguments[0].click();", button)
except NoSuchElementException:
pass

time.sleep(4)

# Read next collection information
page = driver.find_element(
By.ID, "divCalendarGraphics"
).get_attribute("outerHTML")

# Make a BS4 object - remove bold tags and add @ so we can split the lines later
soup = BeautifulSoup(page.strip().replace("<b>", "").replace("</b>", "").replace("<br>", "@"), features="html.parser")
soup.prettify()

# Data to return
data = {"bins": []}

# Valid bin types
binTypes = [
"Refuse",
"Garden"
]

# Value to create dict for bin values
keys, values = [], []

# Loop though html for text containing bins
# example of html (bold tags removed above)
# <div id="divCalendarGraphics">
# <br> <b>Refuse</b>: Tue 14 Nov then every alternate Tue<br><b>Recycling</b>: No Recycling waste collection for this address<br><b>Garden</b>: Tue 21 Nov then every alternate Tue<br><img src="img/Gif-Spacer.gif" alt="spacer" height="1" width="30">
# split by br tag and take first 4 splits
lines = soup.text.split('@',4)
for line in lines[1:4]:
keys.append(line.split(':')[0].strip())
# strip out the day and month from the text
values.append(line.split(':')[1].strip().split(' ')[:3])

# Create dict for bin name and string dates
binDict = dict(zip(keys, values))

# Process dict for valid bin types
for bin in list(binDict):
if bin in binTypes:
# Convert date - no year value so take it from todays date
if binDict[bin][0] == "Tomorrow":
date = datetime.today() + relativedelta(days=1)
elif binDict[bin][0] == "Today":
date = datetime.today()
else:
date = datetime.strptime(' '.join(binDict[bin][1:]), "%d %b").replace(year=datetime.today().year)
# if the date is in the past then it means the collection is next year so add a year
if date < datetime.today():
date = date + relativedelta(years=1)

# Set bin data
dict_data = {
"type": bin,
"collectionDate": date.strftime(date_format),
}
data["bins"].append(dict_data)

# Quit Selenium webdriver to release session
driver.quit()

return data

0 comments on commit a58b159

Please sign in to comment.