-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #438 from PhilDB-cloud/master
feat: Add Mid and East Antrim
- Loading branch information
Showing
3 changed files
with
127 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
uk_bin_collection/uk_bin_collection/councils/MidAndEastAntrimBoroughCouncil.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |