uk_bin_collection 0.152.7__py3-none-any.whl → 0.152.9__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 +11 -15
- uk_bin_collection/uk_bin_collection/councils/AngusCouncil.py +69 -46
- uk_bin_collection/uk_bin_collection/councils/BCPCouncil.py +119 -37
- uk_bin_collection/uk_bin_collection/councils/BarnetCouncil.py +158 -115
- uk_bin_collection/uk_bin_collection/councils/BasildonCouncil.py +87 -66
- uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py +2 -0
- uk_bin_collection/uk_bin_collection/councils/BlabyDistrictCouncil.py +5 -1
- uk_bin_collection/uk_bin_collection/councils/BlaenauGwentCountyBoroughCouncil.py +91 -66
- uk_bin_collection/uk_bin_collection/councils/BroxbourneCouncil.py +88 -67
- uk_bin_collection/uk_bin_collection/councils/BuckinghamshireCouncil.py +67 -56
- uk_bin_collection/uk_bin_collection/councils/ChelmsfordCityCouncil.py +63 -95
- uk_bin_collection/uk_bin_collection/councils/CherwellDistrictCouncil.py +39 -18
- uk_bin_collection/uk_bin_collection/councils/ChorleyCouncil.py +106 -97
- uk_bin_collection/uk_bin_collection/councils/CopelandBoroughCouncil.py +80 -75
- uk_bin_collection/uk_bin_collection/councils/CotswoldDistrictCouncil.py +191 -67
- uk_bin_collection/uk_bin_collection/councils/CoventryCityCouncil.py +6 -2
- uk_bin_collection/uk_bin_collection/councils/MidlothianCouncil.py +12 -3
- uk_bin_collection/uk_bin_collection/councils/NewcastleUnderLymeCouncil.py +2 -1
- uk_bin_collection/uk_bin_collection/councils/RoyalBoroughofGreenwich.py +8 -2
- uk_bin_collection/uk_bin_collection/councils/SouthwarkCouncil.py +23 -1
- uk_bin_collection/uk_bin_collection/councils/SwindonBoroughCouncil.py +2 -1
- uk_bin_collection/uk_bin_collection/councils/WakefieldCityCouncil.py +4 -1
- uk_bin_collection/uk_bin_collection/councils/WestOxfordshireDistrictCouncil.py +3 -3
- uk_bin_collection/uk_bin_collection/get_bin_data.py +1 -1
- {uk_bin_collection-0.152.7.dist-info → uk_bin_collection-0.152.9.dist-info}/METADATA +1 -1
- {uk_bin_collection-0.152.7.dist-info → uk_bin_collection-0.152.9.dist-info}/RECORD +29 -30
- uk_bin_collection/uk_bin_collection/councils/AylesburyValeCouncil.py +0 -69
- {uk_bin_collection-0.152.7.dist-info → uk_bin_collection-0.152.9.dist-info}/LICENSE +0 -0
- {uk_bin_collection-0.152.7.dist-info → uk_bin_collection-0.152.9.dist-info}/WHEEL +0 -0
- {uk_bin_collection-0.152.7.dist-info → uk_bin_collection-0.152.9.dist-info}/entry_points.txt +0 -0
@@ -3,19 +3,14 @@ from selenium.webdriver.common.by import By
|
|
3
3
|
from selenium.webdriver.support import expected_conditions as EC
|
4
4
|
from selenium.webdriver.support.ui import Select
|
5
5
|
from selenium.webdriver.support.wait import WebDriverWait
|
6
|
+
import re
|
7
|
+
import time
|
6
8
|
|
7
9
|
from uk_bin_collection.uk_bin_collection.common import *
|
8
10
|
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
|
9
11
|
|
10
12
|
|
11
|
-
# import the wonderful Beautiful Soup and the URL grabber
|
12
13
|
class CouncilClass(AbstractGetBinDataClass):
|
13
|
-
"""
|
14
|
-
Concrete classes have to implement all abstract operations of the
|
15
|
-
base class. They can also override some operations with a default
|
16
|
-
implementation.
|
17
|
-
"""
|
18
|
-
|
19
14
|
def parse_data(self, page: str, **kwargs) -> dict:
|
20
15
|
driver = None
|
21
16
|
try:
|
@@ -29,85 +24,115 @@ class CouncilClass(AbstractGetBinDataClass):
|
|
29
24
|
|
30
25
|
# Create Selenium webdriver
|
31
26
|
driver = create_webdriver(web_driver, headless, None, __name__)
|
32
|
-
|
33
|
-
|
27
|
+
|
28
|
+
# Navigate to the main page first
|
29
|
+
driver.get("https://www.blaenau-gwent.gov.uk/en/resident/waste-recycling/")
|
30
|
+
|
31
|
+
# Handle cookie overlay if present
|
32
|
+
try:
|
33
|
+
# Wait a moment for any overlays to appear
|
34
|
+
WebDriverWait(driver, 3).until(
|
35
|
+
EC.presence_of_element_located((By.ID, "ccc-overlay"))
|
36
|
+
)
|
37
|
+
# Try to find and click cookie accept buttons
|
38
|
+
cookie_buttons = [
|
39
|
+
"//button[contains(text(), 'Accept')]",
|
40
|
+
"//button[contains(text(), 'OK')]",
|
41
|
+
"//button[@id='ccc-recommended-settings']",
|
42
|
+
"//button[contains(@class, 'cookie')]"
|
43
|
+
]
|
44
|
+
for button_xpath in cookie_buttons:
|
45
|
+
try:
|
46
|
+
cookie_button = driver.find_element(By.XPATH, button_xpath)
|
47
|
+
if cookie_button.is_displayed():
|
48
|
+
cookie_button.click()
|
49
|
+
break
|
50
|
+
except:
|
51
|
+
continue
|
52
|
+
except:
|
53
|
+
pass # No cookie overlay found
|
54
|
+
|
55
|
+
# Find and extract the collection day URL
|
56
|
+
find_collection_link = WebDriverWait(driver, 10).until(
|
57
|
+
EC.presence_of_element_located((By.XPATH, "//a[contains(text(), 'Find Your Collection Day')]"))
|
34
58
|
)
|
59
|
+
collection_url = find_collection_link.get_attribute("href")
|
60
|
+
|
61
|
+
# Navigate to the collection portal
|
62
|
+
driver.get(collection_url)
|
35
63
|
|
36
|
-
# Wait for the postcode field
|
37
|
-
|
64
|
+
# Wait for the postcode field and enter postcode
|
65
|
+
postcode_input = WebDriverWait(driver, 10).until(
|
38
66
|
EC.presence_of_element_located((By.ID, "postcodeSearch"))
|
39
67
|
)
|
40
|
-
|
68
|
+
postcode_input.send_keys(user_postcode)
|
41
69
|
|
42
|
-
# Click
|
43
|
-
|
44
|
-
EC.
|
45
|
-
(By.XPATH, '//button[@class="govuk-button mt-4"]')
|
46
|
-
)
|
70
|
+
# Click Find button
|
71
|
+
find_button = WebDriverWait(driver, 10).until(
|
72
|
+
EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Find')]"))
|
47
73
|
)
|
48
|
-
|
74
|
+
find_button.click()
|
49
75
|
|
50
|
-
# Wait for
|
76
|
+
# Wait for address dropdown and select by UPRN
|
51
77
|
WebDriverWait(driver, 10).until(
|
52
78
|
EC.presence_of_element_located((By.ID, "addressSelect"))
|
53
79
|
)
|
54
|
-
|
55
80
|
dropdown = Select(driver.find_element(By.ID, "addressSelect"))
|
56
81
|
dropdown.select_by_value(user_uprn)
|
57
82
|
|
58
|
-
# Wait for
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
)
|
65
|
-
)
|
83
|
+
# Wait for collection data to load
|
84
|
+
time.sleep(3) # Give JavaScript time to process the selection
|
85
|
+
|
86
|
+
# Wait for the actual collection data to appear
|
87
|
+
WebDriverWait(driver, 20).until(
|
88
|
+
lambda d: "Your next collections" in d.page_source and ("Recycling" in d.page_source or "Refuse" in d.page_source)
|
66
89
|
)
|
67
90
|
|
68
91
|
soup = BeautifulSoup(driver.page_source, features="html.parser")
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
"
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
92
|
+
page_text = soup.get_text()
|
93
|
+
|
94
|
+
# Find the collections section in the text
|
95
|
+
if "Your next collections" in page_text:
|
96
|
+
# Extract the section after "Your next collections"
|
97
|
+
collections_section = page_text.split("Your next collections")[1]
|
98
|
+
collections_section = collections_section.split("Related content")[0] # Stop at Related content
|
99
|
+
|
100
|
+
# Use regex to find collection patterns
|
101
|
+
# Pattern to match: "Collection Type" followed by "Day Date Month" (stopping before 'followed')
|
102
|
+
pattern = r'(Recycling collection|Refuse Bin)([A-Za-z]+ \d+ [A-Za-z]+)(?=followed|$|[A-Z])'
|
103
|
+
matches = re.findall(pattern, collections_section)
|
104
|
+
|
105
|
+
for bin_type, date_text in matches:
|
106
|
+
try:
|
107
|
+
# Clean up the date text
|
108
|
+
date_text = date_text.strip()
|
109
|
+
if "followed by" in date_text:
|
110
|
+
date_text = date_text.split("followed by")[0].strip()
|
111
|
+
|
112
|
+
# Parse the date
|
113
|
+
collection_date = datetime.strptime(date_text, "%A %d %B")
|
114
|
+
|
115
|
+
# Set the correct year
|
116
|
+
current_year = datetime.now().year
|
117
|
+
current_month = datetime.now().month
|
118
|
+
|
119
|
+
if (current_month > 10) and (collection_date.month < 3):
|
120
|
+
collection_date = collection_date.replace(year=(current_year + 1))
|
121
|
+
else:
|
122
|
+
collection_date = collection_date.replace(year=current_year)
|
123
|
+
|
124
|
+
dict_data = {
|
125
|
+
"type": bin_type,
|
126
|
+
"collectionDate": collection_date.strftime("%d/%m/%Y"),
|
127
|
+
}
|
128
|
+
data["bins"].append(dict_data)
|
129
|
+
except ValueError:
|
130
|
+
pass # Skip if date parsing fails
|
103
131
|
|
104
132
|
except Exception as e:
|
105
|
-
# Here you can log the exception if needed
|
106
133
|
print(f"An error occurred: {e}")
|
107
|
-
# Optionally, re-raise the exception if you want it to propagate
|
108
134
|
raise
|
109
135
|
finally:
|
110
|
-
# This block ensures that the driver is closed regardless of an exception
|
111
136
|
if driver:
|
112
137
|
driver.quit()
|
113
|
-
return data
|
138
|
+
return data
|
@@ -1,83 +1,104 @@
|
|
1
1
|
from datetime import datetime
|
2
|
+
import time
|
2
3
|
|
3
|
-
import requests
|
4
4
|
from bs4 import BeautifulSoup
|
5
|
+
from selenium.webdriver.common.by import By
|
6
|
+
from selenium.webdriver.common.keys import Keys
|
7
|
+
from selenium.webdriver.support import expected_conditions as EC
|
8
|
+
from selenium.webdriver.support.ui import Select, WebDriverWait
|
5
9
|
|
6
10
|
from uk_bin_collection.uk_bin_collection.common import *
|
7
11
|
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
|
8
12
|
|
9
13
|
|
10
14
|
class CouncilClass(AbstractGetBinDataClass):
|
11
|
-
"""
|
12
|
-
Concrete classes have to implement all abstract operations of the
|
13
|
-
base class. They can also override some operations with a default
|
14
|
-
implementation.
|
15
|
-
"""
|
16
|
-
|
17
15
|
def parse_data(self, page: str, **kwargs) -> dict:
|
18
16
|
user_uprn = kwargs.get("uprn")
|
19
17
|
user_postcode = kwargs.get("postcode")
|
18
|
+
web_driver = kwargs.get("web_driver")
|
19
|
+
headless = kwargs.get("headless")
|
20
|
+
|
20
21
|
check_uprn(user_uprn)
|
21
22
|
check_postcode(user_postcode)
|
23
|
+
|
22
24
|
bindata = {"bins": []}
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
rows = table.find_all("tr")
|
44
|
-
|
45
|
-
current_year = datetime.now().year
|
46
|
-
current_month = datetime.now().month
|
47
|
-
|
48
|
-
# Process each row into a list of dictionaries
|
49
|
-
for row in rows[1:]: # Skip the header row
|
50
|
-
columns = row.find_all("td")
|
51
|
-
collection_date_text = (
|
52
|
-
columns[0].get_text(separator=" ").replace("\xa0", " ").strip()
|
25
|
+
driver = create_webdriver(web_driver, headless, None, __name__)
|
26
|
+
|
27
|
+
try:
|
28
|
+
driver.get("https://www.broxbourne.gov.uk/bin-collection-date")
|
29
|
+
time.sleep(8)
|
30
|
+
|
31
|
+
# Handle cookie banner with multiple attempts
|
32
|
+
|
33
|
+
try:
|
34
|
+
cookie_btn = WebDriverWait(driver, 15).until(
|
35
|
+
EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Allow all')]"))
|
36
|
+
)
|
37
|
+
cookie_btn.click()
|
38
|
+
except:
|
39
|
+
pass
|
40
|
+
|
41
|
+
# Find postcode input
|
42
|
+
postcode_input = WebDriverWait(driver, 20).until(
|
43
|
+
EC.element_to_be_clickable((By.XPATH, "//input[@autocomplete='postal-code']"))
|
53
44
|
)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
45
|
+
postcode_input.clear()
|
46
|
+
postcode_input.send_keys(user_postcode)
|
47
|
+
|
48
|
+
# Press Enter to lookup
|
49
|
+
postcode_input.send_keys(Keys.RETURN)
|
50
|
+
|
51
|
+
# Select address
|
52
|
+
address_select = WebDriverWait(driver, 15).until(
|
53
|
+
EC.presence_of_element_located((By.XPATH, "//select"))
|
54
|
+
)
|
55
|
+
Select(address_select).select_by_value(user_uprn)
|
56
|
+
|
57
|
+
# Click Next button
|
58
|
+
next_btn = WebDriverWait(driver, 15).until(
|
59
|
+
EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Next')]"))
|
60
|
+
)
|
61
|
+
next_btn.click()
|
62
|
+
|
63
|
+
# Get results
|
64
|
+
WebDriverWait(driver, 15).until(
|
65
|
+
EC.presence_of_element_located((By.XPATH, "//h1[contains(text(), 'When is my bin collection date?')]"))
|
66
|
+
)
|
67
|
+
|
68
|
+
table = WebDriverWait(driver, 15).until(
|
69
|
+
EC.presence_of_element_located((By.XPATH, "//h1[contains(text(), 'When is my bin collection date?')]/following::table[1]"))
|
70
|
+
)
|
71
|
+
|
72
|
+
soup = BeautifulSoup(table.get_attribute('outerHTML'), 'html.parser')
|
73
|
+
rows = soup.find_all('tr')
|
74
|
+
|
75
|
+
current_year = datetime.now().year
|
76
|
+
current_month = datetime.now().month
|
77
|
+
|
78
|
+
for row in rows[1:]:
|
79
|
+
columns = row.find_all('td')
|
80
|
+
if len(columns) >= 2:
|
81
|
+
collection_date_text = columns[0].get_text().strip()
|
82
|
+
service = columns[1].get_text().strip()
|
83
|
+
|
84
|
+
if collection_date_text:
|
85
|
+
try:
|
86
|
+
collection_date = datetime.strptime(collection_date_text, "%a %d %b")
|
87
|
+
if collection_date.month == 1 and current_month != 1:
|
88
|
+
collection_date = collection_date.replace(year=current_year + 1)
|
89
|
+
else:
|
90
|
+
collection_date = collection_date.replace(year=current_year)
|
91
|
+
|
92
|
+
bindata["bins"].append({
|
93
|
+
"type": service,
|
94
|
+
"collectionDate": collection_date.strftime("%d/%m/%Y")
|
95
|
+
})
|
96
|
+
except ValueError:
|
97
|
+
continue
|
98
|
+
|
99
|
+
bindata["bins"].sort(key=lambda x: datetime.strptime(x["collectionDate"], "%d/%m/%Y"))
|
100
|
+
|
101
|
+
finally:
|
102
|
+
driver.quit()
|
103
|
+
|
104
|
+
return bindata
|
@@ -20,6 +20,7 @@ class CouncilClass(AbstractGetBinDataClass):
|
|
20
20
|
data = {"bins": []}
|
21
21
|
user_paon = kwargs.get("paon")
|
22
22
|
user_postcode = kwargs.get("postcode")
|
23
|
+
user_uprn = kwargs.get("uprn")
|
23
24
|
web_driver = kwargs.get("web_driver")
|
24
25
|
headless = kwargs.get("headless")
|
25
26
|
check_paon(user_paon)
|
@@ -27,9 +28,13 @@ class CouncilClass(AbstractGetBinDataClass):
|
|
27
28
|
|
28
29
|
# Create Selenium webdriver
|
29
30
|
driver = create_webdriver(web_driver, headless, None, __name__)
|
30
|
-
driver.get(
|
31
|
-
|
31
|
+
driver.get(kwargs.get("url"))
|
32
|
+
|
33
|
+
# Click "Check now" button
|
34
|
+
check_now_button = WebDriverWait(driver, 10).until(
|
35
|
+
EC.element_to_be_clickable((By.XPATH, "//a[contains(text(), 'Check now')]"))
|
32
36
|
)
|
37
|
+
check_now_button.click()
|
33
38
|
|
34
39
|
# Wait for the postcode field to appear then populate it
|
35
40
|
inputElement_postcode = WebDriverWait(driver, 10).until(
|
@@ -37,71 +42,77 @@ class CouncilClass(AbstractGetBinDataClass):
|
|
37
42
|
)
|
38
43
|
inputElement_postcode.send_keys(user_postcode)
|
39
44
|
|
40
|
-
# Click
|
41
|
-
|
42
|
-
EC.
|
43
|
-
(By.XPATH, '//button[@class="govuk-button mt-4"]')
|
44
|
-
)
|
45
|
+
# Click Find button
|
46
|
+
find_button = WebDriverWait(driver, 10).until(
|
47
|
+
EC.element_to_be_clickable((By.XPATH, "//button[contains(text(), 'Find')]"))
|
45
48
|
)
|
46
|
-
|
49
|
+
find_button.click()
|
47
50
|
|
48
|
-
# Wait for the
|
49
|
-
|
50
|
-
|
51
|
-
(
|
52
|
-
By.XPATH,
|
53
|
-
"//select[@id='addressSelect']//option[contains(., '"
|
54
|
-
+ user_paon
|
55
|
-
+ "')]",
|
56
|
-
)
|
51
|
+
# Wait for the address dropdown and select by UPRN
|
52
|
+
if user_uprn:
|
53
|
+
address_option = WebDriverWait(driver, 10).until(
|
54
|
+
EC.element_to_be_clickable((By.XPATH, f"//option[@value='{user_uprn}']"))
|
57
55
|
)
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
By.XPATH,
|
65
|
-
'//div[@class="ant-row d-flex justify-content-between mb-4 mt-2 css-2rgkd4"]',
|
56
|
+
address_option.click()
|
57
|
+
else:
|
58
|
+
# Fallback to selecting by address text
|
59
|
+
address_option = WebDriverWait(driver, 10).until(
|
60
|
+
EC.element_to_be_clickable(
|
61
|
+
(By.XPATH, f"//select[@id='addressSelect']//option[contains(., '{user_paon}')]")
|
66
62
|
)
|
67
63
|
)
|
68
|
-
|
69
|
-
|
70
|
-
soup = BeautifulSoup(driver.page_source, features="html.parser")
|
64
|
+
address_option.click()
|
71
65
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
"class": "ant-row d-flex justify-content-between mb-4 mt-2 css-2rgkd4"
|
76
|
-
},
|
77
|
-
)
|
66
|
+
# Wait a moment for the page to update after address selection
|
67
|
+
import time
|
68
|
+
time.sleep(2)
|
78
69
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
70
|
+
# Wait for collection information to appear - try multiple possible selectors
|
71
|
+
try:
|
72
|
+
WebDriverWait(driver, 15).until(
|
73
|
+
EC.presence_of_element_located((By.XPATH, "//h2[contains(text(), 'Your next collections')]"))
|
74
|
+
)
|
75
|
+
except:
|
76
|
+
# Alternative wait for collection data structure
|
77
|
+
WebDriverWait(driver, 10).until(
|
78
|
+
EC.presence_of_element_located((By.XPATH, "//div[contains(@class, 'ant-row') and contains(@class, 'd-flex')]//h3[@class='text-white']"))
|
79
|
+
)
|
85
80
|
|
81
|
+
soup = BeautifulSoup(driver.page_source, features="html.parser")
|
82
|
+
|
83
|
+
# Find all collection items with the specific structure - try multiple class patterns
|
84
|
+
collection_items = soup.find_all("div", class_=lambda x: x and "ant-col" in x and "ant-col-xs-12" in x)
|
85
|
+
if not collection_items:
|
86
|
+
# Fallback to finding items by structure
|
87
|
+
collection_items = soup.find_all("div", class_=lambda x: x and "p-2" in x and "d-flex" in x and "flex-column" in x)
|
88
|
+
|
86
89
|
current_year = datetime.now().year
|
87
90
|
current_month = datetime.now().month
|
88
91
|
|
89
|
-
for
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
if
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
92
|
+
for item in collection_items:
|
93
|
+
# Extract bin type from h3 element
|
94
|
+
bin_type_elem = item.find("h3", class_="text-white")
|
95
|
+
# Extract date from div with specific classes
|
96
|
+
date_elem = item.find("div", class_="text-white fw-bold")
|
97
|
+
|
98
|
+
if bin_type_elem and date_elem:
|
99
|
+
bin_type = bin_type_elem.get_text().strip()
|
100
|
+
date_text = date_elem.get_text().strip()
|
101
|
+
|
102
|
+
try:
|
103
|
+
collection_date = datetime.strptime(date_text, "%A %d %B")
|
104
|
+
if (current_month > 10) and (collection_date.month < 3):
|
105
|
+
collection_date = collection_date.replace(year=(current_year + 1))
|
106
|
+
else:
|
107
|
+
collection_date = collection_date.replace(year=current_year)
|
108
|
+
|
109
|
+
dict_data = {
|
110
|
+
"type": bin_type,
|
111
|
+
"collectionDate": collection_date.strftime("%d/%m/%Y"),
|
112
|
+
}
|
113
|
+
data["bins"].append(dict_data)
|
114
|
+
except ValueError:
|
115
|
+
continue
|
105
116
|
|
106
117
|
except Exception as e:
|
107
118
|
# Here you can log the exception if needed
|