uk_bin_collection 0.74.0__py3-none-any.whl → 0.74.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.
@@ -207,8 +207,9 @@
207
207
  "wiki_note": "Both the UPRN and a one-line address are passed in the URL, which needs to be wrapped in double quotes. The one-line address is made up of the house number, street name and postcode.\nUse the form [here](https://online.cheshireeast.gov.uk/mycollectionday/) to find them, then take the first line and post code and replace all spaces with `%20`."
208
208
  },
209
209
  "CheshireWestAndChesterCouncil": {
210
- "house_number": "21",
211
- "postcode": "CW8 1DX",
210
+ "house_number": "Hill View House",
211
+ "postcode": "CH3 9ER",
212
+ "uprn": "100012346655",
212
213
  "skip_get_url": true,
213
214
  "url": "https://www.cheshirewestandchester.gov.uk/residents/waste-and-recycling/your-bin-collection/collection-day",
214
215
  "web_driver": "http://selenium:4444",
@@ -1,29 +1,23 @@
1
1
  import time
2
-
2
+ import logging
3
3
  from bs4 import BeautifulSoup
4
4
  from selenium.webdriver.common.by import By
5
5
  from selenium.webdriver.support import expected_conditions as EC
6
6
  from selenium.webdriver.support.ui import Select
7
7
  from selenium.webdriver.support.wait import WebDriverWait
8
-
9
8
  from uk_bin_collection.uk_bin_collection.common import *
10
9
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
11
10
 
11
+ # Set up logging
12
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
12
13
 
13
- # import the wonderful Beautiful Soup and the URL grabber
14
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
15
  def parse_data(self, page: str, **kwargs) -> dict:
22
16
  driver = None
23
17
  try:
24
18
  data = {"bins": []}
25
19
  collections = []
26
-
20
+ user_uprn = kwargs.get("uprn")
27
21
  user_paon = kwargs.get("paon")
28
22
  user_postcode = kwargs.get("postcode")
29
23
  web_driver = kwargs.get("web_driver")
@@ -33,77 +27,59 @@ class CouncilClass(AbstractGetBinDataClass):
33
27
 
34
28
  # Create Selenium webdriver
35
29
  driver = create_webdriver(web_driver, headless)
36
- driver.get(
37
- "https://www.cheshirewestandchester.gov.uk/residents/waste-and-recycling/your-bin-collection/collection-day"
38
- )
39
-
40
- time.sleep(5)
41
-
42
- cookie_close_button = WebDriverWait(driver, timeout=15).until(
43
- EC.presence_of_element_located((By.ID, "ccc-close"))
44
- )
45
- cookie_close_button.click()
46
-
47
- find_collection_button = WebDriverWait(driver, timeout=10).until(
48
- EC.presence_of_element_located(
49
- (By.LINK_TEXT, "Find your collection day")
50
- )
51
- )
52
- find_collection_button.click()
53
-
54
- banner_close_button = WebDriverWait(driver, timeout=30).until(
55
- EC.presence_of_element_located((By.ID, "close-cookie-message"))
56
- )
57
- banner_close_button.click()
58
-
59
- time.sleep(5)
60
-
61
- frame = driver.find_element(
62
- By.XPATH, "/html/body/div[4]/section/div/div[2]/div[2]/div/iframe"
63
- )
64
- driver.switch_to.frame(frame)
65
-
66
- # Wait for the postcode field to appear then populate it
67
- inputElement_postcode = WebDriverWait(driver, 30).until(
68
- EC.presence_of_element_located((By.NAME, "postcode_search"))
69
- )
70
- inputElement_postcode.send_keys(user_postcode)
71
-
72
- address_box_text = WebDriverWait(driver, 30).until(
73
- EC.presence_of_element_located((By.ID, "label_Choose_Address"))
74
- )
75
- address_box_text.click()
76
- time.sleep(2)
77
-
78
- address_selection_menu = Select(
79
- driver.find_element(By.ID, "Choose_Address")
80
- )
81
- for idx, addr_option in enumerate(address_selection_menu.options):
82
- option_name = addr_option.text[0 : len(user_paon)]
83
- if option_name == user_paon:
84
- selected_address = addr_option
85
- break
86
- address_selection_menu.select_by_visible_text(selected_address.text)
87
-
88
- WebDriverWait(driver, 30).until(
89
- EC.presence_of_element_located(
90
- (By.XPATH, '//*[@id="bin-schedule-content"]/div/h3')
91
- )
92
- )
30
+ if headless:
31
+ driver.set_window_size(1920, 1080)
32
+
33
+ driver.get("https://www.cheshirewestandchester.gov.uk/residents/waste-and-recycling/your-bin-collection/collection-day")
34
+ wait = WebDriverWait(driver, 60)
35
+
36
+ def click_element(by, value):
37
+ element = wait.until(EC.element_to_be_clickable((by, value)))
38
+ driver.execute_script("arguments[0].scrollIntoView();", element)
39
+ element.click()
40
+
41
+ logging.info("Accepting cookies")
42
+ click_element(By.ID, "ccc-close")
43
+
44
+ logging.info("Finding collection day")
45
+ click_element(By.LINK_TEXT, "Find your collection day")
93
46
 
47
+ logging.info("Switching to iframe")
48
+ iframe_presence = wait.until(EC.presence_of_element_located((By.ID, "fillform-frame-1")))
49
+ driver.switch_to.frame(iframe_presence)
50
+
51
+ logging.info("Entering postcode")
52
+ input_element_postcode = wait.until(EC.presence_of_element_located((By.XPATH, '//input[@id="postcode_search"]')))
53
+ input_element_postcode.send_keys(user_postcode)
54
+
55
+ pcsearch_btn = wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@id='postcode_search']")))
56
+ click_element(By.XPATH, "//input[@id='postcode_search']")
57
+
58
+ logging.info("Selecting address")
59
+ dropdown = wait.until(EC.element_to_be_clickable((By.ID, "Choose_Address")))
60
+ dropdown_options = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "lookup-option")))
61
+ drop_down_values = Select(dropdown)
62
+ option_element = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, f'option.lookup-option[value="{str(user_uprn)}"]')))
63
+ driver.execute_script("arguments[0].scrollIntoView();", option_element)
64
+ drop_down_values.select_by_value(str(user_uprn))
65
+
66
+ logging.info("Waiting for bin schedule")
67
+ wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'bin-schedule-content-bin-card')))
68
+
69
+ logging.info("Extracting bin collection data")
94
70
  soup = BeautifulSoup(driver.page_source, features="html.parser")
