diff --git a/uk_bin_collection/tests/input.json b/uk_bin_collection/tests/input.json index 9466bf2fd7..1b3a553456 100644 --- a/uk_bin_collection/tests/input.json +++ b/uk_bin_collection/tests/input.json @@ -194,6 +194,15 @@ "wiki_name": "Blackburn Council", "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN." }, + "BlaenauGwentCountyBoroughCouncil": { + "uprn": "100100471367", + "postcode": "NP23 7TE", + "skip_get_url": false, + "url": "https://www.blaenau-gwent.gov.uk", + "web_driver": "http://selenium:4444", + "wiki_name": "Blaenau Gwent County Borough Council", + "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN." + }, "BoltonCouncil": { "postcode": "BL1 5PQ", "skip_get_url": true, diff --git a/uk_bin_collection/uk_bin_collection/councils/BlaenauGwentCountyBoroughCouncil.py b/uk_bin_collection/uk_bin_collection/councils/BlaenauGwentCountyBoroughCouncil.py new file mode 100644 index 0000000000..e633b31078 --- /dev/null +++ b/uk_bin_collection/uk_bin_collection/councils/BlaenauGwentCountyBoroughCouncil.py @@ -0,0 +1,113 @@ +from bs4 import BeautifulSoup +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.ui import Select +from selenium.webdriver.support.wait import WebDriverWait + +from uk_bin_collection.uk_bin_collection.common import * +from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass + + +# import the wonderful Beautiful Soup and the URL grabber +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: + driver = None + try: + data = {"bins": []} + user_uprn = kwargs.get("uprn") + user_postcode = kwargs.get("postcode") + web_driver = kwargs.get("web_driver") + headless = kwargs.get("headless") + check_uprn(user_uprn) + check_postcode(user_postcode) + + # Create Selenium webdriver + driver = create_webdriver(web_driver, headless, None, __name__) + driver.get( + "https://iportal.itouchvision.com/icollectionday/collection-day/?uuid=238D5F9796C12643D190E3505931401A8C003F0D&lang=en" + ) + + # Wait for the postcode field to appear then populate it + inputElement_postcode = WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.ID, "postcodeSearch")) + ) + inputElement_postcode.send_keys(user_postcode) + + # Click search button + findAddress = WebDriverWait(driver, 10).until( + EC.presence_of_element_located( + (By.XPATH, '//button[@class="govuk-button mt-4"]') + ) + ) + findAddress.click() + + # Wait for the dropdown to be visible + WebDriverWait(driver, 10).until( + EC.presence_of_element_located((By.ID, "addressSelect")) + ) + + dropdown = Select(driver.find_element(By.ID, "addressSelect")) + dropdown.select_by_value(user_uprn) + + # Wait for the collections table to appear + WebDriverWait(driver, 10).until( + EC.presence_of_element_located( + ( + By.XPATH, + '//div[@class="ant-row d-flex justify-content-between mb-4 mt-2 css-2rgkd4"]', + ) + ) + ) + + soup = BeautifulSoup(driver.page_source, features="html.parser") + + recyclingcalendar = soup.find( + "div", + { + "class": "ant-row d-flex justify-content-between mb-4 mt-2 css-2rgkd4" + }, + ) + + rows = recyclingcalendar.find_all( + "div", + { + "class": "ant-col ant-col-xs-12 ant-col-sm-12 ant-col-md-12 ant-col-lg-12 ant-col-xl-12 css-2rgkd4" + }, + ) + + current_year = datetime.now().year + current_month = datetime.now().month + + for row in rows: + BinType = row.find("h3").text + collectiondate = datetime.strptime( + row.find("div", {"class": "text-white fw-bold"}).text, + "%A %d %B", + ) + if (current_month > 10) and (collectiondate.month < 3): + collectiondate = collectiondate.replace(year=(current_year + 1)) + else: + collectiondate = collectiondate.replace(year=current_year) + + dict_data = { + "type": BinType, + "collectionDate": collectiondate.strftime("%d/%m/%Y"), + } + data["bins"].append(dict_data) + + except Exception as e: + # Here you can log the exception if needed + print(f"An error occurred: {e}") + # Optionally, re-raise the exception if you want it to propagate + raise + finally: + # This block ensures that the driver is closed regardless of an exception + if driver: + driver.quit() + return data diff --git a/wiki/Councils.md b/wiki/Councils.md index a11d2527ec..95bbec41af 100644 --- a/wiki/Councils.md +++ b/wiki/Councils.md @@ -35,6 +35,7 @@ This document is still a work in progress, don't worry if your council isn't lis - [Birmingham City Council](#birmingham-city-council) - [Blaby District Council](#blaby-district-council) - [Blackburn Council](#blackburn-council) +- [Blaenau Gwent County Borough Council](#blaenau-gwent-county-borough-council) - [Bolton Council](#bolton-council) - [Bracknell Forest Council](#bracknell-forest-council) - [Bradford MDC](#bradford-mdc) @@ -589,6 +590,20 @@ Note: You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/searc --- +### Blaenau Gwent County Borough Council +```commandline +python collect_data.py BlaenauGwentCountyBoroughCouncil https://www.blaenau-gwent.gov.uk -s -u XXXXXXXX -p "XXXX XXX" -w http://HOST:PORT/ +``` +Additional parameters: +- `-s` - skip get URL +- `-u` - UPRN +- `-p` - postcode +- `-w` - remote Selenium web driver URL (required for Home Assistant) + +Note: You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN. + +--- + ### Bolton Council ```commandline python collect_data.py BoltonCouncil https://carehomes.bolton.gov.uk/bins.aspx -s -u XXXXXXXX -p "XXXX XXX" -w http://HOST:PORT/