ディズニーストアの人気商品を手に入れる方法
前提
奥さんはディズニーの「ラプンツェル」というキャラクターが好きだ。
ある日「ディズニーストアで販売している『ラプンツェルLEDライト』という商品がどうしても欲しいんだけどいつも売り切れてて・・・再入荷したらアラートが来るようにできないか?」という相談を受けた。
まずは敵を知る
ディズニーストアにはオンラインショップがあるので、まずは要素を見てみる。
そこでわかった重要なことは以下の3点だ。※2014年10月01日 時点
- 公式には入荷アラートの機能は存在しない。
- 商品にはそれぞれ固定のURLが存在する。
- 在庫がある商品には、購入数を選択するセレクトボックスと購入ボタンが存在する。
ここまでわかればこっちのものだ。
攻略法(仕様)を決める
cronで定期的に商品ページをスクレイピングして、在庫があるときにだけでる要素が存在すればメールでアラートすることにする。
- 10分に1回処理を実行。
- 在庫があるかの確認は、購入数を選択するときにだけ表示される「数量」という文字があるかどうかで行う。
- メールが何回も送られてくるのは嫌なので1度だけ送るようにする。
- 深夜のメールは迷惑なので、7時から25時までの間だけメールを送るようにする。
- 今後別の商品でも同じ要望があるかもしれないので、「商品の指定」と「在庫チェック」は分離して実装する。
実装
disneystore_check.php
<?php
$id = 1;
$url = "http://www.disneystore.co.jp/shop/ProductDetail.aspx?sku=4936313635065&CD=F3000283&WKCD=";
$name = "ラプンツェルLEDライト";
$checker = new StockChacker($id, $url, $name);
$checker->run();
class StockChacker {
const AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36";
const ENC_FROM = "SJIS";
const ENC_TO = "UTF-8";
const KEYWORD = "数量";
const PID_DIR = "/tmp/cron/disneystore";
private $id;
private $url;
private $name;
public function __construct($id, $url, $name) {
$this->id = $id;
$this->url = $url;
$this->name = $name;
}
public function existsPid() {
return file_exists(sprintf(static::PID_DIR . "/%s.pid", $this->id));
}
public function makePid() {
touch(sprintf(static::PID_DIR . "/%s.pid", $this->id));
}
public function run() {
if ($this->existsPid()) {
return;
}
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $this->url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_USERAGENT, static::AGENT);
$res = curl_exec($curl);
curl_close($curl);
$res = mb_convert_encoding($res, static::ENC_TO, static::ENC_FROM);
if (!strpos($res, static::KEYWORD)) {
return;
}
mb_language('ja');
mb_internal_encoding('UTF-8');
mb_send_mail(
"宛先",
sprintf("%s入荷中", $this->name),
$this->url,
"From: 差出人"
);
$this->makePid();
}
}
crontab.txt
*/10 0,7-23 * * * php disneystore_check.php
結果
無事に購入できました。
※真ん中下にあるやつ。