95
- soup.prettify()
71
+ bin_cards = soup.find_all("div", {"class": "bin-schedule-content-bin-card"})
72
+ collections = []
96
73
 
97
- # Get collections
98
- bin_cards = soup.find_all("div", {"class": "bin-schedule-content-info"})
99
74
  for card in bin_cards:
100
- bin_name = card.contents[0].text.strip() + " bin"
101
- bin_date = datetime.strptime(
102
- card.contents[1].text.split(":")[1].strip(), "%A, %d %B %Y"
103
- )
75
+ bin_info = card.find("div", {"class": "bin-schedule-content-info"})
76
+ bin_name = bin_info.find_all("p")[0].text.strip() + " bin"
77
+ bin_date_str = bin_info.find_all("p")[1].text.split(":")[1].strip()
78
+ bin_date = datetime.strptime(bin_date_str, "%A, %B %d, %Y")
104
79
  collections.append((bin_name, bin_date))
105
80
 
106
81
  ordered_data = sorted(collections, key=lambda x: x[1])
82
+
107
83
  for item in ordered_data:
108
84
  dict_data = {
109
85
  "type": item[0].capitalize(),
@@ -111,15 +87,14 @@ class CouncilClass(AbstractGetBinDataClass):
111
87
  }
112
88
  data["bins"].append(dict_data)
113
89
 
90
+ logging.info("Data extraction complete")
91
+ return data
92
+
114
93
  except Exception as e:
115
- # Here you can log the exception if needed
116
- print(f"An error occurred: {e}")
117
- # Optionally, re-raise the exception if you want it to propagate
94
+ logging.error(f"An error occurred: {e}")
118
95
  raise
119
96
 
120
97
  finally:
121
- # This block ensures that the driver is closed regardless of an exception
122
98
  if driver:
123
99
  driver.quit()
124
100
 
