uk_bin_collection 0.98.4__py3-none-any.whl → 0.99.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.
@@ -620,6 +620,14 @@
620
620
  "wiki_name": "Lichfield District Council",
621
621
  "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
622
622
  },
623
+ "LincolnCouncil": {
624
+ "url": "https://lincoln.gov.uk",
625
+ "wiki_command_url_override": "https://lincoln.gov.uk",
626
+ "uprn": "000235024846",
627
+ "postcode": "LN5 7SH",
628
+ "wiki_name": "Tunbridge Wells Council",
629
+ "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
630
+ },
623
631
  "LisburnCastlereaghCityCouncil": {
624
632
  "house_number": "97",
625
633
  "postcode": "BT28 1JN",
@@ -871,6 +879,13 @@
871
879
  "wiki_name": "Oldham Council",
872
880
  "wiki_note": "Replace UPRN in URL with your own UPRN."
873
881
  },
882
+ "PerthAndKinrossCouncil": {
883
+ "url": "https://www.pkc.gov.uk",
884
+ "wiki_command_url_override": "https://www.pkc.gov.uk",
885
+ "uprn": "124032322",
886
+ "wiki_name": "Perth and Kinross Council",
887
+ "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
888
+ },
874
889
  "PortsmouthCityCouncil": {
875
890
  "postcode": "PO4 0LE",
876
891
  "skip_get_url": true,
@@ -1128,7 +1143,8 @@
1128
1143
  "SwaleBoroughCouncil": {
1129
1144
  "postcode": "ME12 2NQ",
1130
1145
  "skip_get_url": true,
1131
- "uprn": "100061081168",
1146
+ "house_number": "81",
1147
+ "web_driver": "http://selenium:4444",
1132
1148
  "url": "https://swale.gov.uk/bins-littering-and-the-environment/bins/collection-days",
1133
1149
  "wiki_name": "Swale Borough Council"
1134
1150
  },
@@ -1199,6 +1215,13 @@
1199
1215
  "url": "https://collections-torridge.azurewebsites.net/WebService2.asmx",
1200
1216
  "wiki_name": "Torridge District Council"
1201
1217
  },
