Skip to content

Instantly share code, notes, and snippets.

@kobanyan
Created August 6, 2017 15:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kobanyan/888f1ca407290d9a4db37b57139ef4ea to your computer and use it in GitHub Desktop.
Save kobanyan/888f1ca407290d9a4db37b57139ef4ea to your computer and use it in GitHub Desktop.
Ploom の予約を受け付けている店舗を検索し、Slackで通知します。
# -*- coding: utf-8 -*-
"""
Ploom の予約を受け付けている店舗を検索し、Slackで通知します。
実行コマンドサンプル
SLACK_TOKEN=xoxp-xxxx... \
SLACK_CHANNEL_FOUND=@your_id \
SLACK_CHANNEL_LOG=@your_id \
SLACK_MENTION_ID=@UXXXXX \
PLOOM_ACCOUNTUID=id \
PLOOM_PASSWORD=password \
PLOOM_PREFECTURE=東京都 \
PLOOM_CITY=新宿区 \
PLOOM_SHOP='Ploom Shop 新宿三丁目店' \
python ploom.py
実行時に必要な環境変数
SLACK_TOKEN: Slack の token
SLACK_CHANNEL_FOUND: 店舗が見つかった時に送る Slack のチャンネル
SLACK_CHANNEL_LOG: 検索ログを送る Slack のチャンネル
SLACK_MENTION_ID: メッセージにつけるメンション
PLOOM_ACCOUNTUID: 「JTスモーカーズID」もしくはメールアドレス
PLOOM_PASSWORD: パスワード
PLOOM_PREFECTURE: 予約を受け付けている店舗がある都道府県(現状 '東京都' もしくは '福岡県' のみ)
任意指定の環境変数
PLOOM_CITY: 予約を受け付けている店舗がある市区町村('港区' などの市区町村名。未指定の場合には 'すべて選択' 扱い)
PLOOM_SHOP: 店舗を限定したい場合に店舗名を指定
実行に必要なpythonモジュール
pip install selene --pre
pip install slackclient
"""
import os
import traceback
from selene import config
from selene.browsers import BrowserName
from selene.api import *
from selenium import webdriver
from slackclient import SlackClient
SLACK_TOKEN = os.environ['SLACK_TOKEN']
SLACK_CHANNEL_LOG = os.environ['SLACK_CHANNEL_LOG']
SLACK_CHANNEL_FOUND = os.environ['SLACK_CHANNEL_FOUND']
SLACK_MENTION_ID = os.environ['SLACK_MENTION_ID']
PLOOM_ACCOUNTUID = os.environ['PLOOM_ACCOUNTUID']
PLOOM_PASSWORD = os.environ['PLOOM_PASSWORD']
PLOOM_PREFECTURE = os.environ['PLOOM_PREFECTURE']
PLOOM_CITY = os.getenv('PLOOM_CITY', 'すべて選択')
PLOOM_SHOP = os.getenv('PLOOM_SHOP', None)
SLACK_METHOD = 'chat.postMessage'
PLOOM_URL = 'https://www.ploom.jp/tech/reserve/'
def main():
"""
1. 検索開始を os.environ['SLACK_CHANNEL'] に通知
2. os.environ['PLOOM_ACCOUNTUID'] / os.environ['PLOOM_PASSWORD'] でログイン
3. os.environ['PLOOM_PREFECTURE'] 及び os.environ['PLOOM_CITY'] で検索
4. 検索結果を os.environ['SLACK_CHANNEL'] に通知
"""
slack_client = SlackClient(SLACK_TOKEN)
slack_client.api_call(
SLACK_METHOD,
channel=SLACK_CHANNEL_LOG,
text='Ploom の予約を受け付けている店舗を検索しています...\n都道府県 `{0}` 市区町村 `{1}` 店舗名 `{2}`'
.format(PLOOM_PREFECTURE, PLOOM_CITY, PLOOM_SHOP)
)
try:
# open ploom site
config.browser_name = BrowserName.PHANTOMJS
config.desired_capabilities = webdriver.DesiredCapabilities.PHANTOMJS
browser.open_url(PLOOM_URL)
# login
s('input[name="ACCOUNTUID"]').set_value(PLOOM_ACCOUNTUID)
s('input[name="PASSWORD"]').set_value(PLOOM_PASSWORD)
s('input[type="SUBMIT"]').click()
# confirm
s('input[type="checkbox"]').click()
s('input[type="submit"]').click()
# select prefecture
s(by.xpath('//label[text()="上記内容を確認しました"]')).click()
s(by.xpath('//label[text()="{0}"]'.format(PLOOM_PREFECTURE))).click()
s(by.xpath('//a[text()="予約を申し込む"]')).click()
# select city
s(by.xpath('//label[text()="{0}"]'.format(PLOOM_CITY))).click()
s(by.xpath('//a[text()="店舗選択へ"]')).click()
# list
message = None
if PLOOM_SHOP is None:
shops = ss(by.xpath('//a[contains(@class,"is-gold")]/../../..'))
if shops.size() > 0:
message = u'<{0}> 以下の店舗が予約を受け付けています。 :smile:\n'.format(SLACK_MENTION_ID)
for shop in shops:
shop_name = shop.s('h2.shop-name').text
shop_address = shop.s('p.address').text
message += u'店舗名: `{0}`, 住所: `{1}`\n'.format(shop_name, shop_address)
else:
xpath = '//h2[@class="shop-name"][text()="{0}"]/..//p[@class="submit"]/a[contains(@class,"is-gold")]'
# shop = s(by.xpath(xpath.format(PLOOM_SHOP)))
# if shop.is_displayed() is True: # is_displayed throws TimeoutException
shop = ss(by.xpath(xpath.format(PLOOM_SHOP)))
if shop.size() > 0:
message = '<{0}> '.format(SLACK_MENTION_ID)
message += '`{0}` が予約を受け付けています。 :smile:\n'.format(PLOOM_SHOP)
if message is None:
slack_client.api_call(
SLACK_METHOD,
channel=SLACK_CHANNEL_LOG,
text='検索条件に該当する店舗は予約を受け付けていませんでした。 :cry:'
)
else:
message += PLOOM_URL
slack_client.api_call(
SLACK_METHOD,
channel=SLACK_CHANNEL_FOUND,
text=message
)
slack_client.api_call(
SLACK_METHOD,
channel=SLACK_CHANNEL_LOG,
text='検索条件に該当する店舗が予約を受け付けています。 :smile:'
)
except:
slack_client.api_call(
SLACK_METHOD,
channel=SLACK_CHANNEL_LOG,
text='<{0}> 店舗検索に失敗しました。 :angry:\n```{1}```'
.format(SLACK_MENTION_ID, traceback.format_exc())
)
raise
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment