ショッピングサイトの商品を定期的にチェックするプログラムを Python で作った

Photo by Marcin Kempa on Unsplash

ショッピングサイトの商品を定期的にチェックするプログラムを Python で作った。

ショッピングサイトで欲しい商品があっても、よく売れる商品なのですぐに欠品になる。

商品が補充されるのをずっと待っているわけにもいかないので、商品が補充されたときにメールで知らせてくれるプログラムを Python で作成した。

今回はそのプログラムを作成するためのポイントを公開しよう。

ショッピングサイトで商品の在庫をチェックするための準備

まずは、商品を購入したいショッピングサイトを開き、欲しい商品を検索してみる。

今回の例では東急ハンズのハンズネットで検索してみた。

下図は、検索結果のスナップショットの一部である。

アドレスバーには「https://hands.net/search/?q=XXXXX」(XXXXX は商品名)と表示された。

この URL を使用し、商品名のところを変更してやればよい。

(ソースコードの 13行目から 18行目までを参照)

検索結果の 0件がこの URL の HTML のどこにあるのか、知っておく必要がある。

import requests
from bs4 import BeautifulSoup
# Web ページの読み込み
url = "https://hands.net/search/?q=XXXXX"
html = requests.get(url)
# コンテンツの解析
contents = BeautifulSoup(html.content, "html.parser")
print(contents)

上記のコードを実行してみると、この URL の HTMLが表示される。(コードが多いので省略)

HTML で「0件」の箇所を検索してみると、

<div class="result">検索結果 <span class="count">0件</span></div>

という行が特定できた。

商品の在庫があるかどうかは、クラス "count" が「0件」かどうかを判定してやればよい。

(ソースコードの 20行目から 27行目までを参照)

以上がショッピングサイトで商品の在庫をチェックするための準備作業である。

これらの情報を参考にして、コードを書いていけばよい。

在庫判定後の処理

在庫がなかったときは、検索した時刻を取得して在庫がなかったことをログに出力する。

(ソースコードの 30行目から 35行目までを参照)

在庫があったときは、メールを送信して在庫があったことを時刻とともにログに出力する。

(ソースコードの 37行目から 66行目までを参照)

今回メールサービスは GMAIL を使用している。

GMAIL を使用する場合、ログインで使用するパスワードはアプリパスワードにすること。

アプリパスワードの生成方法は、「アプリ パスワードでログイン - Google アカウント ヘルプ」を参照。

なお、ログ出力は在庫があってもなくても行うため、関数にしておいた。

(ソースコードの 71行目から 75行目までを参照)

どれくらいの頻度で何回繰り返すか

検索頻度は10分おきにし、在庫があれば繰り返しから抜けるようにした。在庫がなければ最大144回( 24時間分)繰り返す。

検索頻度は控えめにして、ショッピングサイトに迷惑がかからないようにする。

(ソースコードの 10行目から 12行目まで、68行目から 69行目までを参照)

バックグラウンドで実行する(Windows 10 の場合)

長時間繰り返し検索するため、プログラムは実行可能ファイル(exe ファイル)にして、バックグラウンドで実行できるようにしておく。(参考:Python ファイルをビルドしてEXE ファイルを作る方法

バックグラウンドでプログラムを実行するには、バッチファイルを作成し、その中で start コマンドを使って exe ファイルを起動すればよい。

start /MIN inventory_check.exe

その気になれば、なんとかなる

何かやりたいことがあっても、はじめからできないと諦めてしまうとその先はない。

できるはずと思ってあれこれ調べていけば、必ず解決策が見つかる。

壁にぶつかっても工夫を凝らせば乗り越えられる。

その気になれば、なんとかなるものだ。

ソースコード

import requests
from bs4 import BeautifulSoup
import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate
import time
import datetime
def scraping(key_word):
# 24時間繰り返す
# 10分毎に検索するため144回繰り返す
for i in range(144):
# Web ページの読み込み
# URL はショッピングサイトで検索したとき、アドレスバーに表示される URL を使用する
# 検索キーワードは変数にする
# これはハンズネットの例
url = "https://hands.net/search/?q=" + key_word
html = requests.get(url)
# コンテンツの解析
contents = BeautifulSoup(html.content, "html.parser")
# 検索結果の検索
# 商品がある場合とない場合のパターンを事前に確認しておく
# ハンズネットの場合、商品がない場合は「0件」と表示されるので、その箇所を特定できるようにする
ln = contents.find("div", attrs={"class", "result"})
num = ln.find("span", attrs={"class", "count"}).contents
if num[0] == "0件":
# 在庫なしの場合
# 検索した時間を取得
dt_now = datetime.datetime.now()
# 該当商品がなかったことをログに出力する
string = str(dt_now) + " " + str(key_word) + " がない\n"
write_log(string)
else:
# 在庫ありの場合
# メールを送信送信する
# 例は GMAIL を使用した場合
from_addr = "差出人メールアドレス"
to_addr = "宛先メールアドレス"
subject = key_word + "が売られているよ"
# GMAIL を利用した場合
# パスワードはアプリケーションを使用する
smtpobj = smtplib.SMTP('smtp.gmail.com', 587)
smtpobj.ehlo()
smtpobj.starttls()
smtpobj.login(from_addr, 'パスワード')
msg = MIMEText(subject)
msg['Subject'] = subject
msg['From'] = from_addr
msg['To'] = to_addr
msg['Date'] = formatdate()
# メールを送信
smtpobj.sendmail(from_addr, to_addr, msg.as_string())
smtpobj.close()
# 検索した時間を取得
dt_now = datetime.datetime.now()
# 該当商品があったことをログに出力する
string = str(dt_now) + " " + str(key_word) + " がある!!!\n"
write_log(string)
break
# 1分間休憩
time.sleep(600)
def write_log(text):
# ログを追記モードで出力
file = open('inventory_check.txt', 'a')
file.write(text)
file.close()
if __name__ == "__main__":
scraping("商品名")
Posted in  on 6/28/2020 by rteak |