uk_bin_collection 0.152.4__py3-none-any.whl → 0.152.5__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 +1 -1
- uk_bin_collection/uk_bin_collection/councils/SouthRibbleCouncil.py +108 -54
- {uk_bin_collection-0.152.4.dist-info → uk_bin_collection-0.152.5.dist-info}/METADATA +1 -1
- {uk_bin_collection-0.152.4.dist-info → uk_bin_collection-0.152.5.dist-info}/RECORD +7 -7
- {uk_bin_collection-0.152.4.dist-info → uk_bin_collection-0.152.5.dist-info}/LICENSE +0 -0
- {uk_bin_collection-0.152.4.dist-info → uk_bin_collection-0.152.5.dist-info}/WHEEL +0 -0
- {uk_bin_collection-0.152.4.dist-info → uk_bin_collection-0.152.5.dist-info}/entry_points.txt +0 -0
@@ -2181,7 +2181,7 @@
|
|
2181
2181
|
},
|
2182
2182
|
"SouthRibbleCouncil": {
|
2183
2183
|
"uprn": "10013243496",
|
2184
|
-
"postcode": "
|
2184
|
+
"postcode": "PR266QW",
|
2185
2185
|
"url": "https://forms.chorleysouthribble.gov.uk/xfp/form/70",
|
2186
2186
|
"wiki_command_url_override": "https://forms.chorleysouthribble.gov.uk/xfp/form/70",
|
2187
2187
|
"wiki_name": "South Ribble",
|
@@ -1,76 +1,130 @@
|
|
1
|
-
import
|
1
|
+
from typing import Dict, List, Any, Optional
|
2
2
|
from bs4 import BeautifulSoup
|
3
|
-
|
4
|
-
|
3
|
+
from dateutil.relativedelta import relativedelta
|
4
|
+
import requests
|
5
|
+
import re
|
6
|
+
from datetime import datetime
|
7
|
+
from uk_bin_collection.uk_bin_collection.common import check_uprn, check_postcode, date_format
|
5
8
|
from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
|
9
|
+
from dateutil.parser import parse
|
6
10
|
|
7
11
|
|
8
|
-
# import the wonderful Beautiful Soup and the URL grabber
|
9
12
|
class CouncilClass(AbstractGetBinDataClass):
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
implementation.
|
14
|
-
"""
|
13
|
+
def get_data(self, url: str) -> str:
|
14
|
+
# This method is not used in the current implementation
|
15
|
+
return ""
|
15
16
|
|
16
|
-
def parse_data(self, page: str, **kwargs) ->
|
17
|
+
def parse_data(self, page: str, **kwargs: Any) -> Dict[str, List[Dict[str, str]]]:
|
18
|
+
postcode: Optional[str] = kwargs.get("postcode")
|
19
|
+
uprn: Optional[str] = kwargs.get("uprn")
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
check_uprn(user_uprn)
|
21
|
-
check_postcode(user_postcode)
|
22
|
-
bindata = {"bins": []}
|
21
|
+
if postcode is None or uprn is None:
|
22
|
+
raise ValueError("Both postcode and UPRN are required.")
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
check_postcode(postcode)
|
25
|
+
check_uprn(uprn)
|
26
26
|
|
27
27
|
session = requests.Session()
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
"__token": token,
|
34
|
-
"page": "196",
|
35
|
-
"locale": "en_GB",
|
36
|
-
"qc576c657112a8277ba6f954ebc0490c946168363_0_0": user_postcode,
|
37
|
-
"qc576c657112a8277ba6f954ebc0490c946168363_1_0": user_uprn,
|
38
|
-
"next": "Next",
|
28
|
+
headers = {
|
29
|
+
"User-Agent": (
|
30
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
|
31
|
+
"(KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"
|
32
|
+
)
|
39
33
|
}
|
34
|
+
session.headers.update(headers)
|
35
|
+
|
36
|
+
# Step 1: Load form and get token + field names
|
37
|
+
initial_url = "https://forms.chorleysouthribble.gov.uk/xfp/form/70"
|
38
|
+
get_resp = session.get(initial_url)
|
39
|
+
soup = BeautifulSoup(get_resp.text, "html.parser")
|
40
|
+
|
41
|
+
token = soup.find("input", {"name": "__token"})["value"]
|
42
|
+
page_id = soup.find("input", {"name": "page"})["value"]
|
43
|
+
postcode_field = soup.find("input", {"type": "text", "name": re.compile(".*_0_0")})["name"]
|
44
|
+
|
45
|
+
# Step 2: Submit postcode
|
46
|
+
post_resp = session.post(
|
47
|
+
initial_url,
|
48
|
+
data={
|
49
|
+
"__token": token,
|
50
|
+
"page": page_id,
|
51
|
+
"locale": "en_GB",
|
52
|
+
postcode_field: postcode,
|
53
|
+
"next": "Next",
|
54
|
+
},
|
55
|
+
)
|
40
56
|
|
41
|
-
|
57
|
+
soup = BeautifulSoup(post_resp.text, "html.parser")
|
58
|
+
token = soup.find("input", {"name": "__token"})["value"]
|
59
|
+
address_field_el = soup.find("select", {"name": re.compile(".*_1_0")})
|
60
|
+
if not address_field_el:
|
61
|
+
raise ValueError("Failed to find address dropdown after postcode submission.")
|
42
62
|
|
43
|
-
|
44
|
-
|
63
|
+
address_field = address_field_el["name"]
|
45
64
|
|
46
|
-
|
47
|
-
|
65
|
+
# Step 3: Submit UPRN and retrieve bin data
|
66
|
+
final_resp = session.post(
|
67
|
+
initial_url,
|
68
|
+
data={
|
69
|
+
"__token": token,
|
70
|
+
"page": page_id,
|
71
|
+
"locale": "en_GB",
|
72
|
+
postcode_field: postcode,
|
73
|
+
address_field: uprn,
|
74
|
+
"next": "Next",
|
75
|
+
},
|
76
|
+
)
|
48
77
|
|
49
|
-
|
78
|
+
soup = BeautifulSoup(final_resp.text, "html.parser")
|
79
|
+
table = soup.find("table", class_="data-table")
|
80
|
+
if not table:
|
81
|
+
raise ValueError("Could not find bin collection table.")
|
50
82
|
|
51
|
-
|
83
|
+
rows = table.find("tbody").find_all("tr")
|
52
84
|
data: Dict[str, List[Dict[str, str]]] = {"bins": []}
|
53
85
|
|
54
|
-
#
|
86
|
+
# Extract bin type mapping from JavaScript
|
87
|
+
bin_type_map = {}
|
88
|
+
scripts = soup.find_all("script", type="text/javascript")
|
89
|
+
for script in scripts:
|
90
|
+
if script.string and "const bintype = {" in script.string:
|
91
|
+
match = re.search(r'const bintype = \{([^}]+)\}', script.string, re.DOTALL)
|
92
|
+
if match:
|
93
|
+
bintype_content = match.group(1)
|
94
|
+
for line in bintype_content.split('\n'):
|
95
|
+
line = line.strip()
|
96
|
+
if '"' in line and ':' in line:
|
97
|
+
parts = line.split(':', 1)
|
98
|
+
if len(parts) == 2:
|
99
|
+
key = parts[0].strip().strip('"').strip("'")
|
100
|
+
value = parts[1].strip().rstrip(',').strip().strip('"').strip("'")
|
101
|
+
bin_type_map[key] = value
|
102
|
+
break
|
103
|
+
|
55
104
|
for row in rows:
|
56
105
|
cells = row.find_all("td")
|
57
|
-
|
58
|
-
|
59
|
-
bin_type =
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
106
|
+
if len(cells) >= 2:
|
107
|
+
bin_type_cell = cells[0]
|
108
|
+
bin_type = bin_type_cell.get_text(strip=True)
|
109
|
+
bin_type = bin_type_map.get(bin_type, bin_type)
|
110
|
+
|
111
|
+
date_text = cells[1].get_text(strip=True)
|
112
|
+
date_parts = date_text.split(", ")
|
113
|
+
date_str = date_parts[1] if len(date_parts) == 2 else date_text
|
114
|
+
|
115
|
+
try:
|
116
|
+
day, month, year = date_str.split('/')
|
117
|
+
year = int(year)
|
118
|
+
if year < 100:
|
119
|
+
year = 2000 + year
|
120
|
+
|
121
|
+
date_obj = datetime(year, int(month), int(day)).date()
|
122
|
+
|
123
|
+
data["bins"].append({
|
70
124
|
"type": bin_type,
|
71
|
-
"collectionDate":
|
72
|
-
}
|
73
|
-
|
74
|
-
|
75
|
-
|
125
|
+
"collectionDate": date_obj.strftime(date_format)
|
126
|
+
})
|
127
|
+
except Exception:
|
128
|
+
continue
|
129
|
+
|
76
130
|
return data
|
@@ -7,7 +7,7 @@ uk_bin_collection/tests/council_feature_input_parity.py,sha256=DO6Mk4ImYgM5ZCZ-c
|
|
7
7
|
uk_bin_collection/tests/features/environment.py,sha256=VQZjJdJI_kZn08M0j5cUgvKT4k3iTw8icJge1DGOkoA,127
|
8
8
|
uk_bin_collection/tests/features/validate_council_outputs.feature,sha256=SJK-Vc737hrf03tssxxbeg_JIvAH-ddB8f6gU1LTbuQ,251
|
9
9
|
uk_bin_collection/tests/generate_map_test_results.py,sha256=CKnGK2ZgiSXomRGkomX90DitgMP-X7wkHhyKORDcL2E,1144
|
10
|
-
uk_bin_collection/tests/input.json,sha256=
|
10
|
+
uk_bin_collection/tests/input.json,sha256=A0di9py05xaAUGIAuhzmYPoZYqPZFP9mubA3UgHCwpg,132589
|
11
11
|
uk_bin_collection/tests/output.schema,sha256=ZwKQBwYyTDEM4G2hJwfLUVM-5v1vKRvRK9W9SS1sd18,1086
|
12
12
|
uk_bin_collection/tests/step_defs/step_helpers/file_handler.py,sha256=Ygzi4V0S1MIHqbdstUlIqtRIwnynvhu4UtpweJ6-5N8,1474
|
13
13
|
uk_bin_collection/tests/step_defs/test_validate_council.py,sha256=VZ0a81sioJULD7syAYHjvK_-nT_Rd36tUyzPetSA0gk,3475
|
@@ -271,7 +271,7 @@ uk_bin_collection/uk_bin_collection/councils/SouthKestevenDistrictCouncil.py,sha
|
|
271
271
|
uk_bin_collection/uk_bin_collection/councils/SouthLanarkshireCouncil.py,sha256=fj-eZI0yrvQVCv8GvhcovZ3b9bV6Xv_ws3IunWjnv4U,3126
|
272
272
|
uk_bin_collection/uk_bin_collection/councils/SouthNorfolkCouncil.py,sha256=C2qIZjjbl9JnuukX9OH2RbfP0hSdp3uX76APGY33qKs,4622
|
273
273
|
uk_bin_collection/uk_bin_collection/councils/SouthOxfordshireCouncil.py,sha256=f9d2YDGv5hnN7Ul-u_I63h_BbpBU7CJFdgv-lOviRGc,4031
|
274
|
-
uk_bin_collection/uk_bin_collection/councils/SouthRibbleCouncil.py,sha256=
|
274
|
+
uk_bin_collection/uk_bin_collection/councils/SouthRibbleCouncil.py,sha256=juX7pg7dwqxzZUXHcGeFz8h7SNoUsZWUl8uiEOptE3k,5012
|
275
275
|
uk_bin_collection/uk_bin_collection/councils/SouthStaffordshireDistrictCouncil.py,sha256=ACQMHWyamnj1ag3gNF-8Jhp-DKUok1GhFdnzH4nCzwU,3201
|
276
276
|
uk_bin_collection/uk_bin_collection/councils/SouthTynesideCouncil.py,sha256=dxXGrJfg_fn2IPTBgq6Duwy0WY8GYLafMuisaCjOnbs,3426
|
277
277
|
uk_bin_collection/uk_bin_collection/councils/SouthamptonCityCouncil.py,sha256=exNoI-Vun_C5FowCYhZ_600MBUe_OPR7MdGZEMNLL0I,1542
|
@@ -346,8 +346,8 @@ uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bId
|
|
346
346
|
uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=QD4v4xpsEE0QheR_fGaNOIRMc2FatcUfKkkhAhseyVU,1159
|
347
347
|
uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
|
348
348
|
uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=YvmHfZqanwrJ8ToGch34x-L-7yPe31nB_x77_Mgl_vo,4545
|
349
|
-
uk_bin_collection-0.152.
|
350
|
-
uk_bin_collection-0.152.
|
351
|
-
uk_bin_collection-0.152.
|
352
|
-
uk_bin_collection-0.152.
|
353
|
-
uk_bin_collection-0.152.
|
349
|
+
uk_bin_collection-0.152.5.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
|
350
|
+
uk_bin_collection-0.152.5.dist-info/METADATA,sha256=_fyAz52D1iFURq-XyITh526l91Pc6YQGO4rn7xGotQ8,26688
|
351
|
+
uk_bin_collection-0.152.5.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
352
|
+
uk_bin_collection-0.152.5.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
|
353
|
+
uk_bin_collection-0.152.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{uk_bin_collection-0.152.4.dist-info → uk_bin_collection-0.152.5.dist-info}/entry_points.txt
RENAMED
File without changes
|