uk_bin_collection 0.91.1__py3-none-any.whl → 0.92.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 +13 -3
- uk_bin_collection/uk_bin_collection/councils/ColchesterCityCouncil.py +103 -0
- uk_bin_collection/uk_bin_collection/councils/WindsorAndMaidenheadCouncil.py +23 -108
- {uk_bin_collection-0.91.1.dist-info → uk_bin_collection-0.92.0.dist-info}/METADATA +1 -1
- {uk_bin_collection-0.91.1.dist-info → uk_bin_collection-0.92.0.dist-info}/RECORD +8 -7
- {uk_bin_collection-0.91.1.dist-info → uk_bin_collection-0.92.0.dist-info}/LICENSE +0 -0
- {uk_bin_collection-0.91.1.dist-info → uk_bin_collection-0.92.0.dist-info}/WHEEL +0 -0
- {uk_bin_collection-0.91.1.dist-info → uk_bin_collection-0.92.0.dist-info}/entry_points.txt +0 -0
@@ -247,6 +247,16 @@
|
|
247
247
|
"wiki_name": "Chorley Council",
|
248
248
|
"wiki_note": "Chorley needs to be passed both a Postcode & UPRN in the format of UPRNXXXXXX to work. Find this on [FindMyAddress](https://www.findmyaddress.co.uk/search)"
|
249
249
|
},
|
250
|
+
"ColchesterCityCouncil": {
|
251
|
+
"house_number": "29",
|
252
|
+
"paon": "29",
|
253
|
+
"postcode": "CO2 8UN",
|
254
|
+
"skip_get_url": false,
|
255
|
+
"url": "https://www.colchester.gov.uk/your-recycling-calendar",
|
256
|
+
"web_driver": "http://selenium:4444",
|
257
|
+
"wiki_name": "Colchester City Council",
|
258
|
+
"wiki_note": "Pass the house name/number in the house number parameter, wrapped in double quotes"
|
259
|
+
},
|
250
260
|
"ConwyCountyBorough": {
|
251
261
|
"postcode": "LL30 2DF",
|
252
262
|
"uprn": "100100429249",
|
@@ -1220,10 +1230,10 @@
|
|
1220
1230
|
"wiki_name": "Wiltshire Council"
|
1221
1231
|
},
|
1222
1232
|
"WindsorAndMaidenheadCouncil": {
|
1223
|
-
"
|
1224
|
-
"
|
1233
|
+
"web_driver": "http://selenium:4444",
|
1234
|
+
"uprn": "100080371082",
|
1225
1235
|
"skip_get_url": true,
|
1226
|
-
"url": "https://
|
1236
|
+
"url": "https://forms.rbwm.gov.uk/bincollections?uprn=",
|
1227
1237
|
"wiki_name": "Windsor and Maidenhead Council"
|
1228
1238
|
},
|
1229
1239
|
"WokingBoroughCouncil": {
|
@@ -0,0 +1,103 @@
|
|
1
|
+
from bs4 import BeautifulSoup
|
2
|
+
from selenium.webdriver.common.by import By
|
3
|
+
from selenium.webdriver.support import expected_conditions as EC
|
4
|
+
from selenium.webdriver.support.wait import WebDriverWait
|
5
|
+
|
6
|
+
from uk_bin_collection.uk_bin_collection.common import *
|
7
|
+
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
|
8
|
+
|
9
|
+
|
10
|
+
# import the wonderful Beautiful Soup and the URL grabber
|
11
|
+
class CouncilClass(AbstractGetBinDataClass):
|
12
|
+
"""
|
13
|
+
Concrete classes have to implement all abstract operations of the
|
14
|
+
base class. They can also override some operations with a default
|
15
|
+
implementation.
|
16
|
+
"""
|
17
|
+
|
18
|
+
def parse_data(self, page: str, **kwargs) -> dict:
|
19
|
+
driver = None
|
20
|
+
try:
|
21
|
+
data = {"bins": []}
|
22
|
+
user_paon = kwargs.get("paon")
|
23
|
+
user_postcode = kwargs.get("postcode")
|
24
|
+
web_driver = kwargs.get("web_driver")
|
25
|
+
headless = kwargs.get("headless")
|
26
|
+
check_paon(user_paon)
|
27
|
+
check_postcode(user_postcode)
|
28
|
+
|
29
|
+
# Create Selenium webdriver
|
30
|
+
driver = create_webdriver(web_driver, headless, None, __name__)
|
31
|
+
driver.get(
|
32
|
+
"https://www.colchester.gov.uk/your-recycling-calendar/?start=true"
|
33
|
+
)
|
34
|
+
|
35
|
+
accept_button = WebDriverWait(driver, timeout=30).until(
|
36
|
+
EC.element_to_be_clickable((By.ID, "ccc-notify-accept"))
|
37
|
+
)
|
38
|
+
accept_button.click()
|
39
|
+
|
40
|
+
# Wait for the postcode field to appear then populate it
|
41
|
+
inputElement_postcode = WebDriverWait(driver, 10).until(
|
42
|
+
EC.presence_of_element_located((By.CLASS_NAME, "input-text"))
|
43
|
+
)
|
44
|
+
inputElement_postcode.send_keys(user_postcode)
|
45
|
+
|
46
|
+
# Click search button
|
47
|
+
findAddress = WebDriverWait(driver, 10).until(
|
48
|
+
EC.presence_of_element_located((By.CLASS_NAME, "button-small"))
|
49
|
+
)
|
50
|
+
findAddress.click()
|
51
|
+
|
52
|
+
# Wait for the 'Select address' dropdown to appear and select option matching the house name/number
|
53
|
+
WebDriverWait(driver, 10).until(
|
54
|
+
EC.element_to_be_clickable(
|
55
|
+
(
|
56
|
+
By.XPATH,
|
57
|
+
"//select[@class='input-select']//option[contains(., '"
|
58
|
+
+ user_paon
|
59
|
+
+ "')]",
|
60
|
+
)
|
61
|
+
)
|
62
|
+
).click()
|
63
|
+
|
64
|
+
WebDriverWait(driver, 10).until(
|
65
|
+
EC.presence_of_element_located((By.CLASS_NAME, "button-small"))
|
66
|
+
).click()
|
67
|
+
|
68
|
+
# Wait for the collections table to appear
|
69
|
+
WebDriverWait(driver, 10).until(
|
70
|
+
EC.presence_of_element_located((By.CLASS_NAME, "recycling-calendar"))
|
71
|
+
)
|
72
|
+
|
73
|
+
soup = BeautifulSoup(driver.page_source, features="html.parser")
|
74
|
+
|
75
|
+
recyclingcalendar = soup.find("div", {"class": "recycling-calendar"})
|
76
|
+
|
77
|
+
rows = recyclingcalendar.find_all(
|
78
|
+
"div", {"class": "recycling-calendar-row"}
|
79
|
+
)
|
80
|
+
|
81
|
+
for row in rows:
|
82
|
+
collectiondate = datetime.strptime(
|
83
|
+
row.find("strong").get_text(),
|
84
|
+
"%d %B %Y",
|
85
|
+
)
|
86
|
+
listobj = row.find("ul")
|
87
|
+
for li in listobj.find_all("li"):
|
88
|
+
dict_data = {
|
89
|
+
"type": li.get_text().strip(),
|
90
|
+
"collectionDate": collectiondate.strftime("%d/%m/%Y"),
|
91
|
+
}
|
92
|
+
data["bins"].append(dict_data)
|
93
|
+
|
94
|
+
except Exception as e:
|
95
|
+
# Here you can log the exception if needed
|
96
|
+
print(f"An error occurred: {e}")
|
97
|
+
# Optionally, re-raise the exception if you want it to propagate
|
98
|
+
raise
|
99
|
+
finally:
|
100
|
+
# This block ensures that the driver is closed regardless of an exception
|
101
|
+
if driver:
|
102
|
+
driver.quit()
|
103
|
+
return data
|
@@ -1,7 +1,6 @@
|
|
1
1
|
from datetime import datetime
|
2
|
-
from urllib.parse import urlparse
|
3
2
|
|
4
|
-
import
|
3
|
+
import dateutil.parser
|
5
4
|
from bs4 import BeautifulSoup
|
6
5
|
|
7
6
|
from uk_bin_collection.uk_bin_collection.common import *
|
@@ -17,119 +16,35 @@ class CouncilClass(AbstractGetBinDataClass):
|
|
17
16
|
"""
|
18
17
|
|
19
18
|
def parse_data(self, page: str, **kwargs) -> dict:
|
20
|
-
root_url = "https://my.rbwm.gov.uk"
|
21
|
-
href_url = ""
|
22
|
-
api_url = "https://my.rbwm.gov.uk/block_refresh/block/47/node/136968?"
|
23
|
-
user_postcode = kwargs.get("postcode")
|
24
|
-
user_paon = kwargs.get("paon")
|
25
|
-
|
26
19
|
data = {"bins": []}
|
20
|
+
user_uprn = kwargs.get("uprn")
|
21
|
+
web_driver = kwargs.get("web_driver")
|
22
|
+
headless = kwargs.get("headless")
|
23
|
+
check_uprn(user_uprn)
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
# Form start
|
31
|
-
headers = {
|
32
|
-
"authority": "my.rbwm.gov.uk",
|
33
|
-
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
|
34
|
-
"accept-language": "en-GB,en;q=0.8",
|
35
|
-
"cache-control": "max-age=0",
|
36
|
-
"referer": "https://my.rbwm.gov.uk/special/your-collection-dates?uprn=100080371082&subdate=2022-08-19&addr=11%20Douglas%20Lane%20Wraysbury%20Staines%20TW19%205NF",
|
37
|
-
"sec-fetch-dest": "document",
|
38
|
-
"sec-fetch-mode": "navigate",
|
39
|
-
"sec-fetch-site": "same-origin",
|
40
|
-
"sec-fetch-user": "?1",
|
41
|
-
"sec-gpc": "1",
|
42
|
-
"upgrade-insecure-requests": "1",
|
43
|
-
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36",
|
44
|
-
}
|
45
|
-
s.get(
|
46
|
-
"https://my.rbwm.gov.uk/special/find-your-collection-dates", headers=headers
|
47
|
-
)
|
25
|
+
root_url = "https://forms.rbwm.gov.uk/bincollections?uprn="
|
26
|
+
api_url = root_url + user_uprn
|
48
27
|
|
49
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
|
53
|
-
"accept-language": "en-GB,en;q=0.8",
|
54
|
-
"cache-control": "max-age=0",
|
55
|
-
"origin": "https://my.rbwm.gov.uk",
|
56
|
-
"referer": "https://my.rbwm.gov.uk/special/find-your-collection-dates",
|
57
|
-
"sec-fetch-dest": "document",
|
58
|
-
"sec-fetch-mode": "navigate",
|
59
|
-
"sec-fetch-site": "same-origin",
|
60
|
-
"sec-fetch-user": "?1",
|
61
|
-
"sec-gpc": "1",
|
62
|
-
"upgrade-insecure-requests": "1",
|
63
|
-
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36",
|
64
|
-
}
|
65
|
-
request_data = {
|
66
|
-
"atTxtStreet": user_postcode,
|
67
|
-
"nodeid": "x",
|
68
|
-
"formname": "x",
|
69
|
-
"pg": "20",
|
70
|
-
"start": "1",
|
71
|
-
"selectaddress": "Select this address",
|
72
|
-
"selectheading": "The following addresses match the address you entered - choose your address",
|
73
|
-
"arg": "",
|
74
|
-
}
|
75
|
-
response = s.post(
|
76
|
-
"https://my.rbwm.gov.uk/special/address-selector-collection-dates",
|
77
|
-
headers=headers,
|
78
|
-
data=request_data,
|
79
|
-
)
|
28
|
+
# Create Selenium webdriver
|
29
|
+
driver = create_webdriver(web_driver, headless, None, __name__)
|
30
|
+
driver.get(api_url)
|
80
31
|
|
81
|
-
soup = BeautifulSoup(
|
32
|
+
soup = BeautifulSoup(driver.page_source, features="html.parser")
|
82
33
|
soup.prettify()
|
83
34
|
|
84
|
-
|
85
|
-
|
86
|
-
table_rows = table.find_all("tr")
|
87
|
-
for tr in table_rows:
|
88
|
-
td = tr.find_all("td")
|
89
|
-
# row = [i.text for i in td]
|
90
|
-
for item in td:
|
91
|
-
if user_paon in item.text and user_postcode in item.text:
|
92
|
-
href_url = td[1].find("a").get("href")
|
93
|
-
continue
|
94
|
-
|
95
|
-
# Getting to bin data
|
96
|
-
headers = {
|
97
|
-
"authority": "my.rbwm.gov.uk",
|
98
|
-
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
|
99
|
-
"accept-language": "en-GB,en;q=0.8",
|
100
|
-
"referer": "https://my.rbwm.gov.uk/special/address-selector-collection-dates",
|
101
|
-
"sec-fetch-dest": "document",
|
102
|
-
"sec-fetch-mode": "navigate",
|
103
|
-
"sec-fetch-site": "same-origin",
|
104
|
-
"sec-fetch-user": "?1",
|
105
|
-
"sec-gpc": "1",
|
106
|
-
"upgrade-insecure-requests": "1",
|
107
|
-
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36",
|
108
|
-
}
|
109
|
-
params = {}
|
110
|
-
parsed_params = urlparse(href_url).query.split("&")
|
111
|
-
for item in parsed_params:
|
112
|
-
values = item.split("=")
|
113
|
-
params.update({values[0]: values[1]})
|
35
|
+
# Get collections div
|
36
|
+
next_collection_div = soup.find("div", {"class": "widget-bin-collections"})
|
114
37
|
|
115
|
-
|
116
|
-
|
117
|
-
api_url + href_url.split("?")[1], params=params, headers=headers
|
118
|
-
)
|
119
|
-
|
120
|
-
soup = BeautifulSoup(response.content, features="html.parser")
|
121
|
-
soup.prettify()
|
122
|
-
|
123
|
-
table_rows = soup.find_all("tr")
|
124
|
-
for tr in table_rows:
|
38
|
+
for tbody in next_collection_div.find_all("tbody"):
|
39
|
+
for tr in tbody.find_all("tr"):
|
125
40
|
td = tr.find_all("td")
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
41
|
+
next_collection_type = td[0].get_text()
|
42
|
+
next_collection_date = dateutil.parser.parse(td[1].get_text())
|
43
|
+
print(next_collection_date)
|
44
|
+
dict_data = {
|
45
|
+
"type": next_collection_type,
|
46
|
+
"collectionDate": next_collection_date.strftime("%d/%m/%Y"),
|
47
|
+
}
|
48
|
+
data["bins"].append(dict_data)
|
134
49
|
|
135
50
|
return data
|
@@ -2,7 +2,7 @@ uk_bin_collection/README.rst,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
|
|
2
2
|
uk_bin_collection/tests/council_feature_input_parity.py,sha256=DO6Mk4ImYgM5ZCZ-cutwz5RoYYWZRLYx2tr6zIs_9Rc,3843
|
3
3
|
uk_bin_collection/tests/features/environment.py,sha256=VQZjJdJI_kZn08M0j5cUgvKT4k3iTw8icJge1DGOkoA,127
|
4
4
|
uk_bin_collection/tests/features/validate_council_outputs.feature,sha256=SJK-Vc737hrf03tssxxbeg_JIvAH-ddB8f6gU1LTbuQ,251
|
5
|
-
uk_bin_collection/tests/input.json,sha256=
|
5
|
+
uk_bin_collection/tests/input.json,sha256=Q3l16fwk4hmvIG6tY6SgP2aZCn-_ghBbMnGjuZCtS_c,61684
|
6
6
|
uk_bin_collection/tests/output.schema,sha256=ZwKQBwYyTDEM4G2hJwfLUVM-5v1vKRvRK9W9SS1sd18,1086
|
7
7
|
uk_bin_collection/tests/step_defs/step_helpers/file_handler.py,sha256=Ygzi4V0S1MIHqbdstUlIqtRIwnynvhu4UtpweJ6-5N8,1474
|
8
8
|
uk_bin_collection/tests/step_defs/test_validate_council.py,sha256=LrOSt_loA1Mw3vTqaO2LpaDMu7rYJy6k5Kr-EOBln7s,3424
|
@@ -45,6 +45,7 @@ uk_bin_collection/uk_bin_collection/councils/CheshireEastCouncil.py,sha256=VZQsi
|
|
45
45
|
uk_bin_collection/uk_bin_collection/councils/CheshireWestAndChesterCouncil.py,sha256=M58kIHCAZu1K5qBp6_M4sw8nMvHz38YkoxY_sNuhvOI,4780
|
46
46
|
uk_bin_collection/uk_bin_collection/councils/ChichesterDistrictCouncil.py,sha256=HxrLcJves7ZsE8FbooymeecTUmScY4R7Oi71vwCePPo,4118
|
47
47
|
uk_bin_collection/uk_bin_collection/councils/ChorleyCouncil.py,sha256=M7HjuUaFq8aSnOf_9m1QS4MmPPMmPhF3mLHSrfDPtV0,5194
|
48
|
+
uk_bin_collection/uk_bin_collection/councils/ColchesterCityCouncil.py,sha256=Mny-q2rQkWe2Tj1gINwEM1L4AkqQl1EDMAaKY0-deD4,3968
|
48
49
|
uk_bin_collection/uk_bin_collection/councils/ConwyCountyBorough.py,sha256=el75qv2QyfWZBU09tJLvD8vLQZ9pCg73u1NBFs6ybo8,1034
|
49
50
|
uk_bin_collection/uk_bin_collection/councils/CornwallCouncil.py,sha256=W7_wWHLbE0cyE90GkNaZHmR7Lbd2Aq48A1hKMUNO-vg,2806
|
50
51
|
uk_bin_collection/uk_bin_collection/councils/CrawleyBoroughCouncil.py,sha256=_BEKZAjlS5Ad5DjyxqAEFSLn8F-KYox0zmn4BXaAD6A,2367
|
@@ -183,7 +184,7 @@ uk_bin_collection/uk_bin_collection/councils/WestNorthamptonshireCouncil.py,sha2
|
|
183
184
|
uk_bin_collection/uk_bin_collection/councils/WestSuffolkCouncil.py,sha256=HMFWxM7VMhBuC7iubNGbZYEoCVWi--gRHDJMVdPPFOM,2633
|
184
185
|
uk_bin_collection/uk_bin_collection/councils/WiganBoroughCouncil.py,sha256=3gqFA4-BVx_In6QOu3KUNqPN4Fkn9iMlZTeopMK9p6A,3746
|
185
186
|
uk_bin_collection/uk_bin_collection/councils/WiltshireCouncil.py,sha256=it2Oh5Kmq3lD30gAZgk2bzZPNCtJcFHyQO1NgOQtfvU,5653
|
186
|
-
uk_bin_collection/uk_bin_collection/councils/WindsorAndMaidenheadCouncil.py,sha256=
|
187
|
+
uk_bin_collection/uk_bin_collection/councils/WindsorAndMaidenheadCouncil.py,sha256=7Qhznj95ktAQjpWm5C8pbD5UcvfXm7Mwb7_DQxwjGSM,1777
|
187
188
|
uk_bin_collection/uk_bin_collection/councils/WokingBoroughCouncil.py,sha256=37igH9g0xe4XIhRhcJ-ZJBU8MxTp5yzgpadWbdE33Yg,5205
|
188
189
|
uk_bin_collection/uk_bin_collection/councils/WychavonDistrictCouncil.py,sha256=YuZdzEW0CZLwusm1VQcGRIKXAab_UDFLaCnN60itt_E,5776
|
189
190
|
uk_bin_collection/uk_bin_collection/councils/WyreCouncil.py,sha256=zDDa7n4K_zm5PgDL08A26gD9yOOsOhuexI3x2seaBF4,3511
|
@@ -191,8 +192,8 @@ uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bId
|
|
191
192
|
uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=4s9ODGPAwPqwXc8SrTX5Wlfmizs3_58iXUtHc4Ir86o,1162
|
192
193
|
uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
|
193
194
|
uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=YvmHfZqanwrJ8ToGch34x-L-7yPe31nB_x77_Mgl_vo,4545
|
194
|
-
uk_bin_collection-0.
|
195
|
-
uk_bin_collection-0.
|
196
|
-
uk_bin_collection-0.
|
197
|
-
uk_bin_collection-0.
|
198
|
-
uk_bin_collection-0.
|
195
|
+
uk_bin_collection-0.92.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
|
196
|
+
uk_bin_collection-0.92.0.dist-info/METADATA,sha256=I8N4Q2TwfwCtMksjuMddP2UDKku-BH3LrMasukfm4Z0,16642
|
197
|
+
uk_bin_collection-0.92.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
198
|
+
uk_bin_collection-0.92.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
|
199
|
+
uk_bin_collection-0.92.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|