![image](http://habr.habrastorage.org/post_images/5bc/c9d/e46/5bcc9de463f52e1591b33a6ba2bbb278.jpg)
Сначала я написал код, а потом задумался о хостинге, есстественно сайт не предполагал никакой наживы, а был лишь 4 fun, поэтому и хостинг должен быть бесплатным и тут я вспомнил про App Engine. Для начала работы стоит скачать SDK. Запускаем, указываем путь к будущему приложению:
![image](http://habr.habrastorage.org/post_images/8dc/528/292/8dc528292644b9def66c103ea8df6ee3.jpg)
В указанной рабочей директории сознаем файл настроек app.yaml содержащий примерно следующее:
application: rzdzstan1 version: 1 runtime: python27 threadsafe: false api_version: 1 handlers: - url: /favicon.ico static_files: favicon.ico upload: favicon.ico - url: /.* script: web.py libraries: - name: webapp2 version: "latest"
Дальше в вышеобозначенной рабочей директории создаем, web.py и тут уже можно начинать писать код копипастить. Приложение будем строить на легковесном WebApp2. Итак пишем основные обработчики:
import webapp2 application = webapp2.WSGIApplication([ ('/', MainPage), ('/trains', TrainListPage), ('/suggester', SuggesterPage), ], debug=True) def main(): application.run() if __name__ == "__main__": main()
Далее, как и говорилось в базовой статье, нам понадобятся коды городов для создания запроса:
def getCityId(city, s): req = 'http://pass.rzd.ru/suggester?lang=ru&stationNamePart=' + urllib.quote(city.encode('utf-8')) respData = getResponse(req) rJson = json.loads(respData) for item in rJson: if item['name'].lower() == city.lower(): s.response.out.write(u'Найден: '+item['name']+' -> '+str(item['id'])+'<br>') return str(item['id']) s.response.out.write(u'Не найден: '+city+'<br>') s.response.out.write(u'Выбранный вами город не найден, попробуйте найти в списке и ввести еще раз:<a href="../">Вернуться</a><br>') for item in rJson: s.response.out.write(item['name']+'<br>') return None
Ну а дальше остается получить rid, SESSION_ID и сформировать окончательный запрос, не забывая что часто РЖД рвет соединения, отвечает 500 кодом и т.д. чтобы это замаскировать напишем пару костылей-обработчиков:
def getResponse(url): good = False while not good: try: resp = opener.open(url, timeout=5) if resp.getcode() in [httplib.OK, httplib.CREATED, httplib.ACCEPTED]: good = True except (urllib2.HTTPError, HTTPException): pass return resp.read() def getResponseStub(url): r = json.loads(getResponse(url)) cnt = 0 while (r['result']!='OK' and cnt < 5): sleep(1) cnt+=1 r = json.loads(getResponse(url)) return r def getFinalRequest(): req1 = 'http://pass.rzd.ru/timetable/public/ru?STRUCTURE_ID=735&layer_id=5371&dir=0&tfl=3&checkSeats=1&\ st0='+st0+'&code0='+id0+'&dt0='+date+'&st1='+st1+'&code1='+id1+'&dt1='+date r = json.loads(getResponse(req1)) if (r['result']=='OK'): s.response.out.write(r['tp'][0]['msgList'][0]['message']) #errType s.response.out.write('<br>') return sid = str(r['SESSION_ID']) rid = str(r['rid']) req2 = 'http://pass.rzd.ru/timetable/public/ru?STRUCTURE_ID=735&layer_id=5371&dir=0&tfl=3&checkSeats=1&\ st0='+st0+'&code0='+id0+'&dt0='+date+'&st1='+st1+'&code1='+id1+'&dt1='+date+'&rid='+rid+'&SESSION_ID='+sid r = getResponseStub(req2)
И в получившемся ответе — лежит все необходимое для финального парсинга. Теперь о загадочном sleep, он переехал в функцию: getResponseStub, дело в том что когда мы запрашиваем req1 му таким образом просим поставить нас в очередь исполнения, и если сразу спросить req2 — результат может быть еще не получен. Радиоактивные исходники доступны тут качать осторожно. Попробовать в действии можно тут и тут ибо квоты там небольшие и под известным эффектом быстро закончатся, а пока эта статья проходит премодерацию попробую закинуть немного денег чтобы страница продержалась продолжительное время. В следующей части будем приделывать собственно саму нотификацию по емайлу.
ссылка на оригинал статьи http://habrahabr.ru/post/210420/
Добавить комментарий