warn-scraper 1.2.112__py3-none-any.whl → 1.2.114__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.
@@ -112,7 +112,7 @@ class Site:
112
112
  logger.debug("Fetching from cache")
113
113
  return self.cache.fetch(url, params)
114
114
  else:
115
- logger.debug("Pulling from the web")
115
+ logger.debug(f"Pulling from the web: {url} with params {params}")
116
116
  response = requests.get(url, params=params, verify=self.verify)
117
117
  logger.debug(f"Response code: {response.status_code}")
118
118
  html = response.text
warn/scrapers/la.py CHANGED
@@ -1,13 +1,10 @@
1
1
  import logging
2
2
  import os
3
3
  import re
4
- import sys
5
- from base64 import b64decode
6
4
  from datetime import datetime
7
5
  from pathlib import Path
8
6
 
9
7
  import pdfplumber
10
- import requests
11
8
  from bs4 import BeautifulSoup
12
9
 
13
10
  from .. import utils
@@ -36,14 +33,6 @@ def scrape(
36
33
 
37
34
  Returns: the Path where the file is written
38
35
  """
39
- try:
40
- zyte_api_key = os.environ["ZYTE_API_KEY"]
41
- except KeyError:
42
- logger.error(
43
- "No ZYTE_API_KEY variable found in environment. Please get an API key from Zyte and export it."
44
- )
45
- sys.exit(1)
46
-
47
36
  # Fire up the cache
48
37
  cache = Cache(cache_dir)
49
38
 
@@ -54,18 +43,7 @@ def scrape(
54
43
 
55
44
  # Download the root page
56
45
  url = f"{base_url}Downloads/{file_base}.asp"
57
- api_response = requests.post(
58
- "https://api.zyte.com/v1/extract",
59
- auth=(zyte_api_key, ""),
60
- json={
61
- "url": url,
62
- "httpResponseBody": True,
63
- "followRedirect": True,
64
- },
65
- )
66
- html_bytes: bytes = b64decode(api_response.json()["httpResponseBody"])
67
- # html = utils.get_url(url).text
68
- html = html_bytes.decode("utf-8", errors="backslashreplace")
46
+ htmlbin, html = utils.get_with_zyte(url)
69
47
 
70
48
  # Save it to the cache
71
49
  cache_key = cache_dir / f"{state_code}/{file_base}.html"
@@ -82,25 +60,11 @@ def scrape(
82
60
  if "WARN Notices" in link.text:
83
61
  # Download the PDF
84
62
  pdf_url = f"{base_url}{link['href']}"
85
- logger.debug(pdf_url)
86
- api_response = requests.post(
87
- "https://api.zyte.com/v1/extract",
88
- auth=(zyte_api_key, ""),
89
- json={
90
- "url": pdf_url,
91
- "httpResponseBody": True,
92
- "followRedirect": True,
93
- },
94
- )
95
- http_response_body: bytes = b64decode(
96
- api_response.json()["httpResponseBody"]
97
- )
63
+ rawbin, rawtext = utils.get_with_zyte(pdf_url)
98
64
  pdf_path = cache_dir / f"{state_code}/{os.path.basename(pdf_url)}"
99
65
 
100
66
  with open(pdf_path, "wb") as fp:
101
- fp.write(http_response_body)
102
-
103
- # pdf_path = _read_or_download(cache, state_code, pdf_url)
67
+ fp.write(rawbin)
104
68
 
105
69
  # Process the PDF
106
70
  logger.debug(f"Attempting to parse {pdf_path}")
warn/scrapers/ok.py CHANGED
@@ -1,16 +1,19 @@
1
+ import logging
1
2
  from pathlib import Path
2
3
 
3
- from warn.platforms.job_center.utils import scrape_state
4
+ import requests
4
5
 
5
6
  from .. import utils
6
7
 
7
- __authors__ = ["zstumgoren", "Dilcia19"]
8
- __tags__ = ["jobcenter"]
8
+ __authors__ = ["zstumgoren", "Dilcia19", "stucka"]
9
+ __tags__ = [""]
9
10
  __source__ = {
10
11
  "name": "Oklahoma Office of Workforces Development",
11
- "url": "https://okjobmatch.com/search/warn_lookups/new",
12
+ "url": "https://www.employoklahoma.gov/Participants/s/warnnotices",
12
13
  }
13
14
 
15
+ logger = logging.getLogger(__name__)
16
+
14
17
 
15
18
  def scrape(
16
19
  data_dir: Path = utils.WARN_DATA_DIR,
@@ -28,13 +31,85 @@ def scrape(
28
31
  Returns: the Path where the file is written
29
32
  """
30
33
  output_csv = data_dir / "ok.csv"
31
- search_url = "https://okjobmatch.com/search/warn_lookups"
32
- # Date chosen based on manual research
33
- stop_year = 1999
34
- # Use cache for years before current and prior year
35
- scrape_state(
36
- "OK", search_url, output_csv, stop_year, cache_dir, use_cache=use_cache
37
- )
34
+ # search_url = "https://okjobmatch.com/search/warn_lookups"
35
+ # search_url = "https://www.employoklahoma.gov/Participants/s/warnnotices"
36
+ posturl = "https://www.employoklahoma.gov/Participants/s/sfsites/aura?r=2&aura.ApexAction.execute=6"
37
+
38
+ # There are a bunch of hard-coded values in here that seem to work for at least a day.
39
+ # Undetermined:
40
+ # -- Will this continue working in the short- or medium-term?
41
+ # -- What is the signficance of each variable?
42
+ # -- How do we refresh these?
43
+
44
+ headers = {
45
+ "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/142.0",
46
+ "Accept": "*/*",
47
+ "Accept-Language": "en-US,en;q=0.5",
48
+ "Accept-Encoding": "gzip, deflate, br, zstd",
49
+ "Referer": "https://www.employoklahoma.gov/Participants/s/warnnotices",
50
+ "X-SFDC-LDS-Endpoints": "ApexActionController.execute:ConfigurableLoginAndMaintenanceMessages.hasDocument, ApexActionController.execute:ConfigurableLoginAndMaintenanceMessages.checkJobExpiry, ApexActionController.execute:ConfigurableLoginAndMaintenanceMessages.checkResumeExpiry, ApexActionController.execute:ConfigurableLoginAndMaintenanceMessages.checkUIRegistered, ApexActionController.execute:ConfigurableLoginAndMaintenanceMessages.getLoginMaintenanceMessage, ApexActionController.execute:OESC_JS_getWARNLayoffNotices.getListofLayoffAccService",
51
+ "X-SFDC-Page-Scope-Id": "9c659a19-8020-41b0-a81c-36335e22801a",
52
+ "X-SFDC-Request-Id": "16140000007a08bd2f",
53
+ "X-SFDC-Page-Cache": "9439898463d86806",
54
+ "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
55
+ "X-B3-TraceId": "856a2236ba7d283e",
56
+ "X-B3-SpanId": "b79b2da3a7dc4544",
57
+ "X-B3-Sampled": "0",
58
+ "Origin": "https://www.employoklahoma.gov",
59
+ "Connection": "keep-alive",
60
+ "Cookie": "renderCtx=%7B%22pageId%22%3A%223823bba2-3b00-4db7-aca6-5ca0eb67fc63%22%2C%22schema%22%3A%22Published%22%2C%22viewType%22%3A%22Published%22%2C%22brandingSetId%22%3A%22fa0b6362-0214-44b9-947d-2543eaab22c7%22%2C%22audienceIds%22%3A%22%22%7D; CookieConsentPolicy=0:1; LSKey-c$CookieConsentPolicy=0:1; pctrk=f3070d0c-7078-4062-96bb-de9e82cbb1db",
61
+ "Sec-Fetch-Dest": "empty",
62
+ "Sec-Fetch-Mode": "cors",
63
+ "Sec-Fetch-Site": "same-origin",
64
+ }
65
+
66
+ payload = "message=%7B%22actions%22%3A%5B%7B%22id%22%3A%22156%3Ba%22%2C%22descriptor%22%3A%22aura%3A%2F%2FApexActionController%2FACTION%24execute%22%2C%22callingDescriptor%22%3A%22UNKNOWN%22%2C%22params%22%3A%7B%22namespace%22%3A%22%22%2C%22classname%22%3A%22ConfigurableLoginAndMaintenanceMessages%22%2C%22method%22%3A%22hasDocument%22%2C%22params%22%3A%7B%7D%2C%22cacheable%22%3Afalse%2C%22isContinuation%22%3Afalse%7D%7D%2C%7B%22id%22%3A%22157%3Ba%22%2C%22descriptor%22%3A%22aura%3A%2F%2FApexActionController%2FACTION%24execute%22%2C%22callingDescriptor%22%3A%22UNKNOWN%22%2C%22params%22%3A%7B%22namespace%22%3A%22%22%2C%22classname%22%3A%22ConfigurableLoginAndMaintenanceMessages%22%2C%22method%22%3A%22checkJobExpiry%22%2C%22params%22%3A%7B%7D%2C%22cacheable%22%3Afalse%2C%22isContinuation%22%3Afalse%7D%7D%2C%7B%22id%22%3A%22158%3Ba%22%2C%22descriptor%22%3A%22aura%3A%2F%2FApexActionController%2FACTION%24execute%22%2C%22callingDescriptor%22%3A%22UNKNOWN%22%2C%22params%22%3A%7B%22namespace%22%3A%22%22%2C%22classname%22%3A%22ConfigurableLoginAndMaintenanceMessages%22%2C%22method%22%3A%22checkResumeExpiry%22%2C%22params%22%3A%7B%7D%2C%22cacheable%22%3Afalse%2C%22isContinuation%22%3Afalse%7D%7D%2C%7B%22id%22%3A%22159%3Ba%22%2C%22descriptor%22%3A%22aura%3A%2F%2FApexActionController%2FACTION%24execute%22%2C%22callingDescriptor%22%3A%22UNKNOWN%22%2C%22params%22%3A%7B%22namespace%22%3A%22%22%2C%22classname%22%3A%22ConfigurableLoginAndMaintenanceMessages%22%2C%22method%22%3A%22checkUIRegistered%22%2C%22params%22%3A%7B%7D%2C%22cacheable%22%3Afalse%2C%22isContinuation%22%3Afalse%7D%7D%2C%7B%22id%22%3A%22160%3Ba%22%2C%22descriptor%22%3A%22aura%3A%2F%2FApexActionController%2FACTION%24execute%22%2C%22callingDescriptor%22%3A%22UNKNOWN%22%2C%22params%22%3A%7B%22namespace%22%3A%22%22%2C%22classname%22%3A%22ConfigurableLoginAndMaintenanceMessages%22%2C%22method%22%3A%22getLoginMaintenanceMessage%22%2C%22params%22%3A%7B%22displayTo%22%3A%22Job%20Seekers%22%2C%22messageType%22%3A%22Portal%20Login%20Messages%22%7D%2C%22cacheable%22%3Afalse%2C%22isContinuation%22%3Afalse%7D%7D%2C%7B%22id%22%3A%22161%3Ba%22%2C%22descriptor%22%3A%22aura%3A%2F%2FApexActionController%2FACTION%24execute%22%2C%22callingDescriptor%22%3A%22UNKNOWN%22%2C%22params%22%3A%7B%22namespace%22%3A%22%22%2C%22classname%22%3A%22OESC_JS_getWARNLayoffNotices%22%2C%22method%22%3A%22getListofLayoffAccService%22%2C%22cacheable%22%3Afalse%2C%22isContinuation%22%3Afalse%7D%7D%5D%7D&aura.context=%7B%22mode%22%3A%22PROD%22%2C%22fwuid%22%3A%22eE5UbjZPdVlRT3M0d0xtOXc5MzVOQWg5TGxiTHU3MEQ5RnBMM0VzVXc1cmcxMi42MjkxNDU2LjE2Nzc3MjE2%22%2C%22app%22%3A%22siteforce%3AcommunityApp%22%2C%22loaded%22%3A%7B%22APPLICATION%40markup%3A%2F%2Fsiteforce%3AcommunityApp%22%3A%221305_7pTC6grCTP7M16KdvDQ-Xw%22%7D%2C%22dn%22%3A%5B%5D%2C%22globals%22%3A%7B%7D%2C%22uad%22%3Atrue%7D&aura.pageURI=%2FParticipants%2Fs%2Fwarnnotices&aura.token=null"
67
+
68
+ logger.debug(f"Attempting to send hard-coded data to {posturl}")
69
+ r = requests.post(posturl, headers=headers, data=payload)
70
+ rawdata = r.json()
71
+
72
+ for entry in rawdata["actions"]:
73
+ if (
74
+ entry["id"] == "161;a"
75
+ ): # What is this value? Will this change? Also no idea.
76
+ cleanerdata = entry["returnValue"]["returnValue"]
77
+ """
78
+ fields = set()
79
+ for entry in cleanerdata:
80
+ for field in entry:
81
+ fields.add(field)
82
+ {'Id',
83
+ 'Launchpad__Layoff_Closure_Type__c',
84
+ 'Launchpad__Notice_Date__c',
85
+ 'OESC_Employer_City__c',
86
+ 'OESC_Employer_Name__c',
87
+ 'OESC_Employer_Zip_Code__c',
88
+ 'RecordTypeId',
89
+ 'Select_Local_Workforce_Board__c'}
90
+ """
91
+ fields = {
92
+ "Id": "id",
93
+ "Launchpad__Layoff_Closure_Type__c": "closure_type",
94
+ "Launchpad__Notice_Date__c": "notice_date",
95
+ "OESC_Employer_City__c": "city",
96
+ "OESC_Employer_Name__c": "company name",
97
+ "OESC_Employer_Zip_Code__c": "zip_code",
98
+ "RecordTypeId": "record_type_id",
99
+ "Select_Local_Workforce_Board__c": "workforce_board",
100
+ }
101
+
102
+ masterlist = []
103
+ for entry in cleanerdata:
104
+ line = {}
105
+ for item in fields:
106
+ if item in entry:
107
+ line[fields[item]] = entry[item]
108
+ else:
109
+ line[fields[item]] = None
110
+ masterlist.append(line)
111
+
112
+ utils.write_dict_rows_to_csv(output_csv, list(fields.values()), masterlist)
38
113
  return output_csv
39
114
 
40
115
 
warn/utils.py CHANGED
@@ -1,7 +1,9 @@
1
1
  import csv
2
+ import json
2
3
  import logging
3
4
  import os
4
5
  import typing
6
+ from base64 import b64decode, b64encode
5
7
  from pathlib import Path
6
8
  from time import sleep
7
9
 
@@ -94,6 +96,103 @@ def save_if_good_url(filename, url, **kwargs):
94
96
  return success_flag, content
95
97
 
96
98
 
99
+ def get_with_zyte(url):
100
+ """Use Zyte as a proxy server to retrieve data not available without it.
101
+
102
+ Args:
103
+ url (str): URL to retrieve
104
+ Returns:
105
+ returnbin (bin): raw binary representation of returned data object
106
+ returntext (str): utf-8 conversion of returned data object, e.g., HTML
107
+ Failures:
108
+ Returns (None, None) if it encounters a problem and logs an error.
109
+ Requires:
110
+ ZYTE_API_KEY to be set in environment
111
+ """
112
+ logger.debug(f"Seeking to fetch {url} with Zyte")
113
+ try:
114
+ zyte_api_key = os.environ["ZYTE_API_KEY"]
115
+ except KeyError:
116
+ logger.error(
117
+ "No ZYTE_API_KEY variable found in environment. Please get an API key from Zyte and export it."
118
+ )
119
+ return (None, None)
120
+
121
+ api_response = requests.post(
122
+ "https://api.zyte.com/v1/extract",
123
+ auth=(zyte_api_key, ""),
124
+ json={
125
+ "url": url,
126
+ "httpResponseBody": True,
127
+ "followRedirect": True,
128
+ },
129
+ )
130
+
131
+ if not api_response.ok:
132
+ logger.error(
133
+ f"Error downloading {url} with get_with_zyte. Repsonse code: {api_response.status_code}"
134
+ )
135
+ return (None, None)
136
+ returnbin: bytes = b64decode(api_response.json()["httpResponseBody"])
137
+ returntext: str = returnbin.decode("utf-8", errors="backslashreplace")
138
+ logger.debug(f"Fetched {url}")
139
+ return (returnbin, returntext)
140
+
141
+
142
+ def post_with_zyte(url, payload):
143
+ """Use Zyte as a proxy server to retrieve data not available without it.
144
+
145
+ Args:
146
+ url (str): URL to retrieve
147
+ payload: (dict, str or binary): POST body.
148
+ If type dict: Convert to utf-8 text then:
149
+ If type str: Convert to b64encoded
150
+ Returns:
151
+ returnbin (bin): raw binary representation of returned data object
152
+ returntext (str): utf-8 conversion of returned data object, e.g., HTML
153
+ Failures:
154
+ Returns (None, None) if it encounters a problem and logs an error.
155
+ Requires:
156
+ ZYTE_API_KEY to be set in environment
157
+ """
158
+ logger.debug(f"Seeking to fetch {url} with Zyte")
159
+ try:
160
+ zyte_api_key = os.environ["ZYTE_API_KEY"]
161
+ except KeyError:
162
+ logger.error(
163
+ "No ZYTE_API_KEY variable found in environment. Please get an API key from Zyte and export it."
164
+ )
165
+ return (None, None)
166
+
167
+ if isinstance(payload, dict):
168
+ payload = json.dumps(payload)
169
+
170
+ if isinstance(payload, str):
171
+ payload = b64encode(payload.encode("utf-8"))
172
+
173
+ api_response = requests.post(
174
+ "https://api.zyte.com/v1/extract",
175
+ auth=(zyte_api_key, ""),
176
+ json={
177
+ "url": url,
178
+ "httpRequestMethod": "POST",
179
+ "httpRequestBody": payload,
180
+ "httpResponseBody": True,
181
+ "followRedirect": True,
182
+ },
183
+ )
184
+
185
+ if not api_response.ok:
186
+ logger.error(
187
+ f"Error downloading {url} with post_with_zyte. Repsonse code: {api_response.status_code}. Reponse: {api_response.json()}"
188
+ )
189
+ return (None, None)
190
+ returnbin: bytes = b64decode(api_response.json()["httpResponseBody"])
191
+ returntext: str = returnbin.decode("utf-8", errors="backslashreplace")
192
+ logger.debug(f"Fetched {url}")
193
+ return (returnbin, returntext)
194
+
195
+
97
196
  def write_rows_to_csv(output_path: Path, rows: list, mode="w"):
98
197
  """Write the provided list to the provided path as comma-separated values.
99
198
 
@@ -109,21 +208,19 @@ def write_rows_to_csv(output_path: Path, rows: list, mode="w"):
109
208
  writer.writerows(rows)
110
209
 
111
210
 
112
- def write_dict_rows_to_csv(
113
- output_path, headers, rows, mode="w", extrasaction="raise", encoding="utf-8"
114
- ):
115
- """Write the provided dictionary to the provided path as comma-separated values.
211
+ def write_dict_rows_to_csv(output_path, headers, rows, mode="w", extrasaction="raise"):
212
+ """Write the provided list of dictionaries to the provided path as comma-separated values.
116
213
 
117
214
  Args:
118
215
  output_path (Path): the Path were the result will be saved
119
216
  headers (list): a list of the headers for the output file
120
- rows (list): the dict to be saved
217
+ rows (list): the list of dictionaries to be saved
121
218
  mode (str): the mode to be used when opening the file (default 'w')
122
219
  extrasaction (str): what to do if the if a field isn't in the headers (default 'raise')
123
220
  """
124
221
  create_directory(output_path, is_file=True)
125
222
  logger.debug(f"Writing {len(rows)} rows to {output_path}")
126
- with open(output_path, mode, newline="", encoding=encoding) as f:
223
+ with open(output_path, mode, newline="") as f:
127
224
  # Create the writer object
128
225
  writer = csv.DictWriter(f, fieldnames=headers, extrasaction=extrasaction)
129
226
  # If we are writing a new row ...
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warn-scraper
3
- Version: 1.2.112
3
+ Version: 1.2.114
4
4
  Summary: Command-line interface for downloading WARN Act notices of qualified plant closings and mass layoffs from state government websites
5
5
  Home-page: https://github.com/biglocalnews/warn-scraper
6
6
  Author: Big Local News
@@ -17,11 +17,11 @@ warn/__init__.py,sha256=A07JFY1TyaPtVIndBa7IvTk13DETqIkLgRdk0A-MCoE,85
17
17
  warn/cache.py,sha256=hyta04_G-ALGwcKl4xNc7EgHS_xklyVD5d8SXNrJekY,5520
18
18
  warn/cli.py,sha256=ZqyJwICdHFkn2hEgbArj_upbElR9-TSDlYDqyEGeexE,2019
19
19
  warn/runner.py,sha256=oeGRybGwpnkQKlPzRMlKxhsDt1GN4PZoX-vUwrsPgos,1894
20
- warn/utils.py,sha256=SKwD4P2v2dlzix_zEqb98ZYe-E98Pa0xXxzUFt3rwYY,7087
20
+ warn/utils.py,sha256=Jd1pIVtfUXxDweKa_6vHTNX13E47Ms7FHSw110unDHk,10408
21
21
  warn/platforms/__init__.py,sha256=wIZRDf4tbTuC8oKM4ZrTAtwNgbtMQGzPXMwDYCFyrog,81
22
22
  warn/platforms/job_center/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  warn/platforms/job_center/cache.py,sha256=yhA3sE46lNFg8vEewSoRYVByi0YSlkBiKm7qoSUiTdM,1868
24
- warn/platforms/job_center/site.py,sha256=Voo2PG2YC_kbAa6RUoBiqVBEoOCzIZ8imGko45KBWuY,10207
24
+ warn/platforms/job_center/site.py,sha256=J_J6WYrfrdP9AyOuRJ8Myg_Gh5aB3-lxxp_-PBuB_A4,10236
25
25
  warn/platforms/job_center/urls.py,sha256=IWhpuzN_xcNdHh23GbZPGvuHCsMcmb03qx3pRn1Gy-k,414
26
26
  warn/platforms/job_center/utils.py,sha256=HdUKgKirmpPP7e4Cu_ZyB3zPVS_p-_ylo-lXFhxK2QM,5696
27
27
  warn/scrapers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -42,7 +42,7 @@ warn/scrapers/il.py,sha256=sygdvsNuB_Gvu3o_HidtpSP4FLz0szKb1zEHqGxVtlI,1563
42
42
  warn/scrapers/in.py,sha256=dAT40ROhhKiwLcwa_YJ6EyhsYBLe0IX2rOWXmNa6JMs,2026
43
43
  warn/scrapers/ks.py,sha256=F_3biEMF7zgCX2XVuUACR74Vyzapta4SaM9SY3EuZCU,1266
44
44
  warn/scrapers/ky.py,sha256=XjIojMpaoKbypa7l23IybP02jBijBCJG5UGqfO-EYjg,4365
45
- warn/scrapers/la.py,sha256=z2dCJ0obnKy47ZL21MrtKTo5AdexRDj0BBxyV2uIY_8,14340
45
+ warn/scrapers/la.py,sha256=ORkMOQErl33SEiagOli4agDLdTt0R1MxxBmqOg3hNv8,13175
46
46
  warn/scrapers/md.py,sha256=hwgxXQnhyBWm8qF1dvxIThAX1MkrZbXLwRI9inO5t8g,4060
47
47
  warn/scrapers/me.py,sha256=q36F4yJ7hvZsLayA3uBS1romo4X3Qf-sEi2Y7LAQCi8,1172
48
48
  warn/scrapers/mi.py,sha256=9clZ9mATEJwdVLzDo_h66rK0aV5Zc7GGQ7AauutS6Wo,3591
@@ -53,7 +53,7 @@ warn/scrapers/nj.py,sha256=nwbMbeQuUJbYRVoyUyKZBmNqvqsXu3Habt-10r8DvZE,2230
53
53
  warn/scrapers/nm.py,sha256=HZpfLzn0LvLeRztYvqJ9n6FR5PYpyMndo8tzI8h9S2o,3581
54
54
  warn/scrapers/ny.py,sha256=hXbxPhiK-Eyc9h_05wkAsfdVIT0vayKX4EE5aiJVdBc,2291
55
55
  warn/scrapers/oh.py,sha256=2MEB_0AT37dsAsrhdl_Y0LUNHu0xGy4B1F7aSMhuUu0,3151
56
- warn/scrapers/ok.py,sha256=qJE49VY6dMhbokFB9IAOL2XyuYSJpEKKxITPO9sUHS4,1197
56
+ warn/scrapers/ok.py,sha256=mn9NrhVzNo9ZFtYwBtSgBhPqevHWrz1Hs37gRRjwoSo,7640
57
57
  warn/scrapers/or.py,sha256=0PjyrW3CHdxtHhqEo3Ob-9B6YckACoBD3K0c4FPQUcg,5208
58
58
  warn/scrapers/ri.py,sha256=EUyLy59eNiYHqiJR8C0YcJrZtp09KyVc45AFD0_Uc0U,4497
59
59
  warn/scrapers/sc.py,sha256=p3kscSNSW9C8C5QaSUbCAo6XibgB7G2iH6zaMH7Mnsc,4819
@@ -65,9 +65,9 @@ warn/scrapers/va.py,sha256=7Nle7qL0VNPiE653XyaP9HQqSfuJFDRr2kEkjOqLvFM,11269
65
65
  warn/scrapers/vt.py,sha256=d-bo4WK2hkrk4BhCCmLpEovcoZltlvdIUB6O0uaMx5A,1186
66
66
  warn/scrapers/wa.py,sha256=UXdVtHZo_a-XfoiyOooTRfTb9W3PErSZdKca6SRORgs,4282
67
67
  warn/scrapers/wi.py,sha256=ClEzXkwZbop0W4fkQgsb5oHAPUrb4luUPGV-jOKwkcg,4855
68
- warn_scraper-1.2.112.dist-info/licenses/LICENSE,sha256=ZV-QHyqPwyMuwuj0lI05JeSjV1NyzVEk8Yeu7FPtYS0,585
69
- warn_scraper-1.2.112.dist-info/METADATA,sha256=dHhKPqTbOMGVMZ_eDRMnQ1TEjaoBPvzdqHGPwyWDXsU,2385
70
- warn_scraper-1.2.112.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
71
- warn_scraper-1.2.112.dist-info/entry_points.txt,sha256=poh_oSweObGlBSs1_2qZmnTodlOYD0KfO7-h7W2UQIw,47
72
- warn_scraper-1.2.112.dist-info/top_level.txt,sha256=gOhHgNEkrUvajlzoKkVOo-TlQht9MoXnKOErjzqLGHo,11
73
- warn_scraper-1.2.112.dist-info/RECORD,,
68
+ warn_scraper-1.2.114.dist-info/licenses/LICENSE,sha256=ZV-QHyqPwyMuwuj0lI05JeSjV1NyzVEk8Yeu7FPtYS0,585
69
+ warn_scraper-1.2.114.dist-info/METADATA,sha256=wsOFbBrbNx2mb-YWlWVggvalyIbPnOreJVgTZ222jQY,2385
70
+ warn_scraper-1.2.114.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
71
+ warn_scraper-1.2.114.dist-info/entry_points.txt,sha256=poh_oSweObGlBSs1_2qZmnTodlOYD0KfO7-h7W2UQIw,47
72
+ warn_scraper-1.2.114.dist-info/top_level.txt,sha256=gOhHgNEkrUvajlzoKkVOo-TlQht9MoXnKOErjzqLGHo,11
73
+ warn_scraper-1.2.114.dist-info/RECORD,,