Last active
January 25, 2020 23:25
-
-
Save kmatarese/21f9ec5a6b9a81d93caf3b9cc3fe4c8d to your computer and use it in GitHub Desktop.
A script that pulls campsite availability from recreation.gov and emails the result.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from datetime import datetime | |
from climax import PasswordPrompt | |
from fake_useragent import UserAgent | |
from glide import * | |
import pandas as pd | |
from tlbx import parse_date | |
BASE_URL = "https://www.recreation.gov" | |
AVAILABILITY_URL = BASE_URL + "/api/camps/availability/campground/{camp_id}" | |
BOOKING_URL = BASE_URL + "/camping/campgrounds/{camp_id}/availability" | |
def format_date(d): | |
return datetime.strftime(d, "%Y-%m-%dT00:00:00Z") | |
class GetCampData(URLExtract): | |
def run(self, camp_id, start_date, end_date): | |
print("---- {} {} -> {}".format(camp_id, start_date.date(), end_date.date())) | |
self.update_downstream_context(dict(camp_id=camp_id)) | |
super().run( | |
AVAILABILITY_URL.format(camp_id=camp_id), | |
data_type="json", | |
params=dict( | |
start_date=format_date(start_date), end_date=format_date(end_date) | |
), | |
headers={"User-Agent": UserAgent().random}, | |
) | |
class FilterAvailability(Node): | |
def run(self, data, site_name=None, site_type=None, **kwargs): | |
camp_id = kwargs["camp_id"] # context from upstream | |
sites = [] | |
available = {} | |
for site in data.get("campsites", {}).values(): | |
if site_name and site["site"] != site_name: | |
continue | |
if site_type and site["campsite_type"] != site_type: | |
continue | |
for date, status in site["availabilities"].items(): | |
if status == "Available": | |
sites.append( | |
dict( | |
date=date.split("T")[0], | |
site_name=site["site"], | |
site_type=site["campsite_type"], | |
) | |
) | |
print("{} sites available".format(len(sites))) | |
if sites: | |
available["camp_id"] = camp_id | |
available["url"] = BOOKING_URL.format(camp_id=camp_id) | |
available["sites"] = sites | |
self.push(available) | |
class FormatHTML(Node): | |
def run(self, data): | |
output = "" | |
for row in data: | |
output += "Camp ID: {camp_id}<br>URL: {url}<br>\n".format(**row) | |
df = pd.DataFrame.from_records(row["sites"]) | |
html_content = df.to_html(index=False) | |
output += html_content + "<br>\n" | |
if output: | |
self.push(output) | |
glider = Glider( | |
GetCampData("camp") | |
| FilterAvailability("filter") | |
| Reduce("reduce") | |
| FormatHTML("html") | |
| EmailLoad("email", subject="Camp Sites Available", attach_as="html") | |
) | |
@glider.cli( | |
Arg("glide_data", metavar="camp_id", nargs="+", type=int, help="Camp IDs"), | |
# All of these args already appear with node name prefixed by default, but | |
# adding them here for clarity and more concise names on the command line. | |
Arg("--start_date", required=True, type=parse_date, help="Start date [YYYY-MM-DD]"), | |
Arg("--end_date", required=True, type=parse_date, help="End date [YYYY-MM-DD]"), | |
# Note: could utilize glide's ConfigContext to read from a file instead | |
Arg("--host", required=True, help="Email host"), | |
Arg("--port", required=True, type=int, help="Email port to connect to"), | |
Arg("--frm", required=True, help="Email from address"), | |
Arg("--to", required=True, help="Email destination address(es), comma separated"), | |
Arg("--username", required=True, help="Email account username"), | |
Arg("password", action=PasswordPrompt, help="Email password"), | |
) | |
def main(glide_data, node_contexts, **kwargs): | |
glider.consume(glide_data, **node_contexts) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To run this script, install the following which should cover all dependencies:
$ pip install glide fake-useragent
The example below pulls availability for two popular sites in Yosemite from 6/1/2020 to 6/10/2020. The camp IDs are Recreation.gov's facility IDs that appear in the URL for a particular campground. Fill in the blanks for your email info. You will be prompted for your password. The "frm" param will likely be the same as the "username".
$ python glide_campsite_example.py 232449 232447 --start_date 2020-06-01 --end_date 2020-06-10 --host smtp.gmail.com --port 587 --frm [email protected] --to [email protected] --username [email protected]
You could also easily adjust the script to set some values as defaults or read them from a config file to simplify the command line. More info on glide here.
NOTE: Please don't abuse this script or use it against the terms of recreation.gov.