warn-scraper 1.2.158.dev0__py3-none-any.whl → 1.2.160.dev0__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.
- warn/scrapers/fl.py +12 -11
- warn/scrapers/md.py +9 -0
- warn/scrapers/oh.py +23 -24
- {warn_scraper-1.2.158.dev0.dist-info → warn_scraper-1.2.160.dev0.dist-info}/METADATA +1 -1
- {warn_scraper-1.2.158.dev0.dist-info → warn_scraper-1.2.160.dev0.dist-info}/RECORD +11 -11
- warn_scraper-1.2.160.dev0.dist-info/scm_version.json +8 -0
- warn_scraper-1.2.158.dev0.dist-info/scm_version.json +0 -8
- {warn_scraper-1.2.158.dev0.dist-info → warn_scraper-1.2.160.dev0.dist-info}/WHEEL +0 -0
- {warn_scraper-1.2.158.dev0.dist-info → warn_scraper-1.2.160.dev0.dist-info}/entry_points.txt +0 -0
- {warn_scraper-1.2.158.dev0.dist-info → warn_scraper-1.2.160.dev0.dist-info}/licenses/LICENSE +0 -0
- {warn_scraper-1.2.158.dev0.dist-info → warn_scraper-1.2.160.dev0.dist-info}/scm_file_list.json +0 -0
- {warn_scraper-1.2.158.dev0.dist-info → warn_scraper-1.2.160.dev0.dist-info}/top_level.txt +0 -0
warn/scrapers/fl.py
CHANGED
|
@@ -9,6 +9,7 @@ import requests
|
|
|
9
9
|
import tenacity
|
|
10
10
|
import urllib3
|
|
11
11
|
from bs4 import BeautifulSoup
|
|
12
|
+
from pyquery import PyQuery as pq
|
|
12
13
|
|
|
13
14
|
from .. import utils
|
|
14
15
|
from ..cache import Cache
|
|
@@ -17,7 +18,8 @@ __authors__ = ["zstumgoren", "Dilcia19", "shallotly", "stucka"]
|
|
|
17
18
|
__tags__ = ["html", "pdf"]
|
|
18
19
|
__source__ = {
|
|
19
20
|
"name": "Florida Department of Economic Opportunity",
|
|
20
|
-
"url": "https://floridajobs.org/office-directory/division-of-workforce-services/workforce-programs/reemployment-and-emergency-assistance-coordination-team-react/warn-notices",
|
|
21
|
+
# "url": "https://floridajobs.org/office-directory/division-of-workforce-services/workforce-programs/reemployment-and-emergency-assistance-coordination-team-react/warn-notices",
|
|
22
|
+
"url": "https://floridajobs.org/workforce-resources/worker-adjustment-and-retraining-notification-(warn)",
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
logger = logging.getLogger(__name__)
|
|
@@ -53,25 +55,24 @@ def scrape(
|
|
|
53
55
|
headers = {
|
|
54
56
|
"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"
|
|
55
57
|
}
|
|
56
|
-
url = "https://floridajobs.org/office-directory/division-of-workforce-services/workforce-programs/reemployment-and-emergency-assistance-coordination-team-react/warn-notices"
|
|
58
|
+
# url = "https://floridajobs.org/office-directory/division-of-workforce-services/workforce-programs/reemployment-and-emergency-assistance-coordination-team-react/warn-notices"
|
|
59
|
+
url = "https://floridajobs.org/workforce-resources/worker-adjustment-and-retraining-notification-(warn)"
|
|
57
60
|
response = requests.get(url, headers=headers, verify=True)
|
|
58
61
|
logger.debug(f"Request status is {response.status_code} for {url}")
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
pagesection = pageholder.select("div.sfContentBlock")[0]
|
|
62
|
+
html = response.text
|
|
63
|
+
details = pq(html)("div.contact-details")
|
|
62
64
|
href_lookup = {}
|
|
63
|
-
for
|
|
64
|
-
|
|
65
|
+
for link in pq(details)("a.externalIcon"):
|
|
66
|
+
# logger.debug(pq(link))
|
|
67
|
+
href = pq(link)("a").attr("href")
|
|
65
68
|
tagyear = href[-4:]
|
|
66
|
-
if tagyear not in ["orts"]:
|
|
69
|
+
if tagyear not in ["orts"]: # exclude "reports"
|
|
67
70
|
href_lookup[tagyear] = href
|
|
68
71
|
|
|
69
|
-
# logger.debug(href_lookup)
|
|
70
|
-
# logger.debug(pagesection)
|
|
71
|
-
|
|
72
72
|
base_url = "https://reactwarn.floridajobs.org/WarnList/"
|
|
73
73
|
|
|
74
74
|
# Loop through years and add any missing to the lookup
|
|
75
|
+
# logger.debug(href_lookup.keys())
|
|
75
76
|
most_recent_year = int(list(href_lookup.keys())[0])
|
|
76
77
|
earliest_year = 2015 # We expected files to be available for at least 2015
|
|
77
78
|
for year in range(earliest_year, most_recent_year):
|
warn/scrapers/md.py
CHANGED
|
@@ -61,6 +61,8 @@ def scrape(
|
|
|
61
61
|
html_list.append(html) # Save the source HTML for parsing also
|
|
62
62
|
|
|
63
63
|
old_pages = [
|
|
64
|
+
"warn2025.shtml",
|
|
65
|
+
"warn2024.shtml",
|
|
64
66
|
"warn2023.shtml",
|
|
65
67
|
"warn2022.shtml",
|
|
66
68
|
"warn2021.shtml",
|
|
@@ -83,6 +85,7 @@ def scrape(
|
|
|
83
85
|
filename = f"md/{href}.html"
|
|
84
86
|
|
|
85
87
|
if href not in old_pages:
|
|
88
|
+
logger.debug(f"Trying special handling on {href}")
|
|
86
89
|
sleep(naptime) # Try to stop blocked connections by being less aggressive
|
|
87
90
|
r = utils.get_url(url, headers=request_headers, verify=request_verify)
|
|
88
91
|
r.encoding = "utf-8"
|
|
@@ -116,6 +119,8 @@ def scrape(
|
|
|
116
119
|
row_list = table.find_all("tr")
|
|
117
120
|
|
|
118
121
|
# If it's not the first page, slice off the header
|
|
122
|
+
if i == 0:
|
|
123
|
+
logger.debug(f"Found possible header row: {row_list[0]}")
|
|
119
124
|
if i > 0:
|
|
120
125
|
row_list = row_list[1:]
|
|
121
126
|
|
|
@@ -123,6 +128,10 @@ def scrape(
|
|
|
123
128
|
for row in row_list:
|
|
124
129
|
# Get the cells
|
|
125
130
|
cell_list = row.find_all("td")
|
|
131
|
+
if not cell_list:
|
|
132
|
+
cell_list = row.find_all(
|
|
133
|
+
"th"
|
|
134
|
+
) # Alternate approach for first page's header
|
|
126
135
|
|
|
127
136
|
# Clean them up
|
|
128
137
|
cell_list = [_clean_text(c.text) for c in cell_list]
|
warn/scrapers/oh.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import csv
|
|
2
|
-
import json
|
|
3
2
|
import logging
|
|
3
|
+
import re
|
|
4
|
+
from io import StringIO
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
|
|
6
7
|
import requests
|
|
7
|
-
from bs4 import BeautifulSoup, Tag
|
|
8
8
|
|
|
9
9
|
from .. import utils
|
|
10
|
+
from ..cache import Cache
|
|
10
11
|
|
|
11
12
|
__authors__ = ["zstumgoren", "Dilcia19", "chriszs", "stucka"]
|
|
12
13
|
__tags__ = ["html", "pdf"]
|
|
@@ -32,6 +33,7 @@ def scrape(
|
|
|
32
33
|
Returns: the Path where the file is written
|
|
33
34
|
"""
|
|
34
35
|
state_code = "oh"
|
|
36
|
+
cache = Cache()
|
|
35
37
|
|
|
36
38
|
# Get the latest HTML
|
|
37
39
|
headers = {
|
|
@@ -39,29 +41,26 @@ def scrape(
|
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
# latesturl = "https://jfs.ohio.gov/wps/portal/gov/jfs/job-services-and-unemployment/job-services/job-programs-and-services/submit-a-warn-notice/current-public-notices-of-layoffs-and-closures-sa/current-public-notices-of-layoffs-and-closures"
|
|
42
|
-
latesturl = "https://jfs.ohio.gov/job-services-and-unemployment/job-services/job-programs-and-services/submit-a-warn-notice/current-public-notices-of-layoffs-and-closures-sa"
|
|
43
|
-
|
|
44
|
+
# latesturl = "https://jfs.ohio.gov/job-services-and-unemployment/job-services/job-programs-and-services/submit-a-warn-notice/current-public-notices-of-layoffs-and-closures-sa"
|
|
45
|
+
latesturl = "https://jfs.ohio.gov/job-workforce-services/job-programs-and-services/submit-a-warn-notice/current-public-notices-of-layoffs-and-closures"
|
|
44
46
|
logger.debug(f"Attempting to fetch current data from {latesturl}")
|
|
45
47
|
r = requests.get(latesturl, headers=headers)
|
|
46
|
-
|
|
47
|
-
logger.debug("Attempting to get
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if item != "":
|
|
63
|
-
line[item] = row[i]
|
|
64
|
-
masterlist.append(line)
|
|
48
|
+
cache.write("oh/index.html", r.text)
|
|
49
|
+
logger.debug("Attempting to get CSV link from Ohio file")
|
|
50
|
+
html = r.text
|
|
51
|
+
csv_url = re.findall(r"(\\\"csvUrl\\\":\\\")(.*?)(\\\")", html)[0][1]
|
|
52
|
+
logger.debug(f"CSV link found at {csv_url}")
|
|
53
|
+
r = requests.get(csv_url, headers=headers)
|
|
54
|
+
cache.write("oh/rawdata.csv", r.text)
|
|
55
|
+
|
|
56
|
+
# Ohio CSV as of June 2026 was coming in with extra prefacing headers that ... make it not a CSV.
|
|
57
|
+
# So knock off any lines without useful data.
|
|
58
|
+
clean = []
|
|
59
|
+
for myline in r.text.splitlines():
|
|
60
|
+
if len(myline) > 20:
|
|
61
|
+
clean.append(myline)
|
|
62
|
+
|
|
63
|
+
masterlist = list(csv.DictReader(StringIO("\n".join(clean))))
|
|
65
64
|
|
|
66
65
|
logger.debug("Get historical data and meld it into current format")
|
|
67
66
|
# Get the historical data, and meld it into the same format
|
|
@@ -82,7 +81,7 @@ def scrape(
|
|
|
82
81
|
)
|
|
83
82
|
reader = list(csv.DictReader(r.text.splitlines()))
|
|
84
83
|
for row in reader:
|
|
85
|
-
line = {}
|
|
84
|
+
line: dict = {}
|
|
86
85
|
for item in lookup:
|
|
87
86
|
if not lookup[item]:
|
|
88
87
|
line[item] = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: warn-scraper
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.160.dev0
|
|
4
4
|
Summary: Command-line interface for downloading WARN Act notices of qualified plant closings and mass layoffs from state government websites
|
|
5
5
|
Author-email: Big Local News <biglocalnews@stanford.edu>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -20,7 +20,7 @@ warn/scrapers/co.py,sha256=83OdikIrWGxt22mlI-_zLSNqJg1NO5C2Xjm3FF6DPYY,18252
|
|
|
20
20
|
warn/scrapers/ct.py,sha256=PzRnrq91T2a5IzDWMh0GDxWVLXkN-BtHRIYbutjgQhw,2868
|
|
21
21
|
warn/scrapers/dc.py,sha256=p1_c7O2R3O-41DmvcLVUIRhQKUewvZZKkzWkBxytN5M,5165
|
|
22
22
|
warn/scrapers/de.py,sha256=GyM92A-lFwZAfRxgbO-sIWhRfmBEKirzchaPIv-u0o4,1364
|
|
23
|
-
warn/scrapers/fl.py,sha256=
|
|
23
|
+
warn/scrapers/fl.py,sha256=jxN7zhlSNgcpBcBB01M2RcYJzE8hUsmKg9zS8AHzWI4,9846
|
|
24
24
|
warn/scrapers/ga.py,sha256=2kYhuK0Q6tkwp56lTuOwIH7W5zX6KpYJkqsp5ehSdgc,10700
|
|
25
25
|
warn/scrapers/hi.py,sha256=pSplAP15_ZBfQtcywyErmvNcrk7u55TjZj_F0Nqw9L8,5660
|
|
26
26
|
warn/scrapers/ia.py,sha256=0kOh3EOsXtWYGl5kvwimwFZGpOlu5_qFWhM_-n1MLds,2048
|
|
@@ -30,7 +30,7 @@ warn/scrapers/in.py,sha256=0hOCdbUyls3xX7Q1z5OB6yCrXJFpsu2CmvfwRh9NTfY,2202
|
|
|
30
30
|
warn/scrapers/ks.py,sha256=F_3biEMF7zgCX2XVuUACR74Vyzapta4SaM9SY3EuZCU,1266
|
|
31
31
|
warn/scrapers/ky.py,sha256=7kJTNOzxChyXlcyBImmdwwmrczYksU8XNxbhQ2owmJs,9688
|
|
32
32
|
warn/scrapers/la.py,sha256=52i7ICYH0R7omFyu-kmKi_s-8Rhy0vaPjNIKlW_OMC8,6938
|
|
33
|
-
warn/scrapers/md.py,sha256=
|
|
33
|
+
warn/scrapers/md.py,sha256=Zjudr5X8-E3fjBXbOqnB830XEZqLznGzQbaJ5HSY0zQ,4425
|
|
34
34
|
warn/scrapers/me.py,sha256=q36F4yJ7hvZsLayA3uBS1romo4X3Qf-sEi2Y7LAQCi8,1172
|
|
35
35
|
warn/scrapers/mi.py,sha256=Ppyawp4nbzSBODuzDKeqnO9_9do5MFwK4Y_f3uc6blE,5846
|
|
36
36
|
warn/scrapers/mo.py,sha256=wnnwQAiVPwuheMqptMXZpyQdiKNghhKwTO-Bnh9oXoU,3492
|
|
@@ -40,7 +40,7 @@ warn/scrapers/ne.py,sha256=JawuGJ3tCKvMd-N-p03gnltB4rol4QUJshMk2oyMPO4,4143
|
|
|
40
40
|
warn/scrapers/nj.py,sha256=nwbMbeQuUJbYRVoyUyKZBmNqvqsXu3Habt-10r8DvZE,2230
|
|
41
41
|
warn/scrapers/nm.py,sha256=55kDh65uOc-uMO8wuxPHhHN4Aw8Di2Fx66JBds8f2Io,3694
|
|
42
42
|
warn/scrapers/ny.py,sha256=_nYoawIde4yYtk8-tMG3hekLlSlrKKqULmkBWOUoQJM,2586
|
|
43
|
-
warn/scrapers/oh.py,sha256
|
|
43
|
+
warn/scrapers/oh.py,sha256=kwHm1feWQwZRdWKnZbDm1c2wdYqNUHJ1myrK6uteyfU,3502
|
|
44
44
|
warn/scrapers/ok.py,sha256=ZZciyR1jPS4SzS2JSQwhJsDXP_VxA9UkEQvLpxzWzp4,7676
|
|
45
45
|
warn/scrapers/or.py,sha256=0PjyrW3CHdxtHhqEo3Ob-9B6YckACoBD3K0c4FPQUcg,5208
|
|
46
46
|
warn/scrapers/pa.py,sha256=j6cYZjKJUht2s829VPAbI2IRJazkqOwbwcVMAcItuIc,5410
|
|
@@ -54,11 +54,11 @@ warn/scrapers/va.py,sha256=7Nle7qL0VNPiE653XyaP9HQqSfuJFDRr2kEkjOqLvFM,11269
|
|
|
54
54
|
warn/scrapers/vt.py,sha256=d-bo4WK2hkrk4BhCCmLpEovcoZltlvdIUB6O0uaMx5A,1186
|
|
55
55
|
warn/scrapers/wa.py,sha256=UXdVtHZo_a-XfoiyOooTRfTb9W3PErSZdKca6SRORgs,4282
|
|
56
56
|
warn/scrapers/wi.py,sha256=ClEzXkwZbop0W4fkQgsb5oHAPUrb4luUPGV-jOKwkcg,4855
|
|
57
|
-
warn_scraper-1.2.
|
|
58
|
-
warn_scraper-1.2.
|
|
59
|
-
warn_scraper-1.2.
|
|
60
|
-
warn_scraper-1.2.
|
|
61
|
-
warn_scraper-1.2.
|
|
62
|
-
warn_scraper-1.2.
|
|
63
|
-
warn_scraper-1.2.
|
|
64
|
-
warn_scraper-1.2.
|
|
57
|
+
warn_scraper-1.2.160.dev0.dist-info/licenses/LICENSE,sha256=ZV-QHyqPwyMuwuj0lI05JeSjV1NyzVEk8Yeu7FPtYS0,585
|
|
58
|
+
warn_scraper-1.2.160.dev0.dist-info/METADATA,sha256=eHYbY-2hpPWQAbxPEdBufp79t3vSb1e0gE0WPRKAtMY,1780
|
|
59
|
+
warn_scraper-1.2.160.dev0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
60
|
+
warn_scraper-1.2.160.dev0.dist-info/entry_points.txt,sha256=poh_oSweObGlBSs1_2qZmnTodlOYD0KfO7-h7W2UQIw,47
|
|
61
|
+
warn_scraper-1.2.160.dev0.dist-info/scm_file_list.json,sha256=SBROd7oEfcspIMl6v7yfGzQd2rkWxybkiIXopuTQVL0,4120
|
|
62
|
+
warn_scraper-1.2.160.dev0.dist-info/scm_version.json,sha256=BlfOZmrMfTxErAqmqWjuNwb0FtN0WDp9xyU4qysIay8,161
|
|
63
|
+
warn_scraper-1.2.160.dev0.dist-info/top_level.txt,sha256=dZfms6N3kqVXufiPOo7YqOrAcUtYfNH_oyGvYUk9FB4,5
|
|
64
|
+
warn_scraper-1.2.160.dev0.dist-info/RECORD,,
|
|
File without changes
|
{warn_scraper-1.2.158.dev0.dist-info → warn_scraper-1.2.160.dev0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{warn_scraper-1.2.158.dev0.dist-info → warn_scraper-1.2.160.dev0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{warn_scraper-1.2.158.dev0.dist-info → warn_scraper-1.2.160.dev0.dist-info}/scm_file_list.json
RENAMED
|
File without changes
|
|
File without changes
|