125
- return data
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uk_bin_collection
3
- Version: 0.74.0
3
+ Version: 0.74.1
4
4
  Summary: Python Lib to collect UK Bin Data
5
5
  Author: Robert Bradley
6
6
  Author-email: robbrad182@gmail.com
@@ -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=qS3JuQD__NomFiVvA0_xHL_kWRuvvRhLj_M30xUzcbg,3072
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=XIYnckDPBwBd7jTX2CN7Nv4mhUQsiJYOnYzvXVGfpdk,16246
5
- uk_bin_collection/tests/input.json,sha256=5PCw3swXDYnnjX_IFUJEcY4sQ18jn_iLem0xOvj364U,53429
5
+ uk_bin_collection/tests/input.json,sha256=lbJZCvGd0kvIvI-0dD7Q9clMnkk_zX2UWbp8j2Ji1ow,53474
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=Pg3Z7c3zrebx1w-yIZ9xTJ3E-okVndlNIAJL-F46HKU,2962
@@ -38,7 +38,7 @@ uk_bin_collection/uk_bin_collection/councils/CastlepointDistrictCouncil.py,sha25
38
38
  uk_bin_collection/uk_bin_collection/councils/CharnwoodBoroughCouncil.py,sha256=tXfzMetN6wxahuGGRp2mIyCCDSL4F2aG61HhUxw6COQ,2172
39
39
  uk_bin_collection/uk_bin_collection/councils/ChelmsfordCityCouncil.py,sha256=pEMQKNNTExYEqAyEn9ZMplwLVMly8R6tJeN5zNS_vpY,5074
40
40
  uk_bin_collection/uk_bin_collection/councils/CheshireEastCouncil.py,sha256=pyCxi_UZQkRnuHnwynLFHiux-__UIgAqhcpI3c2mkfA,1132
41
- uk_bin_collection/uk_bin_collection/councils/CheshireWestAndChesterCouncil.py,sha256=0uXeubLEoueEKDzryJ10A3F11aVz75FKFABLjxdocUU,4704
41
+ uk_bin_collection/uk_bin_collection/councils/CheshireWestAndChesterCouncil.py,sha256=GE5l66hB6qnhEbewKvioW9YOp8a90Xnnzu9_6Gl2n5A,4432
42
42
  uk_bin_collection/uk_bin_collection/councils/ChorleyCouncil.py,sha256=A6HSR7bapz0X03sMzu0BXIke9wlsCpWhIddDXkfVFZc,5183
43
43
  uk_bin_collection/uk_bin_collection/councils/ConwyCountyBorough.py,sha256=el75qv2QyfWZBU09tJLvD8vLQZ9pCg73u1NBFs6ybo8,1034
44
44
  uk_bin_collection/uk_bin_collection/councils/CrawleyBoroughCouncil.py,sha256=rZIRiXp0rOkc20M9DpgxuhbykACip7LNjpn6ytDsnwk,2361
@@ -164,8 +164,8 @@ uk_bin_collection/uk_bin_collection/councils/WyreCouncil.py,sha256=zDDa7n4K_zm5P
164
164
  uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bIdsvmoSzBjJAvTTi6yPfJa8xjJx1ys2w,1490
165
165
  uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=4s9ODGPAwPqwXc8SrTX5Wlfmizs3_58iXUtHc4Ir86o,1162
166
166
  uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=9qppF2oPkhmOoK8-ZkRIU1M6vhBh-yUCWAZEEd07iLk,5414
167
- uk_bin_collection-0.74.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
168
- uk_bin_collection-0.74.0.dist-info/METADATA,sha256=CUB3a19tRQY1WdptH6xh650CdkPtMRrYxD5sRhaCOEQ,12594
169
- uk_bin_collection-0.74.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
170
- uk_bin_collection-0.74.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
171
- uk_bin_collection-0.74.0.dist-info/RECORD,,
167
+ uk_bin_collection-0.74.1.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
168
+ uk_bin_collection-0.74.1.dist-info/METADATA,sha256=mZbP454WX8TthYdJSeCodIRKf62cZaU_CWjOhVTl6cI,12594
169
+ uk_bin_collection-0.74.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
170
+ uk_bin_collection-0.74.1.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
171
+ uk_bin_collection-0.74.1.dist-info/RECORD,,