1218
+ "TunbridgeWellsCouncil": {
1219
+ "url": "https://tunbridgewells.gov.uk",
1220
+ "wiki_command_url_override": "https://tunbridgewells.gov.uk",
1221
+ "uprn": "10090058289",
1222
+ "wiki_name": "Tunbridge Wells Council",
1223
+ "wiki_note": "You will need to use [FindMyAddress](https://www.findmyaddress.co.uk/search) to find the UPRN."
1224
+ },
1202
1225
  "UttlesfordDistrictCouncil": {
1203
1226
  "house_number": "72, Birchanger Lane",
1204
1227
  "postcode": "CM23 5QF",
@@ -74,13 +74,30 @@ class CouncilClass(AbstractGetBinDataClass):
74
74
 
75
75
  driver.get(page)
76
76
 
77
+ wait = WebDriverWait(driver, 10)
78
+ accept_cookies_button = wait.until(
79
+ EC.element_to_be_clickable(
80
+ (
81
+ By.XPATH,
82
+ "//button[contains(text(), 'Accept additional cookies')]",
83
+ )
84
+ )
85
+ )
86
+ accept_cookies_button.click()
87
+
77
88
  # Wait for the element to be clickable
78
- find_your_collection_button = WebDriverWait(driver, 10).until(
89
+ wait = WebDriverWait(driver, 10)
90
+ find_your_collection_button = wait.until(
79
91
  EC.element_to_be_clickable(
80
- (By.XPATH, '//a[contains(text(), "Find your household collection day")]')
92
+ (By.LINK_TEXT, "Find your household collection day")
81
93
  )
82
94
  )
83
95
 
96
+ # Scroll to the element (in case something is blocking it)
97
+ driver.execute_script(
98
+ "arguments[0].scrollIntoView();", find_your_collection_button
99
+ )
100
+
84
101
  # Click the element
85
102
  find_your_collection_button.click()
86
103
 
@@ -107,12 +124,12 @@ class CouncilClass(AbstractGetBinDataClass):
107
124
 
108
125
  postcode_input.send_keys(user_postcode)
109
126
 
110
- find_address_button = WebDriverWait(driver, 10).until(
111
- EC.presence_of_element_located(
112
- (By.CSS_SELECTOR, '[value="Find address"]')
113
- )
127
+ find_address_button = WebDriverWait(driver, 30).until(
128
+ EC.element_to_be_clickable((By.CSS_SELECTOR, '[value="Find address"]'))
114
129
  )
115
- find_address_button.click()
130
+ driver.execute_script("arguments[0].scrollIntoView();", find_address_button)
131
+ driver.execute_script("arguments[0].click();", find_address_button)
132
+ # find_address_button.click()
116
133
 
117
134
  time.sleep(15)
118
135
  # Wait for address box to be visible
@@ -80,6 +80,10 @@ class CouncilClass(AbstractGetBinDataClass):
80
80
  )
81
81
  )
82
82
  search_btn.send_keys(Keys.ENTER)
83
+ WebDriverWait(driver, 10).until(
84
+ EC.presence_of_element_located((By.ID, "collectionTabs"))
85
+ )
86
+
83
87
  soup = BeautifulSoup(driver.page_source, features="html.parser")
84
88
 
85
89
  # Find all tab panels within the collectionTabs
@@ -0,0 +1,96 @@
1
+ import time
2
+
3
+ import requests
4
+
5
+ from uk_bin_collection.uk_bin_collection.common import *
6
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
7
+
8
+
9
+ # import the wonderful Beautiful Soup and the URL grabber
10
+ 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
+ def parse_data(self, page: str, **kwargs) -> dict:
18
+
19
+ user_uprn = kwargs.get("uprn")
20
+ user_postcode = kwargs.get("postcode")
21
+ check_uprn(user_uprn)
22
+ check_postcode(user_postcode)
23
+ bindata = {"bins": []}
24
+
25
+ SESSION_URL = "https://contact.lincoln.gov.uk/authapi/isauthenticated?uri=https://contact.lincoln.gov.uk/AchieveForms/?mode=fill&consentMessage=yes&form_uri=sandbox-publish://AF-Process-503f9daf-4db9-4dd8-876a-6f2029f11196/AF-Stage-a1c0af0f-fec1-4419-80c0-0dd4e1d965c9/definition.json&process=1&process_uri=sandbox-processes://AF-Process-503f9daf-4db9-4dd8-876a-6f2029f11196&process_id=AF-Process-503f9daf-4db9-4dd8-876a-6f2029f11196&hostname=contact.lincoln.gov.uk&withCredentials=true"
26
+
27
+ API_URL = "https://contact.lincoln.gov.uk/apibroker/runLookup"
28
+
29
+ data = {
30
+ "formValues": {
31
+ "Section 1": {
32
+ "chooseaddress": {"value": user_uprn},
33
+ "postcode": {"value": user_postcode},
34
+ }
35
+ },
36
+ }
37
+
38
+ headers = {
39
+ "Content-Type": "application/json",
40
+ "Accept": "application/json",
41
+ "User-Agent": "Mozilla/5.0",
42
+ "X-Requested-With": "XMLHttpRequest",
43
+ "Referer": "https://contact.lincoln.gov.uk/fillform/?iframe_id=fillform-frame-1&db_id=",
44
+ }
45
+ s = requests.session()
46
+ r = s.get(SESSION_URL)
47
+ r.raise_for_status()
48
+ session_data = r.json()
49
+ sid = session_data["auth-session"]
50
+ params = {
51
+ "id": "62aafd258f72c",
52
+ "repeat_against": "",
53
+ "noRetry": "false",
54
+ "getOnlyTokens": "undefined",
55
+ "log_id": "",
56
+ "app_name": "AF-Renderer::Self",
57
+ # unix_timestamp
58
+ "_": str(int(time.time() * 1000)),
59
+ "sid": sid,
60
+ }
61
+
62
+ r = s.post(API_URL, json=data, headers=headers, params=params)
63
+ r.raise_for_status()
64
+ data = r.json()
65
+ rows_data = data["integration"]["transformed"]["rows_data"]
66
+ if not isinstance(rows_data, dict):
67
+ raise ValueError("Invalid data returned from API")
68
+
69
+ BIN_TYPES = [
70
+ ("refusenextdate", "Black Bin", "refuse_freq"),
71
+ ("recyclenextdate", "Brown Bin", "recycle_freq"),
72
+ ("gardennextdate", "Green Bin", "garden_freq"),
73
+ ]
74
+
75
+ for uprn, data in rows_data.items():
76
+ if uprn != user_uprn:
77
+ continue
78
+ for key, bin_type, freq in BIN_TYPES:
79
+ if not data[key]:
80
+ continue
81
+ offsets = [0]
82
+ if data[freq] == "fortnightly":
83
+ offsets.extend(list(range(14, 30, 14)))
84
+ elif data[freq] == "weekly":
85
+ offsets.extend(list(range(7, 30, 7)))
86
+ date = datetime.strptime(data[key], "%Y-%m-%d").date()
87
+ for offset in offsets:
88
+ dict_data = {
89
+ "type": bin_type,
90
+ "collectionDate": (date + timedelta(days=offset)).strftime(
91
+ "%d/%m/%Y"
92
+ ),
93
+ }
94
+ bindata["bins"].append(dict_data)
95
+
96
+ return bindata
@@ -0,0 +1,95 @@
1
+ import time
2
+
3
+ import requests
4
+
5
+ from uk_bin_collection.uk_bin_collection.common import *
6
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
7
+
8
+
9
+ # import the wonderful Beautiful Soup and the URL grabber
10
+ 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
+ def parse_data(self, page: str, **kwargs) -> dict:
18
+
19
+ user_uprn = kwargs.get("uprn")
20
+ check_uprn(user_uprn)
21
+ bindata = {"bins": []}
22
+
23
+ SESSION_URL = "https://pkc-self.achieveservice.com/authapi/isauthenticated?uri=https%253A%252F%252Fpkc-self.achieveservice.com%252Fen%252FAchieveForms%252F%253Fform_uri%253Dsandbox-publish%253A%252F%252FAF-Process-de9223b1-a7c6-408f-aaa3-aee33fd7f7fa%252FAF-Stage-9fa33e2e-4c1b-4963-babf-4348ab8154bc%252Fdefinition.json%2526redirectlink%253D%25252Fen%2526cancelRedirectLink%253D%25252Fen%2526consentMessage%253Dyes&hostname=pkc-self.achieveservice.com&withCredentials=true"
24
+
25
+ API_URL = "https://pkc-self.achieveservice.com/apibroker/runLookup"
26
+
27
+ data = {
28
+ "formValues": {
29
+ "Bin collections": {"propertyUPRNQuery": {"value": user_uprn}}
30
+ },
31
+ }
32
+
33
+ headers = {
34
+ "Content-Type": "application/json",
35
+ "Accept": "application/json",
36
+ "User-Agent": "Mozilla/5.0",
37
+ "X-Requested-With": "XMLHttpRequest",
38
+ "Referer": "https://pkc-self.achieveservice.com/fillform/?iframe_id=fillform-frame-1&db_id=",
39
+ }
40
+ s = requests.session()
41
+ r = s.get(SESSION_URL)
42
+ r.raise_for_status()
43
+ session_data = r.json()
44
+ sid = session_data["auth-session"]
45
+ params = {
46
+ "id": "5c9267cee5efe",
47
+ "repeat_against": "",
48
+ "noRetry": "true",
49
+ "getOnlyTokens": "undefined",
50
+ "log_id": "",
51
+ "app_name": "AF-Renderer::Self",
52
+ # unix_timestamp
53
+ "_": str(int(time.time() * 1000)),
54
+ "sid": sid,
55
+ }
56
+
57
+ r = s.post(API_URL, json=data, headers=headers, params=params)
58
+ r.raise_for_status()
59
+
60
+ data = r.json()
61
+ rows_data = data["integration"]["transformed"]["rows_data"]["0"]
62
+ if not isinstance(rows_data, dict):
63
+ raise ValueError("Invalid data returned from API")
64
+
65
+ schedule = {
66
+ "Green Bin": [
67
+ rows_data.get("nextGeneralWasteCollectionDate"),
68
+ rows_data.get("nextGeneralWasteCollectionDate2nd"),
69
+ ],
70
+ "Blue Bin": [
71
+ rows_data.get("nextBlueCollectionDate"),
72
+ rows_data.get("nextBlueWasteCollectionDate2nd"),
73
+ ],
74
+ "Grey Bin": [
75
+ rows_data.get("nextGreyWasteCollectionDate"),
76
+ rows_data.get("nextGreyWasteCollectionDate2nd"),
77
+ ],
78
+ "Brown Bin": [
79
+ rows_data.get("nextGardenandFoodWasteCollectionDate"),
80
+ rows_data.get("nextGardenandFoodWasteCollectionDate2nd"),
81
+ ],
82
+ "Paper Waste": [
83
+ rows_data.get("nextPaperWasteCollectionDate"),
84
+ rows_data.get("nextPaperWasteCollectionDate2nd"),
85
+ ],
86
+ }
87
+
88
+ # Format and output the schedule
89
+ for bin_type, dates in schedule.items():
90
+ if any(dates):
91
+ for date in dates:
92
+ dict_data = {"type": bin_type, "collectionDate": date}
93
+ bindata["bins"].append(dict_data)
94
+
95
+ return bindata
@@ -1,9 +1,11 @@
1
- import requests
2
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
+
3
6
  from uk_bin_collection.uk_bin_collection.common import *
4
7
  from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
5
8
 
6
-
7
9
  # import the wonderful Beautiful Soup and the URL grabber
8
10
 
9
11
 
@@ -17,36 +19,72 @@ class CouncilClass(AbstractGetBinDataClass):
17
19
  def parse_data(self, page: str, **kwargs) -> dict:
18
20
  # Get postcode and UPRN from kwargs
19
21
  user_postcode = kwargs.get("postcode")
20
- user_uprn = kwargs.get("uprn")
22
+ user_paon = kwargs.get("paon")
23
+ web_driver = kwargs.get("web_driver")
24
+ headless = kwargs.get("headless")
21
25
  check_postcode(user_postcode)
22
- check_uprn(user_uprn)
26
+ check_paon(user_paon)
23
27
 
24
28
  # Build URL to parse
25
- council_url = f"https://swale.gov.uk/bins-littering-and-the-environment/bins/collection-days?postcode={user_postcode.replace(' ', '+')}&addresses={user_uprn}&address-submit="
29
+ council_url = "https://swale.gov.uk/bins-littering-and-the-environment/bins/my-collection-day"
30
+
31
+ # Create Selenium webdriver
32
+ driver = create_webdriver(web_driver, headless, None, __name__)
33
+ driver.get(council_url)
34
+
35
+ # Wait for the postcode field to appear then populate it
36
+ try:
37
+ inputElement_postcode = WebDriverWait(driver, 10).until(
38
+ EC.presence_of_element_located((By.ID, "q462406_q1"))
39
+ )
40
+ inputElement_postcode.send_keys(user_postcode)
41
+ except Exception:
42
+ print("Page failed to load. Probably due to Cloudflare robot check!")
43
+
44
+ # Click search button
45
+ findAddress = WebDriverWait(driver, 10).until(
46
+ EC.presence_of_element_located((By.ID, "form_email_462397_submit"))
47
+ )
48
+ driver.execute_script("arguments[0].click();", findAddress)
49
+
50
+ # Wait for the 'Select address' dropdown to appear and select option matching the house name/number
51
+ WebDriverWait(driver, 10).until(
52
+ EC.element_to_be_clickable(
53
+ (
54
+ By.XPATH,
55
+ "//select[@id='SBCYBDAddressList']//option[contains(., '"
56
+ + user_paon
57
+ + "')]",
58
+ )
59
+ )
60
+ ).click()
61
+
62
+ # Click search button
63
+ getBins = WebDriverWait(driver, 10).until(
64
+ EC.presence_of_element_located((By.ID, "form_email_462397_submit"))
65
+ )
66
+ driver.execute_script("arguments[0].click();", getBins)
67
+
68
+ BinTable = WebDriverWait(driver, 30).until(
69
+ EC.presence_of_element_located((By.ID, "SBC-YBD-Main"))
70
+ )
26
71
 
27
- # Parse URL and read if connection successful
28
- requests.packages.urllib3.disable_warnings()
29
- response = requests.get(council_url, verify=False)
30
- if response.status_code == 200:
31
- soup = BeautifulSoup(response.text, features="html.parser")
32
- soup.prettify()
33
- else:
34
- raise ConnectionAbortedError("Could not parse council website.")
72
+ soup = BeautifulSoup(driver.page_source, features="html.parser")
73
+ soup.prettify()
35
74
 
36
75
  data = {"bins": []}
37
76
 
38
77
  # Get the collection bullet points on the page and parse them
39
- form_area = soup.find("form", {"class": "integration bin-lookup"})
40
- collections = [
41
- item.text.strip().split(",") for item in form_area.find_all("li")
42
- ]
43
- for c in collections:
44
- bin_type = c[0].strip()
45
- # temp_date = c[2].strip() + " " + str(datetime.now().year)
46
- bin_date = datetime.strptime(
47
- c[2].strip() + " " + str(datetime.now().year), "%d %B %Y"
48
- ).strftime(date_format)
49
- dict_data = {"type": bin_type, "collectionDate": bin_date}
50
- data["bins"].append(dict_data)
78
+ nextCollections = soup.find("div", {"id": "nextCollections"})
79
+ for c in nextCollections:
80
+ collection = c.find_all("strong")
81
+ for bin in collection:
82
+ split = (bin.text).split(" on ")
83
+ bin_type = split[0]
84
+ bin_date = datetime.strptime(split[1], "%A %d %b %Y").strftime(
85
+ "%d/%m/%Y"
86
+ )
87
+ dict_data = {"type": bin_type, "collectionDate": bin_date}
88
+ data["bins"].append(dict_data)
51
89
 
52
90
  return data
@@ -0,0 +1,71 @@
1
+ import time
2
+
3
+ import requests
4
+
5
+ from uk_bin_collection.uk_bin_collection.common import *
6
+ from uk_bin_collection.uk_bin_collection.get_bin_data import AbstractGetBinDataClass
7
+
8
+
9
+ # import the wonderful Beautiful Soup and the URL grabber
10
+ 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
+ def parse_data(self, page: str, **kwargs) -> dict:
18
+
19
+ user_uprn = kwargs.get("uprn")
20
+ check_uprn(user_uprn)
21
+ bindata = {"bins": []}
22
+
23
+ SESSION_URL = "https://mytwbc.tunbridgewells.gov.uk/authapi/isauthenticated?uri=https%3A%2F%2Fmytwbc.tunbridgewells.gov.uk%2FAchieveForms%2F%3Fmode%3Dfill%26consentMessage%3Dyes%26form_uri%3Dsandbox-publish%3A%2F%2FAF-Process-e01af4d4-eb0f-4cfe-a5ac-c47b63f017ed%2FAF-Stage-88caf66c-378f-4082-ad1d-07b7a850af38%2Fdefinition.json%26process%3D1%26process_uri%3Dsandbox-processes%3A%2F%2FAF-Process-e01af4d4-eb0f-4cfe-a5ac-c47b63f017ed%26process_id%3DAF-Process-e01af4d4-eb0f-4cfe-a5ac-c47b63f017ed&hostname=mytwbc.tunbridgewells.gov.uk&withCredentials=true"
24
+
25
+ API_URL = "https://mytwbc.tunbridgewells.gov.uk/apibroker/runLookup"
26
+
27
+ data = {
28
+ "formValues": {"Property": {"siteReference": {"value": user_uprn}}},
29
+ }
30
+
31
+ headers = {
32
+ "Content-Type": "application/json",
33
+ "Accept": "application/json",
34
+ "User-Agent": "Mozilla/5.0",
35
+ "X-Requested-With": "XMLHttpRequest",
36
+ "Referer": "https://mytwbc.tunbridgewells.gov.uk/fillform/?iframe_id=fillform-frame-1&db_id=",
37
+ }
38
+ s = requests.session()
39
+ r = s.get(SESSION_URL)
40
+ r.raise_for_status()
41
+ session_data = r.json()
42
+ sid = session_data["auth-session"]
43
+ params = {
44
+ "id": "6314720683f30",
45
+ "repeat_against": "",
46
+ "noRetry": "false",
47
+ "getOnlyTokens": "undefined",
48
+ "log_id": "",
49
+ "app_name": "AF-Renderer::Self",
50
+ # unix_timestamp
51
+ "_": str(int(time.time() * 1000)),
52
+ "sid": sid,
53
+ }
54
+
55
+ r = s.post(API_URL, json=data, headers=headers, params=params)
56
+ r.raise_for_status()
57
+
58
+ data = r.json()
59
+ rows_data = data["integration"]["transformed"]["rows_data"]
60
+ if not isinstance(rows_data, dict):
61
+ raise ValueError("Invalid data returned from API")
62
+
63
+ for _, item in rows_data.items():
64
+ bin_type = item["collectionType"]
65
+ date = datetime.strptime(item["nextDateUnformatted"], "%d/%m/%Y").strftime(
66
+ "%d/%m/%Y"
67
+ )
68
+ dict_data = {"type": bin_type, "collectionDate": date}
69
+ bindata["bins"].append(dict_data)
70
+
71
+ return bindata
@@ -74,30 +74,51 @@ class CouncilClass(AbstractGetBinDataClass):
74
74
  soup = BeautifulSoup(driver.page_source, features="html.parser")
75
75
  soup.prettify()
76
76
 
77
- rubbish_date = datetime.strptime(
78
- " ".join(
79
- soup.find("div", {"id": "FINDYOURBINDAYS_RUBBISHDATE_OUTERDIV"})
80
- .get_text(strip=True)
81
- .split()[6:8]
82
- ),
83
- "%d %B",
84
- ).replace(year=datetime.now().year)
85
- recycling_date = datetime.strptime(
86
- " ".join(
87
- soup.find("div", {"id": "FINDYOURBINDAYS_RECYCLINGDATE_OUTERDIV"})
88
- .get_text(strip=True)
89
- .split()[6:8]
90
- ),
91
- "%d %B",
92
- ).replace(year=datetime.now().year)
93
- food_date = datetime.strptime(
94
- " ".join(
95
- soup.find("div", {"id": "FINDYOURBINDAYS_FOODWASTEDATE_OUTERDIV"})
96
- .get_text(strip=True)
97
- .split()[8:10]
98
- ),
99
- "%d %B",
100
- ).replace(year=datetime.now().year)
77
+ rubbish_div = soup.find(
78
+ "div", {"id": "FINDYOURBINDAYS_RUBBISHDATE_OUTERDIV"}
79
+ )
80
+ try:
81
+ rubbish_date = rubbish_div.find_all("div")[2]
82
+ rubbish_date = datetime.strptime(
83
+ rubbish_date.text,
84
+ "%A %d %B",
85
+ ).replace(year=datetime.now().year)
86
+ except:
87
+ rubbish_date = rubbish_div.find_all("div")[3]
88
+ rubbish_date = datetime.strptime(
89
+ rubbish_date.text,
90
+ "%A %d %B",
91
+ ).replace(year=datetime.now().year)
92
+ recycling_div = soup.find(
93
+ "div", {"id": "FINDYOURBINDAYS_RECYCLINGDATE_OUTERDIV"}
94
+ )
95
+ try:
96
+ recycling_date = recycling_div.find_all("div")[2]
97
+ recycling_date = datetime.strptime(
98
+ recycling_date.text,
99
+ "%A %d %B",
100
+ ).replace(year=datetime.now().year)
101
+ except:
102
+ rubbish_date = recycling_div.find_all("div")[3]
103
+ rubbish_date = datetime.strptime(
104
+ rubbish_date.text,
105
+ "%A %d %B",
106
+ ).replace(year=datetime.now().year)
107
+ food_div = soup.find(
108
+ "div", {"id": "FINDYOURBINDAYS_RECYCLINGDATE_OUTERDIV"}
109
+ )
110
+ try:
111
+ food_date = food_div.find_all("div")[2]
112
+ food_date = datetime.strptime(
113
+ food_date.text,
114
+ "%A %d %B",
115
+ ).replace(year=datetime.now().year)
116
+ except:
117
+ food_date = food_div.find_all("div")[3]
118
+ food_date = datetime.strptime(
119
+ food_date.text,
120
+ "%A %d %B",
121
+ ).replace(year=datetime.now().year)
101
122
 
102
123
  if datetime.now().month == 12 and rubbish_date.month == 1:
103
124
  rubbish_date = rubbish_date + relativedelta(years=1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: uk_bin_collection
3
- Version: 0.98.4
3
+ Version: 0.99.0
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=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=R0NULatIVLIsX13cKIDBD9ukIbCJ3nw_Gg3iC4nudvE,68070
5
+ uk_bin_collection/tests/input.json,sha256=MyICwD7_JIC5MIoyHk9kUItaHIxkPHuWdG85bsAiI4g,69171
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
@@ -17,7 +17,7 @@ uk_bin_collection/uk_bin_collection/councils/ArmaghBanbridgeCraigavonCouncil.py,
17
17
  uk_bin_collection/uk_bin_collection/councils/ArunCouncil.py,sha256=yfhthv9nuogP19VOZ3TYQrq51qqjiCZcSel4sXhiKjs,4012
18
18
  uk_bin_collection/uk_bin_collection/councils/AylesburyValeCouncil.py,sha256=LouqjspEMt1TkOGqWHs2zkxwOETIy3n7p64uKIlAgUg,2401
19
19
  uk_bin_collection/uk_bin_collection/councils/BCPCouncil.py,sha256=W7QBx6Mgso8RYosuXsaYo3GGNAu-tiyBSmuYxr1JSOU,1707
20
- uk_bin_collection/uk_bin_collection/councils/BarnetCouncil.py,sha256=NccMd0830aiNRQ8SH6mc4r5Hlugfey5-PyUd24QLo4s,8478
20
+ uk_bin_collection/uk_bin_collection/councils/BarnetCouncil.py,sha256=Sd4-pbv0QZsR7soxvXYqsfdOUIqZqS6notyoZthG77s,9182
21
21
  uk_bin_collection/uk_bin_collection/councils/BarnsleyMBCouncil.py,sha256=MgF_7XyIcIoNzFR0OJsjBkLCZKgWxBrV6nTcutMxO1Q,4244
22
22
  uk_bin_collection/uk_bin_collection/councils/BasildonCouncil.py,sha256=SBvAa0GZM3V7ygK8ARawbHAPH6R_303U30RH8WYPi5Q,3020
23
23
  uk_bin_collection/uk_bin_collection/councils/BasingstokeCouncil.py,sha256=VPWGljnH4C3q8qs5ZmCtqjNjgWQvviALzjk00q3EZeQ,2632
@@ -81,7 +81,7 @@ uk_bin_collection/uk_bin_collection/councils/GedlingBoroughCouncil.py,sha256=Iss
81
81
  uk_bin_collection/uk_bin_collection/councils/GlasgowCityCouncil.py,sha256=i7BympEhCm7D9yR0p5_QQICtWvNcDYNJIWB19SA0g2k,2303
82
82
  uk_bin_collection/uk_bin_collection/councils/GloucesterCityCouncil.py,sha256=8Wjvmdvg5blHVrREaEnhhWZaWhYVP4v_KdDVPLIUxaU,4889
83
83
  uk_bin_collection/uk_bin_collection/councils/GuildfordCouncil.py,sha256=9pVrmQhZcK2AD8gX8mNvP--L4L9KaY6L3B822VX6fec,5695
84
- uk_bin_collection/uk_bin_collection/councils/HaltonBoroughCouncil.py,sha256=r8cmtWhMJg-XG63ZHxidKKW7i4yQNrZSSMSCkBwrqjI,5837
84
+ uk_bin_collection/uk_bin_collection/councils/HaltonBoroughCouncil.py,sha256=gq_CPqi6qM2oNiHhKKF1lZC86fyKL4lPhh_DN9pJZ04,5971
85
85
  uk_bin_collection/uk_bin_collection/councils/HaringeyCouncil.py,sha256=t_6AkAu4wrv8Q0WlDhWh_82I0djl5tk531Pzs-SjWzg,2647
86
86
  uk_bin_collection/uk_bin_collection/councils/HarrogateBoroughCouncil.py,sha256=_g3fP5Nq-OUjgNrfRf4UEyFKzq0x8QK-4enh5RP1efA,2050
87
87
  uk_bin_collection/uk_bin_collection/councils/HighPeakCouncil.py,sha256=oqF8M0lcT3KsrG6W6I6JJX07E6Sc_-_sr7MybfIMab8,4626
@@ -96,6 +96,7 @@ uk_bin_collection/uk_bin_collection/councils/KnowsleyMBCouncil.py,sha256=VdlWDES
96
96
  uk_bin_collection/uk_bin_collection/councils/LancasterCityCouncil.py,sha256=FmHT6oyD4BwWuhxA80PHnGA7HPrLuyjP_54Cg8hT6k4,2537
97
97
  uk_bin_collection/uk_bin_collection/councils/LeedsCityCouncil.py,sha256=iSZApZ9oSfSatQ6dAxmykSfti91jGuY6n2BwEkVMOiU,5144
98
98
  uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py,sha256=l3zgTWuKOW8fgb8PmXv0OTI6HaiGBPndefNQk8MM4oY,1810
99
+ uk_bin_collection/uk_bin_collection/councils/LincolnCouncil.py,sha256=aUCqjHuk0sLtx83a-2agcLIMgEbfqjltXRCBRXT9J-8,3733
99
100
  uk_bin_collection/uk_bin_collection/councils/LisburnCastlereaghCityCouncil.py,sha256=vSOzdEwp9ZeUhed7E3eVv9ReD-2XgbSkpyAbVnfc-Gk,3309
100
101
  uk_bin_collection/uk_bin_collection/councils/LiverpoolCityCouncil.py,sha256=n17OqZrCGrPrnxGUfHc-RGkb4oJ9Bx6uUWiLdzxfQlY,2587
101
102
  uk_bin_collection/uk_bin_collection/councils/LondonBoroughEaling.py,sha256=QDx2Izr-6hUSFMi4UWqsgo3p6U8aRZ9d_Cu9cBSp2rY,1653
@@ -133,6 +134,7 @@ uk_bin_collection/uk_bin_collection/councils/NorthYorkshire.py,sha256=2wTrr3VrZD
133
134
  uk_bin_collection/uk_bin_collection/councils/NorthumberlandCouncil.py,sha256=KEFsxEvQ159fkuFo-fza67YCnnCZ5ElwE80zTrqDEWI,4990
134
135
  uk_bin_collection/uk_bin_collection/councils/NottinghamCityCouncil.py,sha256=panTCjnsBOQ98-TBO9xVZk_jcT_gjMhx3Gg5oWxBRLo,1254
135
136
  uk_bin_collection/uk_bin_collection/councils/OldhamCouncil.py,sha256=9dlesCxNoVXlmQaqZj7QFh00smnJbm1Gnjkr_Uvzurs,1771
137
+ uk_bin_collection/uk_bin_collection/councils/PerthAndKinrossCouncil.py,sha256=Kos5GzN2co3Ij3tSHOXB9S71Yt78RROCfVRtnh7M1VU,3657
136
138
  uk_bin_collection/uk_bin_collection/councils/PortsmouthCityCouncil.py,sha256=xogNgVvwM5FljCziiNLgZ_wzkOnrQkifi1dkPMDRMtg,5588
137
139
  uk_bin_collection/uk_bin_collection/councils/PrestonCityCouncil.py,sha256=3Nuin2hQsiEsbJR_kHldtzRhzmnPFctH7C7MFG7thj8,3838
138
140
  uk_bin_collection/uk_bin_collection/councils/ReadingBoroughCouncil.py,sha256=ZlQjU0IeKylGE9VlivSMh4XKwoLgntESPiylSOYkuD4,1009
@@ -170,7 +172,7 @@ uk_bin_collection/uk_bin_collection/councils/StokeOnTrentCityCouncil.py,sha256=K
170
172
  uk_bin_collection/uk_bin_collection/councils/StratfordUponAvonCouncil.py,sha256=DMTAcXT_lay8Cl1hBbzf_LN7-GwTDGxT3Ug9QJkaF9Y,3936
171
173
  uk_bin_collection/uk_bin_collection/councils/StroudDistrictCouncil.py,sha256=9bYWppi7ViLGHL4VEg--nFn28MLYJYbiEntull1uZxU,3561
172
174
  uk_bin_collection/uk_bin_collection/councils/SunderlandCityCouncil.py,sha256=4DnKyyu56_AwuchD6_oL1dvpDStMvkkxQtYN79rUKOs,3825
173
- uk_bin_collection/uk_bin_collection/councils/SwaleBoroughCouncil.py,sha256=CCAjclhkCxwf_MkdrIif7MZpLfV5SPy7hyM7BE0TRPc,2048
175
+ uk_bin_collection/uk_bin_collection/councils/SwaleBoroughCouncil.py,sha256=ak0zqBJ6UAS8_t5zKGwigMxPMdlQuYXRsGCQJCNERJs,3415
174
176
  uk_bin_collection/uk_bin_collection/councils/SwanseaCouncil.py,sha256=nmVPoPhnFgVi--vczX2i4Sf3bqM5RWJuwfhioRUr5XE,2303
175
177
  uk_bin_collection/uk_bin_collection/councils/TamesideMBCouncil.py,sha256=k2TAAZG7n2S1BWVyxbE_-4-lZuzhOimCNz4yimUCOGk,1995
176
178
  uk_bin_collection/uk_bin_collection/councils/TandridgeDistrictCouncil.py,sha256=KLVvM2NNq_DQylVe5dwO2l7qPahLHg08jJGLCv1MBQ4,2324
@@ -181,6 +183,7 @@ uk_bin_collection/uk_bin_collection/councils/ThreeRiversDistrictCouncil.py,sha25
181
183
  uk_bin_collection/uk_bin_collection/councils/TonbridgeAndMallingBC.py,sha256=UlgnHDoi8ecav2H5-HqKNDpqW1J3RN-c___5c08_Q7I,4859
182
184
  uk_bin_collection/uk_bin_collection/councils/TorbayCouncil.py,sha256=JW_BS7wkfxFsmx6taQtPAQWdBp1AfLrxs0XRQ2XZcSw,2029
183
185
  uk_bin_collection/uk_bin_collection/councils/TorridgeDistrictCouncil.py,sha256=6gOO02pYU0cbj3LAHiBVNG4zkFMyIGbkE2jAye3KcGM,6386
186
+ uk_bin_collection/uk_bin_collection/councils/TunbridgeWellsCouncil.py,sha256=s8Nm9Ef-4561mEXPa0ylYHrXyYIulgCcNV2uAnrXyZk,2846
184
187
  uk_bin_collection/uk_bin_collection/councils/UttlesfordDistrictCouncil.py,sha256=GSELWbSn5jtznv6FSLIMxK6CyQ27MW9FoY_m5jhTEBA,4175
185
188
  uk_bin_collection/uk_bin_collection/councils/ValeofGlamorganCouncil.py,sha256=Phgb_ECiUOOkqOx6OsfsTHMCW5VQfRmOC2zgYIQhuZA,5044
186
189
  uk_bin_collection/uk_bin_collection/councils/ValeofWhiteHorseCouncil.py,sha256=KBKGHcWAdPC_8-CfKnLOdP7Ww6RIvlxLIJGqBsq_77g,4208
@@ -191,7 +194,7 @@ uk_bin_collection/uk_bin_collection/councils/WarwickDistrictCouncil.py,sha256=3W
191
194
  uk_bin_collection/uk_bin_collection/councils/WaverleyBoroughCouncil.py,sha256=tp9l7vdgSGRzNNG0pDfnNuFj4D2bpRJUJmAiTJ6bM0g,4662
192
195
  uk_bin_collection/uk_bin_collection/councils/WealdenDistrictCouncil.py,sha256=SvSSaLkx7iJjzypAwKkaJwegXkSsIQtUOS2V605kz1A,3368
193
196
  uk_bin_collection/uk_bin_collection/councils/WelhatCouncil.py,sha256=ikUft37dYNJghfe-_6Fskiq1JihqpLmLNj38QkKSUUA,2316
194
- uk_bin_collection/uk_bin_collection/councils/WestBerkshireCouncil.py,sha256=r90AIUdPgo85VuuvN_NeCDUy3NEJXdO4Ntt93yKo6qI,5110
197
+ uk_bin_collection/uk_bin_collection/councils/WestBerkshireCouncil.py,sha256=XhTimZAPNgcuFgNp5mQjkR8mC4LRqUEUCy6e6plHspM,6004
195
198
  uk_bin_collection/uk_bin_collection/councils/WestLindseyDistrictCouncil.py,sha256=JFWUy4w0CKulGq16PfbRDKAdQEbokVEuabwlZYigdEU,4606
196
199
  uk_bin_collection/uk_bin_collection/councils/WestLothianCouncil.py,sha256=dq0jimtARvRkZiGbVFrXXZgY-BODtz3uYZ5UKn0bf64,4114
197
200
  uk_bin_collection/uk_bin_collection/councils/WestMorlandAndFurness.py,sha256=jbqV3460rn9D0yTBGWjpSe1IvWWcdGur5pzgj-hJcQ4,2513
@@ -210,8 +213,8 @@ uk_bin_collection/uk_bin_collection/councils/YorkCouncil.py,sha256=I2kBYMlsD4bId
210
213
  uk_bin_collection/uk_bin_collection/councils/council_class_template/councilclasstemplate.py,sha256=4s9ODGPAwPqwXc8SrTX5Wlfmizs3_58iXUtHc4Ir86o,1162
211
214
  uk_bin_collection/uk_bin_collection/create_new_council.py,sha256=m-IhmWmeWQlFsTZC4OxuFvtw5ZtB8EAJHxJTH4O59lQ,1536
212
215
  uk_bin_collection/uk_bin_collection/get_bin_data.py,sha256=YvmHfZqanwrJ8ToGch34x-L-7yPe31nB_x77_Mgl_vo,4545
213
- uk_bin_collection-0.98.4.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
214
- uk_bin_collection-0.98.4.dist-info/METADATA,sha256=YKK2go_0HJQg2QyV6u0dz0ALkinbMCvzNteuuslvn3I,16843
215
- uk_bin_collection-0.98.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
216
- uk_bin_collection-0.98.4.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
217
- uk_bin_collection-0.98.4.dist-info/RECORD,,
216
+ uk_bin_collection-0.99.0.dist-info/LICENSE,sha256=vABBUOzcrgfaTKpzeo-si9YVEun6juDkndqA8RKdKGs,1071
217
+ uk_bin_collection-0.99.0.dist-info/METADATA,sha256=aakearxZxxoL0MqAE2WaAqz1NPpl2ePxoPHxxdkQHpU,16843
218
+ uk_bin_collection-0.99.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
219
+ uk_bin_collection-0.99.0.dist-info/entry_points.txt,sha256=36WCSGMWSc916S3Hi1ZkazzDKHaJ6CD-4fCEFm5MIao,90
220
+ uk_bin_collection-0.99.0.dist-info/RECORD,,