Skip to content

Instantly share code, notes, and snippets.

@fabiomadge
Last active August 28, 2016 20:06
Show Gist options
  • Save fabiomadge/8cd610b1c31a806d3e52f4e77c2fc909 to your computer and use it in GitHub Desktop.
Save fabiomadge/8cd610b1c31a806d3e52f4e77c2fc909 to your computer and use it in GitHub Desktop.
Watches www.hotwire.com hotel prices.
import http.client
import xml.etree.ElementTree as ET
import csv
import datetime
import os
import sys
import time
APIKEY = $APIKEY
OUTPUTFIELDS = ['timestamp', 'price']
CONFIGFIELDS = ['city', 'arrival', 'departure']
CONFIG = "config.csv"
INTERVAL = 10 * 60
# date: 07/04/2009 is July 4th 2009
def getStop(city, arrival, departure, deal):
conn = http.client.HTTPSConnection("api.hotwire.com")
conn.request("GET", "/v1/" + ("deal" if deal else "search") + "/hotel"
+ "?dest=" + str.replace(city, ' ', '%20') + "&distance=*~4"
+ "&startdate=" + arrival + "&enddate=" + departure
+ "&starrating=4~*"
# + "&hwpos=de"
# + "&recommendation=80~*"
# + "&sort=price"
+ "&rooms=1&adults=2&children=0"
+ "&apikey=" + APIKEY + "&limit=100")
return conn.getresponse().read().decode('utf-8')
def stringNode(node):
if node == None:
return "None"
else:
return str(node.text)
def amenityString(node):
ret = ""
for code in node:
ret += stringNode(code)
return ret
def lastPrice(filename):
try:
with open(filename, 'r', newline='') as f:
reader = csv.DictReader(f, fieldnames=OUTPUTFIELDS, dialect='excel')
next(reader)
cur = -1
for row in reader:
cur = int(float(row['price']))
return cur
except:
return -1
def handleStop(city, arrival, departure, deal):
xml = getStop(city, arrival, departure, deal)
try:
root = ET.fromstring(xml)
results = root[1 if deal else 2]
except:
print('parse failure ignored - ' + city + ', ' + arrival + ', ' + departure + ', ' + ('deal' if deal else 'search'))
print(xml)
return
dirstring = city + ',' + str.replace(arrival, '/', '_') + '-' + str.replace(departure, '/', '_')
if not os.path.exists(dirstring):
os.makedirs(dirstring)
for result in results:
ident = stringNode(result.find('NeighborhoodId')) + '_' + stringNode(result.find('StarRating')) + '_' + stringNode(result.find('RecommendationPercentage')) + '_' + ('D' if deal else amenityString(result.find('AmenityCodes')) + '_S')
filename = dirstring + '/' + ident + '.csv'
existed = os.path.isfile(filename)
PRICETAG = 'Price' if deal else 'SubTotal'
lastprice = lastPrice(filename)
newprice = int(float(result.find(PRICETAG).text))
if lastprice != newprice:
with open(filename, 'a', newline='') as f:
writer = csv.DictWriter(f, fieldnames=OUTPUTFIELDS, dialect='excel')
if not existed:
writer.writeheader()
writer.writerow({'timestamp': datetime.datetime.utcnow(), 'price': result.find(PRICETAG).text})
print(('new' if not existed else ('lower' if lastprice > newprice else 'higher')) + ' price in ' + filename)
def handleSearchStop(city, arrival, departure):
handleStop(city, arrival, departure, False)
def handleDealStop(city, arrival, departure):
handleStop(city, arrival, departure, True)
def totalRecrawl():
if not os.path.isfile(CONFIG):
with open(CONFIG, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=CONFIGFIELDS, dialect='excel')
writer.writeheader()
print("no config - file created")
sys.exit()
with open('config.csv', 'r', newline='') as f:
reader = csv.DictReader(f, fieldnames=CONFIGFIELDS, dialect='excel')
next(reader)
for row in reader:
handleSearchStop(row[CONFIGFIELDS[0]], row[CONFIGFIELDS[1]], row[CONFIGFIELDS[2]])
time.sleep(1)
handleDealStop(row[CONFIGFIELDS[0]], row[CONFIGFIELDS[1]], row[CONFIGFIELDS[2]])
time.sleep(1)
while True:
totalRecrawl()
time.sleep(INTERVAL)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment