|
| 1 | +#!/usr/bin/env python |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | +__date__= ' 7 05, 2016 ' |
| 4 | +__author__= 'mkfsn' |
| 5 | + |
| 6 | + |
| 7 | +from re import sub |
| 8 | +import requests |
| 9 | +from pyquery import PyQuery |
| 10 | +from datetime import datetime |
| 11 | + |
| 12 | + |
| 13 | +class ToyokoInn(object): |
| 14 | + |
| 15 | + def __init__(self, name): |
| 16 | + self.name = name |
| 17 | + |
| 18 | + |
| 19 | +def fetch(year, month, day, member=False): |
| 20 | + # Results of dates. {DATE: {ROOM: {member: PRICE, guest: PRICE}}} |
| 21 | + results = {} |
| 22 | + |
| 23 | + s = requests.session() |
| 24 | + |
| 25 | + url = "https://yoyaku.4and5.com/reserve/html/rvpc_srchHtl.html?htlDtl=true&cntry=JPN&chcknYearAndMnth={year}{month}&chcknDayOfMnth={day}&ldgngNum=1&roomNum=1&roomClssId=&fvrtName=&prfctr=35&htlName=%E5%BE%B3%E5%B1%B1%E9%A7%85%E6%96%B0%E5%B9%B9%E7%B7%9A%E5%8F%A3&language=ja&dispFull=on&ldgngPpl=1&id=131&ref=info&_ga=1.151929791.720274849.1467717947".format(year=year, month=month, day=day) |
| 26 | + |
| 27 | + headers = { |
| 28 | + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36', |
| 29 | + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', |
| 30 | + 'Accept-Encoding': 'gzip, deflate, sdch, br', |
| 31 | + 'Accept-Language': 'zh-TW,zh;q=0.8,en-US;q=0.6,en;q=0.4,ja;q=0.2', |
| 32 | + } |
| 33 | + |
| 34 | + # session GET |
| 35 | + r = s.get(url, headers=headers) |
| 36 | + |
| 37 | + url = 'https://yoyaku.4and5.com/reserve/html/rvpc_srchHtl.html' |
| 38 | + data = { |
| 39 | + 'rg.seasar.ymir.token': '89dbd02e37b4597e8862423dc09a4c0d', |
| 40 | + 'language': '', |
| 41 | + 'htlUid': '', |
| 42 | + 'srchRoomAllFlag': 'true', |
| 43 | + 'srchRoomBasicFlag': 'false', |
| 44 | + 'srchRoomPlanFlag': 'false', |
| 45 | + 'tabGrpCode': 'ALL', |
| 46 | + 'langFlag': 'ja', |
| 47 | + 'dsplLinkPnt': '', |
| 48 | + 'hospital': '', |
| 49 | + 'cntry': 'JPN', |
| 50 | + 'prfctr': '35', |
| 51 | + 'mncplty': '', |
| 52 | + 'clsstSttn': '', |
| 53 | + 'htlName': '徳山駅新幹線口', |
| 54 | + 'chcknYearAndMnth': '%s%s' % (year, month), |
| 55 | + 'chcknDayOfMnth': '%s' % day, |
| 56 | + 'ldgngNum': '1', |
| 57 | + 'ldgngPpl': '2', |
| 58 | + 'roomNum': '2', |
| 59 | + 'dispFull': 'on', |
| 60 | + } |
| 61 | + |
| 62 | + # session POST |
| 63 | + r = s.post(url, headers=headers, data=data, allow_redirects=False) |
| 64 | + |
| 65 | + url = 'https://yoyaku.4and5.com/reserve/html/rvpc_srchHtl.html?clndr[6000136][][6000136][][20071001]' |
| 66 | + r = s.post(url, headers=headers, data=data) |
| 67 | + |
| 68 | + html = r.text.encode('utf-8') |
| 69 | + pq = PyQuery(html).find("form div.BlockFormClndr table.BlockSrchClndr3") |
| 70 | + |
| 71 | + date_order = [PyQuery(th).text() for th in PyQuery(pq).find("tr:eq(11) th")] |
| 72 | + results = {PyQuery(th).text(): {} for th in PyQuery(pq).find("tr:eq(11) th")} |
| 73 | + |
| 74 | + index = 9 |
| 75 | + while index < 100: |
| 76 | + room = PyQuery(pq).children("tbody > tr:eq(%d) th:eq(0)" % index).text() |
| 77 | + if room == '': |
| 78 | + break |
| 79 | + for date, v in results.items(): |
| 80 | + results[date][room] = {'member': [], 'guest': []} |
| 81 | + |
| 82 | + i_ = 0 |
| 83 | + for td in PyQuery(pq).children("tbody > tr:eq(%d) > td:gt(0)" % index): |
| 84 | + item = PyQuery(td).find("table > tbody div tr:eq(1)") |
| 85 | + price = sub(r'[^\d.]', '', PyQuery(item).find("td > span").text()[1:]) |
| 86 | + remain = PyQuery(item).find("td + td + td").text() |
| 87 | + remain = 0 if remain == u'\xd7' or remain == '' else int(remain) |
| 88 | + |
| 89 | + results[date_order[i_]][room]['member'] = [price, remain] |
| 90 | + i_ += 1 |
| 91 | + |
| 92 | + i_ = 0 |
| 93 | + for td in PyQuery(pq).children("tbody > tr:eq(%d) > td:gt(0)" % (index + 2)): |
| 94 | + item = PyQuery(td).find("table > tbody div tr:eq(1)") |
| 95 | + price = sub(r'[^\d.]', '', PyQuery(item).find("td > span").text()[1:]) |
| 96 | + remain = PyQuery(item).find("td + td + td").text() |
| 97 | + remain = 0 if remain == u'\xd7' or remain == '' else int(remain) |
| 98 | + |
| 99 | + results[date_order[i_]][room]['guest'] = [price, remain] |
| 100 | + i_ += 1 |
| 101 | + index += 3 |
| 102 | + |
| 103 | + # List all |
| 104 | + # for date, _item in results.items(): |
| 105 | + # for room, item in results[date].items(): |
| 106 | + # price, remain = item['member'] if member else item['guest'] |
| 107 | + # if remain == 0: |
| 108 | + # continue |
| 109 | + # print date, room, price, remain |
| 110 | + |
| 111 | + retval = [] |
| 112 | + for room, item in results['%s/%s' % (int(month), int(day))].items(): |
| 113 | + price, remain = item['member'] if member else item['guest'] |
| 114 | + if remain == 0: |
| 115 | + continue |
| 116 | + retval.append('%s %s %s' % (room, price, remain)) |
| 117 | + return retval |
| 118 | + |
| 119 | + |
| 120 | +if __name__ == '__main__': |
| 121 | + import argparse, json, os, sys |
| 122 | + |
| 123 | + parser = argparse.ArgumentParser(description='Fetch ToyokoINN reservable room') |
| 124 | + parser.add_argument('--year', type=int, required=True, help='Specify year of date') |
| 125 | + parser.add_argument('--month', type=int, choices=xrange(1, 13), required=True, help='Specify month of date') |
| 126 | + parser.add_argument('--day', type=int, choices=xrange(1, 32), required=True, help='Specify day of date') |
| 127 | + |
| 128 | + args = parser.parse_args() |
| 129 | + if datetime.now() > datetime(args.year, args.month, args.day, 23, 59, 59): |
| 130 | + sys.exit(-1) |
| 131 | + |
| 132 | + year, month, day = [args.year, '%02d' % args.month, '%02d' % args.day] |
| 133 | + result = fetch(year, month, day, member=True) |
| 134 | + |
| 135 | + title = "徳山駅新幹線口-%s-%s-%s" % (year, month, day) |
| 136 | + |
| 137 | + changed = False |
| 138 | + |
| 139 | + filename = '/tmp/%s' % title |
| 140 | + if not os.path.isfile(filename): |
| 141 | + with open(filename, 'w') as f: |
| 142 | + changed = True |
| 143 | + f.write(json.dumps(result)) |
| 144 | + else: |
| 145 | + with open(filename, 'r+') as f: |
| 146 | + previous = f.read() |
| 147 | + if previous != json.dumps(result): |
| 148 | + changed = True |
| 149 | + f.seek(0) |
| 150 | + f.write(json.dumps(result)) |
| 151 | + |
| 152 | + if not changed: |
| 153 | + sys.exit(0) |
| 154 | + |
| 155 | + content = '[%s]\n%s' % (title.decode('utf-8'), '\n'.join(result)) |
| 156 | + data = { |
| 157 | + 'username': 'ToyokoINN-bot', |
| 158 | + 'text': content, |
| 159 | + 'channel': 'toyokoinn', |
| 160 | + } |
| 161 | + slack_url = 'https://hooks.slack.com/services/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' |
| 162 | + requests.post(slack_url, data=json.dumps(data)) |
0 commit comments