uk_bin_collection 0.159.0__py3-none-any.whl → 0.159.1__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.
@@ -1,10 +1,40 @@
1
- import requests
1
+ from datetime import datetime
2
+
2
3
  from bs4 import BeautifulSoup
3
4
 
4
- from uk_bin_collection.uk_bin_collection.common import *
5
+ from uk_bin_collection.uk_bin_collection.common import check_uprn
5
6
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
6
7
 
7
8
 
9
+ def extract_collection_date(section, section_id):
10
+ """
11
+ Helper function to safely extract title and collection date from a section.
12
+ Returns tuple (title, collection_date) or (None, None) if not found.
13
+ """
14
+ if not section:
15
+ return None, None
16
+
17
+ title_element = section.find("p", {"id": section_id})
18
+ if not title_element:
19
+ return None, None
20
+
21
+ title = title_element.get_text(strip=True)
22
+
23
+ next_collection_text = section.find(
24
+ string=lambda t: isinstance(t, str) and "next collection" in t.lower()
25
+ )
26
+
27
+ if not next_collection_text:
28
+ return title, None
29
+
30
+ text = str(next_collection_text).strip()
31
+ _, sep, rhs = text.partition(":")
32
+ if not sep:
33
+ return title, None
34
+ collection_date = rhs.strip()
35
+ return title, collection_date
36
+
37
+
8
38
  # import the wonderful Beautiful Soup and the URL grabber
9
39
  class CouncilClass(AbstractGetBinDataClass):
