uk_bin_collection 0.143.6__py3-none-any.whl → 0.144.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uk_bin_collection/tests/input.json +9 -0
- uk_bin_collection/uk_bin_collection/councils/GreatYarmouthBoroughCouncil.py +140 -0
- {uk_bin_collection-0.143.6.dist-info → uk_bin_collection-0.144.0.dist-info}/METADATA +1 -1
- {uk_bin_collection-0.143.6.dist-info → uk_bin_collection-0.144.0.dist-info}/RECORD +7 -6
- {uk_bin_collection-0.143.6.dist-info → uk_bin_collection-0.144.0.dist-info}/LICENSE +0 -0
- {uk_bin_collection-0.143.6.dist-info → uk_bin_collection-0.144.0.dist-info}/WHEEL +0 -0
- {uk_bin_collection-0.143.6.dist-info → uk_bin_collection-0.144.0.dist-info}/entry_points.txt +0 -0
@@ -877,6 +877,15 @@
|
|
877
877
|
"wiki_name": "Gravesham Borough Council",
|
878
878
|
"wiki_note": "Pass the UPRN. You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search)."
|
879
879
|
},
|
880
|
+
"GreatYarmouthBoroughCouncil": {
|
881
|
+
"postcode": "NR31 7EB",
|
882
|
+
"skip_get_url": true,
|
883
|
+
"uprn": "100090834792",
|
884
|
+
"url": "https://myaccount.great-yarmouth.gov.uk/article/6456/Find-my-waste-collection-days",
|
885
|
+
"web_driver": "http://selenium:4444",
|
886
|
+
"wiki_name": "Great Yarmouth Borough Council",
|
887
|
+
"wiki_note": "Pass the postcode, and UPRN in their respective parameters. This parser requires a Selenium webdriver."
|
888
|
+
},
|
880
889
|
"GuildfordCouncil": {
|
881
890
|
"house_number": "THE LODGE, PUTTENHAM HILL HOUSE, PUTTENHAM HILL, PUTTENHAM, GUILDFORD, GU3 1AH",
|
882
891
|
"postcode": "GU3 1AH",
|
@@ -0,0 +1,140 @@
|
|
1
|
+
import time
|
2
|
+
|
3
|
+
from bs4 import BeautifulSoup
|
4
|
+
from selenium.webdriver.common.by import By
|
5
|
+
from selenium.webdriver.support import expected_conditions as EC
|
6
|
+
from selenium.webdriver.support.ui import Select, WebDriverWait
|
7
|
+
from selenium.webdriver.common.keys import Keys
|
8
|
+
from datetime import datetime
|
9
|
+
|
10
|
+
from uk_bin_collection.uk_bin_collection.common import *
|
11
|
+
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
|
12
|
+
|
13
|
+
# import the wonderful Beautiful Soup and the URL grabber
|
14
|
+
class CouncilClass(AbstractGetBinDataClass):
|
15
|
+
"""
|
16
|
+
Concrete classes have to implement all abstract operations of the
|
17
|
+
base class. They can also override some operations with a default
|
18
|
+
implementation.
|
19
|
+
"""
|
20
|
+
|
21
|
+
def parse_data(self, page: str, **kwargs) -> dict:
|
22
|
+
driver = None
|
23
|
+
try:
|
24
|
+
user_uprn = kwargs.get("uprn")
|
25
|
+
user_postcode = kwargs.get("postcode")
|
26
|
+
headless = kwargs.get("headless")
|
27
|
+
web_driver = kwargs.get("web_driver")
|
28
|
+
url = kwargs.get("url")
|
29
|
+
|
30
|
+
check_uprn(user_uprn)
|
31
|
+
check_postcode(user_postcode)
|
32
|
+
|
33
|
+
driver = create_webdriver(web_driver, headless, None, __name__)
|
34
|
+
|
35
|
+
driver.get(url)
|
36
|
+
|
37
|
+
wait = WebDriverWait(driver, 10)
|
38
|
+
accept_cookies_button = wait.until(
|
39
|
+
EC.element_to_be_clickable(
|
40
|
+
(
|
41
|
+
By.NAME,
|
42
|
+
"acceptall",
|
43
|
+
)
|
44
|
+
)
|
45
|
+
)
|
46
|
+
accept_cookies_button.click()
|
47
|
+
|
48
|
+
postcode_input = WebDriverWait(driver, 10).until(
|
49
|
+
EC.element_to_be_clickable(
|
50
|
+
(By.ID, "WASTECOLLECTIONCALENDARV2_ADDRESS_ALSF")
|
51
|
+
)
|
52
|
+
)
|
53
|
+
|
54
|
+
postcode_input.send_keys(user_postcode)
|
55
|
+
postcode_input.send_keys(Keys.TAB + Keys.ENTER)
|
56
|
+
|
57
|
+
time.sleep(2)
|
58
|
+
# Wait for address box to be visible
|
59
|
+
select_address_input = WebDriverWait(driver, 10).until(
|
60
|
+
EC.presence_of_element_located(
|
61
|
+
(
|
62
|
+
By.ID,
|
63
|
+
"WASTECOLLECTIONCALENDARV2_ADDRESS_ALML",
|
64
|
+
)
|
65
|
+
)
|
66
|
+
)
|
67
|
+
select_address_input.click()
|
68
|
+
|
69
|
+
# Assume select_address_input is already the dropdown <select> element
|
70
|
+
select = Select(select_address_input)
|
71
|
+
|
72
|
+
# Select the option with the matching UPRN
|
73
|
+
select.select_by_value(user_uprn)
|
74
|
+
select_address_input.click()
|
75
|
+
|
76
|
+
select_address_input.send_keys(Keys.TAB * 2 + Keys.ENTER)
|
77
|
+
|
78
|
+
time.sleep(5)
|
79
|
+
# Wait for the specified div to be present
|
80
|
+
target_div = WebDriverWait(driver, 10).until(
|
81
|
+
EC.presence_of_element_located((By.ID, "WASTECOLLECTIONCALENDARV2_LOOKUP_SHOWSCHEDULE"))
|
82
|
+
)
|
83
|
+
|
84
|
+
soup = BeautifulSoup(driver.page_source, "html.parser")
|
85
|
+
|
86
|
+
bin_data = {"bins": []}
|
87
|
+
next_collections = {} # Dictionary to store the next collection for each bin type
|
88
|
+
|
89
|
+
bin_types = {
|
90
|
+
"bulky": "Bulky Collection",
|
91
|
+
"green": "Recycling",
|
92
|
+
"black": "General Waste",
|
93
|
+
"brown": "Garden Waste"
|
94
|
+
}
|
95
|
+
|
96
|
+
for div in soup.select(".collection-area"):
|
97
|
+
img = div.select_one("img")
|
98
|
+
detail = div.select_one(".collection-detail")
|
99
|
+
date_text = detail.select_one("b").get_text(strip=True)
|
100
|
+
|
101
|
+
try:
|
102
|
+
# Parse the date text
|
103
|
+
date_obj = datetime.strptime(date_text + " 2025", "%A %d %B %Y")
|
104
|
+
if date_obj.date() < datetime.today().date():
|
105
|
+
continue # Skip past dates
|
106
|
+
except ValueError:
|
107
|
+
continue
|
108
|
+
|
109
|
+
# Determine bin type from alt or description
|
110
|
+
description = detail.get_text(separator=" ", strip=True).lower()
|
111
|
+
alt_text = img['alt'].lower()
|
112
|
+
|
113
|
+
for key, name in bin_types.items():
|
114
|
+
if key in alt_text or key in description:
|
115
|
+
# Format date as dd/mm/yyyy
|
116
|
+
formatted_date = date_obj.strftime("%d/%m/%Y")
|
117
|
+
bin_entry = {
|
118
|
+
"type": name,
|
119
|
+
"collectionDate": formatted_date
|
120
|
+
}
|
121
|
+
|
122
|
+
# Only keep the earliest date for each bin type
|
123
|
+
if name not in next_collections or date_obj < datetime.strptime(next_collections[name]["collectionDate"], "%d/%m/%Y"):
|
124
|
+
next_collections[name] = bin_entry
|
125
|
+
print(f"Found next collection for {name}: {formatted_date}") # Debug output
|
126
|
+
break
|
127
|
+
|
128
|
+
# Add the next collections to the bin_data
|
129
|
+
bin_data["bins"] = list(next_collections.values())
|
130
|
+
|
131
|
+
except Exception as e:
|
132
|
+
print(f"An error occurred: {e}")
|
133
|
+
raise
|
134
|
+
finally:
|
135
|
+
if driver:
|
136
|
+
driver.quit()
|
137
|
+
|
138
|
+
print("\nFinal bin data:")
|
139
|
+
print(bin_data) # Debug output
|
140
|
+
return bin_data
|
@@ -3,7 +3,7 @@ uk_bin_collection/tests/check_selenium_url_in_input.json.py,sha256=Iecdja0I3XIiY
|
|
3
3
|
uk_bin_collection/tests/council_feature_input_parity.py,sha256=DO6Mk4ImYgM5ZCZ-cutwz5RoYYWZRLYx2tr6zIs_9Rc,3843
|
4
4
|
uk_bin_collection/tests/features/environment.py,sha256=VQZjJdJI_kZn08M0j5cUgvKT4k3iTw8icJge1DGOkoA,127
|
5
5
|
uk_bin_collection/tests/features/validate_council_outputs.feature,sha256=SJK-Vc737hrf03tssxxbeg_JIvAH-ddB8f6gU1LTbuQ,251
|
6
|
-
uk_bin_collection/tests/input.json,sha256=
|
6
|
+
uk_bin_collection/tests/input.json,sha256=ArQftTY8SVx1lttw69j6vTOydzcq2D-aza_sXwjQq5I,121959
|
7
7
|
uk_bin_collection/tests/output.schema,sha256=ZwKQBwYyTDEM4G2hJwfLUVM-5v1vKRvRK9W9SS1sd18,1086
|
8
8
|
uk_bin_collection/tests/step_defs/step_helpers/file_handler.py,sha256=Ygzi4V0S1MIHqbdstUlIqtRIwnynvhu4UtpweJ6-5N8,1474
|
9
9
|
uk_bin_collection/tests/step_defs/test_validate_council.py,sha256=VZ0a81sioJULD7syAYHjvK_-nT_Rd36tUyzPetSA0gk,3475
|
@@ -131,6 +131,7 @@ uk_bin_collection/uk_bin_collection/councils/GlasgowCityCouncil.py,sha256=9Rk9Kf
|
|
131
131
|
uk_bin_collection/uk_bin_collection/councils/GloucesterCityCouncil.py,sha256=67D8rbhn0t4rsCSJRTXZVtHmph2wT6rJiexNWKOnMok,4625
|
132
132
|
uk_bin_collection/uk_bin_collection/councils/GooglePublicCalendarCouncil.py,sha256=KiDfL9AVhUlRuY98sbNs_Fb-vUVeo5n1bBShTJHcO8w,1173
|
133
133
|
uk_bin_collection/uk_bin_collection/councils/GraveshamBoroughCouncil.py,sha256=ueQ9xFiTxMUBTGV9VjtySHA1EFWliTM0AeNePBIG9ho,4568
|
134
|
+
uk_bin_collection/uk_bin_collection/councils/GreatYarmouthBoroughCouncil.py,sha256=6NIzcn6iiXHEeBer1TlUAAXRWSJOFiYO1IUDmLkF7R0,5295
|
134
135
|
uk_bin_collection/uk_bin_collection/councils/GuildfordCouncil.py,sha256=9pVrmQhZcK2AD8gX8mNvP--L4L9KaY6L3B822VX6fec,5695
|
135
136
|
uk_bin_collection/uk_bin_collection/councils/GwyneddCouncil.py,sha256=eK2KkY1NbIxVtBruQYSNPA0J7fuzMik5it02dFbKYV0,1855
|
136
137
|
uk_bin_collection/uk_bin_collection/councils/HackneyCouncil.py,sha256=vO3ugk5fcdkYTslXNKmpJC84-ZHqrdFqW8zfX7TSiTQ,3104
|
@@ -328,8 +329,8 @@ uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bId
|
|
328
329
|
uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=EQWRhZ2pEejlvm0fPyOTsOHKvUZmPnxEYO_OWRGKTjs,1158
|
329
330
|
uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
|
330
331
|
uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=YvmHfZqanwrJ8ToGch34x-L-7yPe31nB_x77_Mgl_vo,4545
|
331
|
-
uk_bin_collection-0.
|
332
|
-
uk_bin_collection-0.
|
333
|
-
uk_bin_collection-0.
|
334
|
-
uk_bin_collection-0.
|
335
|
-
uk_bin_collection-0.
|
332
|
+
uk_bin_collection-0.144.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
|
333
|
+
uk_bin_collection-0.144.0.dist-info/METADATA,sha256=k-jkQ-brkbppOAbOHd39-gv751ReJOWBS72yj-zZSyI,19858
|
334
|
+
uk_bin_collection-0.144.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
335
|
+
uk_bin_collection-0.144.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
|
336
|
+
uk_bin_collection-0.144.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{uk_bin_collection-0.143.6.dist-info → uk_bin_collection-0.144.0.dist-info}/entry_points.txt
RENAMED
File without changes
|