mirror of
https://github.com/sascha-hemi/hacs_waste_collection_schedule.git
synced 2026-03-21 04:06:03 +01:00
add Port Adelaide Enfield, Austrailia
This commit is contained in:
@@ -45,6 +45,7 @@ Waste collection schedules in the following formats and countries are supported.
|
|||||||
- [Melton City Council](/doc/source/melton_vic_gov_au.md) / melton.vic.gov.au
|
- [Melton City Council](/doc/source/melton_vic_gov_au.md) / melton.vic.gov.au
|
||||||
- [Nillumbik Shire Council](/doc/source/nillumbik_vic_gov_au.md) / nillumbik.vic.gov.au
|
- [Nillumbik Shire Council](/doc/source/nillumbik_vic_gov_au.md) / nillumbik.vic.gov.au
|
||||||
- [North Adelaide Waste Management Authority](/doc/source/nawma_sa_gov_au.md) / nawma.sa.gov.au
|
- [North Adelaide Waste Management Authority](/doc/source/nawma_sa_gov_au.md) / nawma.sa.gov.au
|
||||||
|
- [Port Adelaide Enfield, South Australia](/doc/source/portenf_sa_gov_au.md) / ecouncil.portenf.sa.gov.au
|
||||||
- [RecycleSmart](/doc/source/recyclesmart_com.md) / recyclesmart.com
|
- [RecycleSmart](/doc/source/recyclesmart_com.md) / recyclesmart.com
|
||||||
- [Stonnington City Council](/doc/source/stonnington_vic_gov_au.md) / stonnington.vic.gov.au
|
- [Stonnington City Council](/doc/source/stonnington_vic_gov_au.md) / stonnington.vic.gov.au
|
||||||
- [The Hills Shire Council, Sydney](/doc/source/thehills_nsw_gov_au.md) / thehills.nsw.gov.au
|
- [The Hills Shire Council, Sydney](/doc/source/thehills_nsw_gov_au.md) / thehills.nsw.gov.au
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
import requests
|
||||||
|
from waste_collection_schedule import Collection # type: ignore[attr-defined]
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
import logging
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
# With verify=True the POST fails due to a SSLCertVerificationError.
|
||||||
|
# Using verify=False works, but is not ideal. The following links may provide a better way of dealing with this:
|
||||||
|
# https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings
|
||||||
|
# https://urllib3.readthedocs.io/en/1.26.x/user-guide.html#ssl
|
||||||
|
# These two lines areused to suppress the InsecureRequestWarning when using verify=False
|
||||||
|
import urllib3
|
||||||
|
urllib3.disable_warnings()
|
||||||
|
|
||||||
|
TITLE = "Port Adelaide Enfield, South Australia"
|
||||||
|
DESCRIPTION = "Source for City of Port Adelaide Enfield, South Australia."
|
||||||
|
URL = "https://ecouncil.portenf.sa.gov.au/"
|
||||||
|
TEST_CASES = {
|
||||||
|
"Broadview, Regency Road, 565 ": {"suburb": "Broadview", "street": "Regency Road", "house_number": 565, "unit_number": ""},
|
||||||
|
"48 Floriedale Rd ": {"suburb": "Greenacres", "street": "Floriedale Rd", "house_number": "48"},
|
||||||
|
"24 Margaret Terrace": {"suburb": "Rosewater", "street": "Margaret Terrace", "house_number": "24"},
|
||||||
|
"Addison Road 91 with unit": {"suburb": "Rosewater", "street": "Addison Road", "house_number": 91, "unit_number": 2},
|
||||||
|
}
|
||||||
|
|
||||||
|
ICON_MAP = {
|
||||||
|
"general-waste bin": "mdi:trash-can",
|
||||||
|
"organics bin": "mdi:leaf",
|
||||||
|
"recycling bin": "mdi:recycle",
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
API_URL = "https://ecouncil.portenf.sa.gov.au/public/propertywastedates/public.aspx"
|
||||||
|
|
||||||
|
|
||||||
|
class Source:
|
||||||
|
def __init__(self, suburb: str, street: str, house_number: str | int, unit_number: str | int = ""):
|
||||||
|
self._suburb: str = suburb
|
||||||
|
self._street: str = street
|
||||||
|
self._house_number: str = str(house_number)
|
||||||
|
self._unit_number: str = str(unit_number)
|
||||||
|
|
||||||
|
def __set_args(self, soup: BeautifulSoup, event_taget=None, additonal: dict = {}) -> dict:
|
||||||
|
args = {
|
||||||
|
"ctl00$MainContent$txtSuburb": self._suburb,
|
||||||
|
"ctl00$MainContent$txtStreetName": self._street,
|
||||||
|
"ctl00$MainContent$txtHouseNumber": self._house_number,
|
||||||
|
"ctl00$MainContent$txtUnitNumber": self._unit_number,
|
||||||
|
}
|
||||||
|
if event_taget is not None:
|
||||||
|
args["__EVENTTARGET"] = event_taget
|
||||||
|
|
||||||
|
for hidden_val in soup.find_all("input", {"type": "hidden"}):
|
||||||
|
args[hidden_val["name"]] = hidden_val["value"]
|
||||||
|
|
||||||
|
for key, value in additonal.items():
|
||||||
|
args[key] = value
|
||||||
|
return args
|
||||||
|
|
||||||
|
def fetch(self):
|
||||||
|
session = requests.Session()
|
||||||
|
|
||||||
|
# get First page
|
||||||
|
r = session.get(API_URL, verify=False)
|
||||||
|
r.raise_for_status()
|
||||||
|
|
||||||
|
# extractt arguments
|
||||||
|
args = self.__set_args(BeautifulSoup(
|
||||||
|
r.text, "html.parser"), event_taget="ctl00$MainContent$btnSearch")
|
||||||
|
|
||||||
|
r = session.post(API_URL, data=args)
|
||||||
|
r.raise_for_status()
|
||||||
|
|
||||||
|
# get page to select an address
|
||||||
|
soup = BeautifulSoup(r.text, "html.parser")
|
||||||
|
|
||||||
|
selectable = soup.find_all(
|
||||||
|
"a", {"class": "anchor-button small"}, text="Select")
|
||||||
|
|
||||||
|
if len(selectable) == 0:
|
||||||
|
raise ValueError("No address found")
|
||||||
|
selected = selectable[0]
|
||||||
|
|
||||||
|
# If multiple addresses are found, try to find the one that matches the input and warn if there are multiple or none matches
|
||||||
|
if len(selectable) > 1:
|
||||||
|
found = [" ".join([y.text for y in x.parent.parent.find_all("td")[
|
||||||
|
1].find_all("span")]) for x in selectable]
|
||||||
|
using_index = 0
|
||||||
|
|
||||||
|
match = False
|
||||||
|
|
||||||
|
for index, entry in enumerate(found):
|
||||||
|
entry = entry.lower().strip().replace(" ", "")
|
||||||
|
if self._house_number.lower().strip().replace(" ", "") in entry and self._street.lower().strip().replace(" ", "") in entry and self._suburb.lower().strip().replace(" ", "") in entry and self._unit_number.lower().strip().replace(" ", "") in entry:
|
||||||
|
if match:
|
||||||
|
LOGGER.warning(
|
||||||
|
f"Multiple addresses found, using first one \nfound:{', '.join(found[:10])}{'...' if len(found) >= 10 else ''} \nusing:{found[using_index]}")
|
||||||
|
break
|
||||||
|
using_index = index
|
||||||
|
match = True
|
||||||
|
if not match:
|
||||||
|
LOGGER.warning(
|
||||||
|
f"no perfect addres match found, using:{found[using_index]}")
|
||||||
|
|
||||||
|
# request first address
|
||||||
|
args = self.__set_args(soup, event_taget="ctl00$MainContent$gvPropertyResults$ctl02$btnSelect", additonal={
|
||||||
|
selected["href"].split("'")[1]: ""})
|
||||||
|
r = session.post(API_URL, data=args)
|
||||||
|
r.raise_for_status()
|
||||||
|
|
||||||
|
soup = BeautifulSoup(r.text, "html.parser")
|
||||||
|
cal_header = soup.find(
|
||||||
|
"th", {"class": "header-month"}).find("span").text
|
||||||
|
main_month = cal_header.split("-")[0].strip()
|
||||||
|
|
||||||
|
secondary_month = cal_header.split("-")[1].strip().split(" ")[0]
|
||||||
|
secondary_year = main_year = cal_header.split("-")[1].strip().split(" ")[1]
|
||||||
|
|
||||||
|
# if main month contains a year, set it (mabe happens in december???)
|
||||||
|
if len(main_month.split(" ")) > 1:
|
||||||
|
main_year = main_month.split(" ")[1]
|
||||||
|
main_month = main_month.split(" ")[0]
|
||||||
|
|
||||||
|
entries = []
|
||||||
|
|
||||||
|
calendar = soup.find("table", {"class": "collection-day-calendar"})
|
||||||
|
# Iterate over all days with pickups
|
||||||
|
for pickup in calendar.find_all("div", {"class": "pickup"}):
|
||||||
|
parent_td = pickup.parent
|
||||||
|
month = main_month if parent_td.attrs["class"] == "main-month" else secondary_month
|
||||||
|
year = main_year if parent_td.attrs["class"] == "main-month" else secondary_year
|
||||||
|
day = parent_td.find("div", {"class": "daynumber"}).text
|
||||||
|
|
||||||
|
# Iterate over all pickup container types for this day
|
||||||
|
for container in pickup.find_all("div", {"class": "bin-container"}):
|
||||||
|
container_type = " ".join(container.find("div").attrs["class"])
|
||||||
|
container_icon = ICON_MAP.get(container_type)
|
||||||
|
|
||||||
|
date = datetime.datetime.strptime(f"{year}-{month}-{day}", "%Y-%B-%d").date()
|
||||||
|
entries.append(Collection(date=date, t=container_type, icon=container_icon))
|
||||||
|
|
||||||
|
return entries
|
||||||
49
doc/source/portenf_sa_gov_au.md
Normal file
49
doc/source/portenf_sa_gov_au.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# City of Port Adelaide Enfield, South Australia
|
||||||
|
|
||||||
|
Support for schedules provided by [City of Port Adelaide Enfield, South Australia](https://ecouncil.portenf.sa.gov.au/), serving City of Port Adelaide Enfield, South Australia, South Australia.
|
||||||
|
|
||||||
|
## Configuration via configuration.yaml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
waste_collection_schedule:
|
||||||
|
sources:
|
||||||
|
- name: portenf_sa_gov_au
|
||||||
|
args:
|
||||||
|
suburb: SUBURB
|
||||||
|
street: STREET NAME
|
||||||
|
house_number: "HOUSE NUMBER"
|
||||||
|
unit_number: UNIT NUMBER
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuration Variables
|
||||||
|
|
||||||
|
**suburb**
|
||||||
|
*(String) (required)*
|
||||||
|
|
||||||
|
**street**
|
||||||
|
*(String) (required)*
|
||||||
|
|
||||||
|
**house_number**
|
||||||
|
*(String | Integer) (required)*
|
||||||
|
|
||||||
|
**unit_number**
|
||||||
|
*(String | Integer) (optional)*
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
waste_collection_schedule:
|
||||||
|
sources:
|
||||||
|
- name: portenf_sa_gov_au
|
||||||
|
args:
|
||||||
|
suburb: Rosewater
|
||||||
|
street: Addison Road
|
||||||
|
house_number: 91
|
||||||
|
unit_number: 2
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to get the source argument
|
||||||
|
|
||||||
|
Find the parameter of your address using [https://www.cityofpae.sa.gov.au/live/waste/bin-collection](https://www.cityofpae.sa.gov.au/live/waste/bin-collection) and write them exactly like the address you get searching for your address.
|
||||||
2
info.md
2
info.md
@@ -16,7 +16,7 @@ Waste collection schedules from service provider web sites are updated daily, de
|
|||||||
|--|--|
|
|--|--|
|
||||||
| Generic | ICS / iCal files |
|
| Generic | ICS / iCal files |
|
||||||
| Static | User-defined dates or repeating date patterns |<!--Begin of country section-->
|
| Static | User-defined dates or repeating date patterns |<!--Begin of country section-->
|
||||||
| Australia | Banyule City Council, Belmont City Council, Brisbane City Council, Campbelltown City Council (NSW), Cardinia Shire Council, City of Canada Bay Council, City of Kingston, City of Onkaparinga Council, Gold Coast City Council, Hume City Council, Inner West Council (NSW), Ipswich City Council, Ku-ring-gai Council, Lake Macquarie City Council, Macedon Ranges Shire Council, Maribyrnong Council, Maroondah City Council, Melton City Council, Nillumbik Shire Council, North Adelaide Waste Management Authority, RecycleSmart, Stonnington City Council, The Hills Shire Council, Sydney, Unley City Council (SA), Whittlesea City Council, Wollongong City Council, Wyndham City Council, Melbourne |
|
| Australia | Banyule City Council, Belmont City Council, Brisbane City Council, Campbelltown City Council (NSW), Cardinia Shire Council, City of Canada Bay Council, City of Kingston, City of Onkaparinga Council, Gold Coast City Council, Hume City Council, Inner West Council (NSW), Ipswich City Council, Ku-ring-gai Council, Lake Macquarie City Council, Macedon Ranges Shire Council, Maribyrnong Council, Maroondah City Council, Melton City Council, Nillumbik Shire Council, North Adelaide Waste Management Authority, Port Adelaide Enfield, South Australia, RecycleSmart, Stonnington City Council, The Hills Shire Council, Sydney, Unley City Council (SA), Whittlesea City Council, Wollongong City Council, Wyndham City Council, Melbourne |
|
||||||
| Austria | Andau, Apetlon, App CITIES, Bad Blumau, Bad Gleichenberg, Bad Loipersdorf, Bad Radkersburg, Bad Tatzmannsdorf, Bildein, Breitenbrunn am Neusiedler See, Breitenstein, Bruckneudorf, Buch - St. Magdalena, Burgau, Burgenländischer Müllverband, Dechantskirchen, Deutsch Goritz, Deutsch Jahrndorf, Deutsch Kaltenbrunn, Deutschkreutz, Dobl-Zwaring, Draßmarkt, Eberau, Eberndorf, Eberstein, Edelsbach bei Feldbach, Eggersdorf bei Graz, Eisenstadt, Fehring, Feistritz ob Bleiburg, Feldbach, Frankenau-Unterpullendorf, Frauenkirchen, Freistadt, Friedberg, Fürstenfeld, Gabersdorf, Gattendorf, Gols, Grafendorf bei Hartberg, Grafenstein, Gratkorn, Großwarasdorf, Großwilfersdorf, Gutenberg-Stenzengreith, Güssing, Hartberg, Heiligenkreuz am Waasen, Hofstätten an der Raab, Horitschon, Hornstein, Hüttenberg, Ilz, infeo, Innsbrucker Kommunalbetriebe, Jabing, Jagerberg, Kaindorf, Kaisersdorf, Kalsdorf bei Graz, Kapfenstein, Kirchberg an der Raab, Kleinmürbisch, Klingenbach, Klöch, Kohfidisch, Korneuburg, Laa an der Thaya, Leithaprodersdorf, Lieboch, Litzelsdorf, Loipersbach im Burgenland, Mariasdorf, Markt Hartmannsdorf, Markt Neuhodis, Marz, Mattersburg, Melk, Mettersdorf am Saßbach, Mischendorf, Mistelbach, Mitterdorf an der Raab, Mureck, Mörbisch am See, Neudorf bei Parndorf, Neufeld an der Leitha, Neusiedl am See, Nickelsdorf, Oberpullendorf, Oberwart, Oslip, Ottendorf an der Rittschein, Paldau, Pamhagen, Parndorf, Peggau, Pernegg an der Mur, Pilgersdorf, Pinggau, Pinkafeld, Podersdorf am See, Poggersdorf, Potzneusiedl, Poysdorf, Pöchlarn, Radmer, Ragnitz, Raiding, Rudersdorf, Rust, Saalfelden am Steinernen Meer, Sankt Oswald bei Plankenwarth, Schäffern, Schützen am Gebirge, Seiersberg-Pirka, Sigleß, Sinabelkirchen, St. Andrä, St. Anna am Aigen, St. Johann in der Haide, St. Lorenzen am Wechsel, St. Margarethen an der Raab, St. Margarethen im Burgenland, St. Peter - Freienstein, St. Peter am Ottersbach, St. Ruprecht an der Raab, St. Veit in der Südsteiermark, Stadt Salzburg, Stadtservice Korneuburg, Stegersbach, Steinbrunn, Steuerberg, Stinatz, Stiwoll, Stockerau, Söchau, Thal, Tieschen, Tulln an der Donau, Umweltprofis, Unterfrauenhaid, Unterkohlstätten, Unterlamm, Vasoldsberg, Vordernberg, Völkermarkt, Weiz, Werfenweng, Wies, Wiesen, Wiesfleck, Wimpassing an der Leitha, Winden am See, Wolfsberg, Wolkersdorf im Weinviertel, WSZ Moosburg, Zagersdorf, Zillingtal, Zurndorf, Übelbach |
|
| Austria | Andau, Apetlon, App CITIES, Bad Blumau, Bad Gleichenberg, Bad Loipersdorf, Bad Radkersburg, Bad Tatzmannsdorf, Bildein, Breitenbrunn am Neusiedler See, Breitenstein, Bruckneudorf, Buch - St. Magdalena, Burgau, Burgenländischer Müllverband, Dechantskirchen, Deutsch Goritz, Deutsch Jahrndorf, Deutsch Kaltenbrunn, Deutschkreutz, Dobl-Zwaring, Draßmarkt, Eberau, Eberndorf, Eberstein, Edelsbach bei Feldbach, Eggersdorf bei Graz, Eisenstadt, Fehring, Feistritz ob Bleiburg, Feldbach, Frankenau-Unterpullendorf, Frauenkirchen, Freistadt, Friedberg, Fürstenfeld, Gabersdorf, Gattendorf, Gols, Grafendorf bei Hartberg, Grafenstein, Gratkorn, Großwarasdorf, Großwilfersdorf, Gutenberg-Stenzengreith, Güssing, Hartberg, Heiligenkreuz am Waasen, Hofstätten an der Raab, Horitschon, Hornstein, Hüttenberg, Ilz, infeo, Innsbrucker Kommunalbetriebe, Jabing, Jagerberg, Kaindorf, Kaisersdorf, Kalsdorf bei Graz, Kapfenstein, Kirchberg an der Raab, Kleinmürbisch, Klingenbach, Klöch, Kohfidisch, Korneuburg, Laa an der Thaya, Leithaprodersdorf, Lieboch, Litzelsdorf, Loipersbach im Burgenland, Mariasdorf, Markt Hartmannsdorf, Markt Neuhodis, Marz, Mattersburg, Melk, Mettersdorf am Saßbach, Mischendorf, Mistelbach, Mitterdorf an der Raab, Mureck, Mörbisch am See, Neudorf bei Parndorf, Neufeld an der Leitha, Neusiedl am See, Nickelsdorf, Oberpullendorf, Oberwart, Oslip, Ottendorf an der Rittschein, Paldau, Pamhagen, Parndorf, Peggau, Pernegg an der Mur, Pilgersdorf, Pinggau, Pinkafeld, Podersdorf am See, Poggersdorf, Potzneusiedl, Poysdorf, Pöchlarn, Radmer, Ragnitz, Raiding, Rudersdorf, Rust, Saalfelden am Steinernen Meer, Sankt Oswald bei Plankenwarth, Schäffern, Schützen am Gebirge, Seiersberg-Pirka, Sigleß, Sinabelkirchen, St. Andrä, St. Anna am Aigen, St. Johann in der Haide, St. Lorenzen am Wechsel, St. Margarethen an der Raab, St. Margarethen im Burgenland, St. Peter - Freienstein, St. Peter am Ottersbach, St. Ruprecht an der Raab, St. Veit in der Südsteiermark, Stadt Salzburg, Stadtservice Korneuburg, Stegersbach, Steinbrunn, Steuerberg, Stinatz, Stiwoll, Stockerau, Söchau, Thal, Tieschen, Tulln an der Donau, Umweltprofis, Unterfrauenhaid, Unterkohlstätten, Unterlamm, Vasoldsberg, Vordernberg, Völkermarkt, Weiz, Werfenweng, Wies, Wiesen, Wiesfleck, Wimpassing an der Leitha, Winden am See, Wolfsberg, Wolkersdorf im Weinviertel, WSZ Moosburg, Zagersdorf, Zillingtal, Zurndorf, Übelbach |
|
||||||
| Belgium | Hygea, Limburg.net, Recycle! |
|
| Belgium | Hygea, Limburg.net, Recycle! |
|
||||||
| Canada | City of Toronto |
|
| Canada | City of Toronto |
|
||||||
|
|||||||
Reference in New Issue
Block a user