10
40
  """
@@ -22,141 +52,39 @@ class CouncilClass(AbstractGetBinDataClass):
22
52
  baseurl = "https://services.southwark.gov.uk/bins/lookup/"
23
53
  url = baseurl + user_uprn
24
54
 
25
- headers = {
26
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"
27
- }
28
-
29
- # Make the web request
30
- response = requests.get(url, headers=headers).text
55
+ # Make the web request using the common helper (standard UA, timeout, logging)
56
+ response = self.get_data(url).text
31
57
 
32
58
  soup = BeautifulSoup(response, "html.parser")
33
-
34
- # Extract recycling collection information
35
- recycling_section = soup.find(
36
- "div", {"aria-labelledby": "recyclingCollectionTitle"}
37
- )
38
- if recycling_section:
39
- recycling_title = recycling_section.find(
40
- "p", {"id": "recyclingCollectionTitle"}
41
- ).text
42
- recycling_next_collection = (
43
- recycling_section.find(text=lambda text: "Next collection" in text)
44
- .strip()
45
- .split(": ")[1]
46
- )
47
-
48
- dict_data = {
49
- "type": recycling_title,
50
- "collectionDate": datetime.strptime(
51
- recycling_next_collection, "%a, %d %B %Y"
52
- ).strftime("%d/%m/%Y"),
53
- }
54
- data["bins"].append(dict_data)
55
-
56
- # Extract refuse collection information
57
- refuse_section = soup.find("div", {"aria-labelledby": "refuseCollectionTitle"})
58
- if refuse_section:
59
- refuse_title = refuse_section.find(
60
- "p", {"id": "refuseCollectionTitle"}
61
- ).text
62
- refuse_next_collection = (
63
- refuse_section.find(text=lambda text: "Next collection" in text)
64
- .strip()
65
- .split(": ")[1]
66
- )
67
-
68
- dict_data = {
69
- "type": refuse_title,
70
- "collectionDate": datetime.strptime(
71
- refuse_next_collection, "%a, %d %B %Y"
72
- ).strftime("%d/%m/%Y"),
73
- }
74
- data["bins"].append(dict_data)
75
-
76
- # Extract food waste collection information
77
- food_section = soup.find(
78
- "div", {"aria-labelledby": "domesticFoodCollectionTitle"}
79
- )
80
- if food_section:
81
- food_title = food_section.find(
82
- "p", {"id": "domesticFoodCollectionTitle"}
83
- ).text
84
- food_next_collection = (
85
- food_section.find(text=lambda text: "Next collection" in text)
86
- .strip()
87
- .split(": ")[1]
88
- )
89
-
90
- dict_data = {
91
- "type": food_title,
92
- "collectionDate": datetime.strptime(
93
- food_next_collection, "%a, %d %B %Y"
94
- ).strftime("%d/%m/%Y"),
95
- }
96
- data["bins"].append(dict_data)
97
-
98
- # Extract communal food waste collection information
99
- comfood_section = soup.find(
100
- "div", {"aria-labelledby": "communalFoodCollectionTitle"}
101
- )
102
- if comfood_section:
103
- comfood_title = comfood_section.find(
104
- "p", {"id": "communalFoodCollectionTitle"}
105
- ).text
106
- comfood_next_collection = (
107
- comfood_section.find(text=lambda text: "Next collection" in text)
108
- .strip()
109
- .split(": ")[1]
110
- )
111
-
112
- dict_data = {
113
- "type": comfood_title,
114
- "collectionDate": datetime.strptime(
115
- comfood_next_collection, "%a, %d %B %Y"
116
- ).strftime("%d/%m/%Y"),
117
- }
118
- data["bins"].append(dict_data)
119
-
120
- comrec_section = soup.find(
121
- "div", {"aria-labelledby": "recyclingCommunalCollectionTitle"}
59
+ # Extract collection information for all bin types
60
+ section_ids = (
61
+ "recyclingCollectionTitle",
62
+ "refuseCollectionTitle",
63
+ "domesticFoodCollectionTitle",
64
+ "communalFoodCollectionTitle",
65
+ "recyclingCommunalCollectionTitle",
66
+ "refuseCommunalCollectionTitle",
122
67
  )
123
- if comrec_section:
124
- comrec_title = comrec_section.find(
125
- "p", {"id": "recyclingCommunalCollectionTitle"}
126
- ).text
127
- comrec_next_collection = (
128
- comrec_section.find(text=lambda text: "Next collection" in text)
129
- .strip()
130
- .split(": ")[1]
131
- )
132
68
 
133
- dict_data = {
134
- "type": comrec_title,
135
- "collectionDate": datetime.strptime(
136
- comrec_next_collection, "%a, %d %B %Y"
137
- ).strftime("%d/%m/%Y"),
138
- }
139
- data["bins"].append(dict_data)
140
-
141
- comref_section = soup.find(
142
- "div", {"aria-labelledby": "refuseCommunalCollectionTitle"}
143
- )
144
- if comref_section:
145
- comref_title = comref_section.find(
146
- "p", {"id": "refuseCommunalCollectionTitle"}
147
- ).text
148
- comref_next_collection = (
149
- comref_section.find(text=lambda text: "Next collection" in text)
150
- .strip()
151
- .split(": ")[1]
69
+ for section_id in section_ids:
70
+ section = soup.find("div", {"aria-labelledby": section_id})
71
+ if not section:
72
+ continue
73
+
74
+ title, next_collection = extract_collection_date(section, section_id)
75
+ if not (title and next_collection):
76
+ continue
77
+
78
+ try:
79
+ parsed = datetime.strptime(next_collection, "%a, %d %B %Y")
80
+ except ValueError:
81
+ continue
82
+
83
+ data["bins"].append(
84
+ {
85
+ "type": title,
86
+ "collectionDate": parsed.strftime("%d/%m/%Y"),
87
+ }
152
88
  )
153
89
 
154
- dict_data = {
155
- "type": comref_title,
156
- "collectionDate": datetime.strptime(
157
- comref_next_collection, "%a, %d %B %Y"
158
- ).strftime("%d/%m/%Y"),
159
- }
160
- data["bins"].append(dict_data)
161
-
162
- return data
90
+ return data
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uk_bin_collection
3
- Version: 0.159.0
3
+ Version: 0.159.1
4
4
  Summary: Python Lib to collect UK Bin Data
5
5
  Author: Robert Bradley
6
6
  Author-email: robbrad182@gmail.com
@@ -276,7 +276,7 @@ uk_bin_collection/uk_bin_collection/councils/SouthRibbleCouncil.py,sha256=juX7pg
276
276
  uk_bin_collection/uk_bin_collection/councils/SouthStaffordshireDistrictCouncil.py,sha256=ACQMHWyamnj1ag3gNF-8Jhp-DKUok1GhFdnzH4nCzwU,3201
277
277
  uk_bin_collection/uk_bin_collection/councils/SouthTynesideCouncil.py,sha256=dxXGrJfg_fn2IPTBgq6Duwy0WY8GYLafMuisaCjOnbs,3426
278
278
  uk_bin_collection/uk_bin_collection/councils/SouthamptonCityCouncil.py,sha256=exNoI-Vun_C5FowCYhZ_600MBUe_OPR7MdGZEMNLL0I,1542
279
- uk_bin_collection/uk_bin_collection/councils/SouthwarkCouncil.py,sha256=xgxOKyy-jFKOl_5zYaJovr0ijEMN20ssOSB7I7Jtfhw,5685
279
+ uk_bin_collection/uk_bin_collection/councils/SouthwarkCouncil.py,sha256=AR4qv12oHkMRmNb62pk0IByeOQ7ePh-FnxrK4TWqM0E,2772
280
280
  uk_bin_collection/uk_bin_collection/councils/SpelthorneBoroughCouncil.py,sha256=iamG0wxIyYprttJPVc0jdbOoHavc1AmRpMhyc02MUrE,5703
281
281
  uk_bin_collection/uk_bin_collection/councils/StAlbansCityAndDistrictCouncil.py,sha256=mPZz6Za6kTSkrfHnj0OfwtnpRYR1dKvxbuFEKnWsiL8,1451
282
282
  uk_bin_collection/uk_bin_collection/councils/StHelensBC.py,sha256=X9dvnQTNn7QUO8gv1A587e1aDI92TWN4iNLATTn3H3w,4777
@@ -350,8 +350,8 @@ uk_bin_collection/uk_bin_collection/councils/tests/test_south_kesteven_district_
350
350
  uk_bin_collection/uk_bin_collection/councils/tests/test_south_kesteven_integration.py,sha256=ax_kevIIB1BpDTVjEnoiZnDk0srkc1Vw7B2i5XLLqiE,6647
351
351
  uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
352
352
  uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=Qb76X46V0UMZJwO8zMNPvnVY7jNa-bmTlrirDi1tuJA,4553
353
- uk_bin_collection-0.159.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
354
- uk_bin_collection-0.159.0.dist-info/METADATA,sha256=P0cd-TTHh50QbuBkadrZ-QSykQIQLQnVTCknm-vJu0k,26769
355
- uk_bin_collection-0.159.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
356
- uk_bin_collection-0.159.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
357
- uk_bin_collection-0.159.0.dist-info/RECORD,,
353
+ uk_bin_collection-0.159.1.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
354
+ uk_bin_collection-0.159.1.dist-info/METADATA,sha256=ea00NlOlSDzueVpUIYwsoIOyerpqMHlcr8fz2MQIvkw,26769
355
+ uk_bin_collection-0.159.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
356
+ uk_bin_collection-0.159.1.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
357
+ uk_bin_collection-0.159.1.dist-info/RECORD,,