Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Mid and East Antrim #438

Merged
merged 3 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading