ワクチン予約のキャンセル通知システム作ってみた
目的!
- コロナワクチン予約をキャンセル待ちしたい!
使ったもの
やったこと
予約はいっぱいだったので、たまにキャンセルが出て一瞬予約できるっぽい > それを検知してみる! ワクチン予約サイトを定期的にチェックして、空きが出たらslackに通知する仕組みを作る!
準備
使った環境などを雑に並べる
ざっくり処理の抜粋&説明
※とりあえず通知まで行くために、エラー処理やsleep処理はだいぶ適当
headlessブラウザで実行
option = Options() option.add_argument('--headless') driver = webdriver.Chrome(chrome_driver_path, options=option) driver.get(target_url)
自分のワクチン番号&パスワードを使ってログイン(selenium)
number = driver.find_element_by_css_selector("input[type=\"tel\"]") number.send_keys(coupon_number) sleep(1) password = driver.find_element_by_css_selector("input[type=\"password\"]") password.send_keys(passwd) sleep(1) driver.find_element_by_css_selector("input[type=\"checkbox\"]").click() sleep(1) driver.find_element_by_css_selector("button[type=\"submit\"]").click() sleep(3)
予約サイトで予約可能な会場の件数を取得(速度はいらないので、そのままselenium)
driver.find_element_by_xpath("//*[text()=\" 新規予約\"]").click() sleep(1) driver.find_element_by_xpath("/html/body/div[1]/div/div[2]/div/div/button[1]").click() sleep(2) driver.find_element_by_css_selector("input[type=\"checkbox\"]").click(); sleep(3) element = driver.find_element_by_class_name("page-department-search_nav-header__count") result = re.sub(r"\D", "", element.text)
slack通知
- slackワークスペース設定で「Incoming Webhook」を追加してWebhookURLをコピー
- slackwebを使って通知(めっちゃ簡単に通知できた!)
import slackweb … slack = slackweb.Slack(url=slack_webhook_URL) if result != "0": print(result); slack.notify(text="<!channel> 空いてるよ!!!") else: print("空いてなかったよ")
定期実行
プログラムの定期実行はなんとなくmacのcrontabを利用!(1分ごとに実行) 通知が来たら素早く予約サイトにアクセスして予約完了!
詳細コードは↓ GitHub - kyamada23/covid19itami-vaccine-check
詰まったところなど
crontabの環境変数問題
crontabで定期実行するも全然動いてくれない。 crontabではPATHが全然通ってなくてpythonが動いていないっぽい ↓を参考に解決!
【保存版】cronでPython3を定時実行する方法&注意すべき4つのポイント | たぬハック
定期実行が途中で止まる問題
1回1回seleniumでブラウザを起動しっぱなしで、ブラウザが溜まり続けてたのが問題だった
ちゃんと終わりましょう
driver.quit()
↓参照
Selenium - かならずwebdriverを閉じる - Kobe's Public Scrapbox
感想
2,3時間で10件以上キャンセルは出てたっぽいので、F5アタックでも普通に予約できたかも。 でも作った通知システムで予約できたことですごい満足
ちなみに今回は伊丹市のワクチン予約サイトでしてみました。 ワクチン打つと伊丹消滅するらしい コロナワクチン予約システム
GoToEatひょうごが使える店をgoogle mapにしてみた(python/beautifulsoupでwebスクレイピング)
目的!
go to eatひょうごキャンペーンの食事券が使える店を地図で見たい! gotoeat-hyogo.com
webスクレイピングをやってみたい
どっちかというと2番目の目的が先で、何かないかなと思った時に1が出てきた感じです。 python(JupyterNotebook)を使って作ってみました。
出来たこと
go to eatひょうごキャンペーンの食事券が使える店の情報を読み込んで、google mapに読み込むcsvファイルを作成!
作ったgoogleマップがこちら↓ www.google.com
出来なかったこと
googleマップに自動で読み込みは出来ず、手動読み込みに・・・
自動操作はgoogleに禁止されているようです。
準備
使った環境などを雑に並べる
- mac catalina : 10.15.7
- chrome : 86
- python : 3.9.0
- JupyterNotebook : 6.1.4
- requests:データ取得ライブラリ
- BeautifulSoup:データ抽出ライブラリ
※なんとなくAnacondaは使わず、適当にpip3でインストール
ざっくり処理の抜粋&説明
requestsで、キーワード(兵庫県の市町村ごとに)から食事券が使える店を検索
import requests from bs4 import BeautifulSoup as bs4 … #検索ページのURL、検索ワード、ページ数から結果のページ情報を取得 url ="(検索ページのURL)" param = {"keyword" : (検索ワード), "page" : (検索ページ数)} res = requests.get(url, param)
主にbeautifulsoupのselectを使って 検索結果&詳細ページから店の情報(店名、住所、電話番号、webサイト、営業時間)を抽出
#ページ解析 search_result = bs4( res.text, "html.parser") #店舗情報のエリアを取得(1ページで10件ぐらいあったので、リストで取得して順番に処理) store_list = search_result.select("div.search-results-list-box") for store in store_list: #店名 store_name = store.select("p.search-results-list-name")[0].text #住所 store_address = store.select("p.search-results-list-p01")[0].text.replace(" ", "").replace("\n", "").replace("住所:", "") ...
あとは各店舗の情報を1行にしてcsvに出力
import csv csv_filename = "goto_eat_" + search_word + ".csv" f = open(csv_filename, mode = 'w', encoding='utf-8', errors = 'ignore') writer = csv.writer(f, lineterminator = '\n') csv_list = [] csv_list.append(store_name) csv_list.append(store_address) … writer.writerow(csv_list)
詳細コードは↓ https://github.com/kyamada23/goto_eat_hyogo
詰まったところなど
JupyterNotebookがでなんか起動しない問題
jupyter notebook
コマンドを実行すると、自動でchromeのページが開いて↓のページが表示されるんですが、
「click here to go to Jupyter.」をクリックしても全然反応してくれない・・・
ターミナルにこれをコピーしろみたいなのがあったのでとりあえずそれ(↓の一番下だけ)をコピペして表示されました。
To access the notebook, open this file in a browser: file:///Users/… Or copy and paste one of these URLs: http://localhost:8888/?token=… or http://127.0.0.1:8888/?token=…
隣の要素取得がしっくりこない
<th>定休日</th> <td>毎週火曜日</td>
上記で定休日の要素を見つけて、その隣の情報を取得しようとするときに
(定休日の要素).next_sibling
だと取得できず(改行が取得されるから?)
(定休日の要素).next_sibling.next_sibling
と2回繰り返すと取得できた。
go to eatひょうごの食事券アクセス殺到問題
食事券を購入する時にアクセスが殺到して、全然ページが開かずに買うまでにめちゃめちゃ時間がかかりました。 11/10分からは抽選になっているみたいです。
JupyterNotebook
気軽に実行するには便利なんですが、ファイル形式が独自のものになるので、git管理すると分かりづらい感じがしました。 終わったらpython形式に出力したらいいのかも?
感想
覚えたwebスクレイピングを試してみるにはいい素材だったかなと思います。
他の都道府県のもやってみると面白いかも
ちなみに企業が作った地図検索サービスもあります!(あるかなと思っていたけど、作るまではあえて調べなかった)
SQLの準備/実行/読み込み(prepare/execute/fetch)メモ -PHP-
phpのPDO(PHP Data Objects)のかなり簡単なメモです。
メソッド(prepare, execute, fetch)を実行してどんな結果が返ってくるのかあたり。
クエリの作成(PDO::prepare)
実行例:
$dbh->prepare($sql)
クエリーの文(PDOStatementオブジェクト)が返ってくる
基本的に何が入っててもそのまま文にして返してくるっぽい。SQL文として間違っていてもエラーにはならない。
※失敗したらfalseを返すか、例外を投げるっぽいが、どういう時にそうなるのか・・・
参照: https://www.php.net/manual/ja/pdo.prepare.php
クエリの実行(PDO::execute)
実行例:
$dbh->execute($data)
クエリの実行が成功した場合はtrue
を返す
クエリの実行が失敗した場合はfalse
を返す
※SELECTの結果のレコードが0件の場合もfalse?と思われる
参照: https://www.php.net/manual/ja/pdostatement.execute.php
クエリの結果取得(PDO::fetch)
実行例
$result = $stmt->fetch(PDO::FETCH_ASSOC);
成功した場合、結果のレコードを連想配列として返す(FETCH_ASSOCの場合)
失敗したばい、falseを返す
連想配列として返ってくるので、最初の値を取得する場合はarray_shiftやcurrentなどで指定したり、キーを指定したりする($result['(キー名)'])
https://www.php.net/manual/ja/pdostatement.fetch.php
おまけ
取得した結果を判定するのに参考にしてるページ
empty(), is_null(), isset()の結果一覧:
https://php.net/manual/ja/types.comparisons.php