こんにちは、はるです。
pythonでwebスクレイピングをしてみたい。
webスクレイピングした情報をLINEに送ってみたい。
こんな悩みを解決していきます。
私自身pythonを勉強中ですが、「楽天ハンドの入荷情報をスクレイピングして、入荷したらLINEに通知を送る」という処理を作りました。
楽天モバイルの公式サイトの利用規約を見る感じスクレイピングは禁止されていなかったので、「まだスクレイピングやったことがないよ」という方は本記事を参考にぜひチャレンジしてみてください!
クローリングできるページ一覧は、robots.txtで見ることができます。(Disallow は禁止ページ)
楽天サイトのrobots.txt
本記事では楽天ハンドを例に、pythonでスクレイピングする方法と、webスクレイピングした値をLineに通知させる方法を解説していきます。
実行環境
- Windows10
- Anaconda3
追記:2021年3月15日
楽天ハンドのクラス名が変わっています。
本記事で紹介したクラス名は、product-detail-Layout_Btn-modalですが、
2021/3/15現在では、c-Btn_Primary-autoとproduct-Rakuten-hand_Nav-btnになっています。
はじめに、ソースコード公開
今回解説するソースコードを載せておきます。
from bs4 import BeautifulSoup
import requests
r = requests.get("https://network.mobile.rakuten.co.jp/product/smartphone/rakuten-hand/")
print(r)
c = r.content
# print(c)
soup = BeautifulSoup(c, "html.parser")
# print(soup)
category = soup.find_all('div',{'class': 'product-detail-Layout_Btn-modal'})
print(category.text)
stock = category.text
def main():
send_line_notify(stock)
def send_line_notify(notification_message):
line_notify_token = 'LINEのトークン'
line_notify_api = 'https://notify-api.line.me/api/notify'
headers = {'Authorization': f'Bearer {line_notify_token}'}
data = {'message': f'message: {notification_message}'}
requests.post(line_notify_api, headers = headers, data = data)
if ("現在入荷待ち" != stock):
print("入荷したみたい")
if __name__ == "__main__":
main()
else:
print("入荷待ち")
pythonでwebスクレイピングする方法
以下の順番で、webスクレイピングをすることができます。
- BeautifulSoupとrequestsのインポート
- サイトを読み込む
- 値をとってくる
BeautifulSoupとrequestsのインポート
まずは、BeautifulSoupとrequestsをインストールします。Anacondaを使っている人はconda、使っていない人はpipです。
私はAnaconda環境なので、公式サイトのとおりにcondaでインストールしました。
- conda install -c anaconda beautifulsoup4
- conda install -c anaconda requests
参考:Anaconda公式サイト
- pip install beautifulsoup4
- pip install requests
参考:pipy公式サイト
インストールが終わったら、インポートしていきます。以下のような感じです。
from bs4 import BeautifulSoup
import requests
サイトを読み込む
requestsを使って、スクレイピングしたいサイトを読み込みます。
r = requests.get("https://network.mobile.rakuten.co.jp/product/smartphone/rakuten-hand/")
# print(r)
c = r.content
# print(c)
requests.getでサイトのURLをとってきます。
このrに入った値は、「Response[200]」といったHTTPステータスコードです。
カンタンに説明すると、「URLちょうだいー」「OK、取得に成功したよ」というやり取りをしていて、「Response[200]」が成功を表しています。
r.contentとすることで、htmlソースコードを抜き出すことができます。ですが、改行が¥nとなっていたり、日本語が英数字になっていたりして見にくい。
そこで、BeautifulSoupを使ってキレイにしていきます。
soup = BeautifulSoup(c, "html.parser")
# print(soup)
第一引数(,の前)にとってきたhtmlを入れ、第二引数(,から後ろ)にはhtml.parserを指定します。
html.parserの代わりにlxmlでも大丈夫みたいですが、lxmlをインポートする必要があったので使いませんでした。
値をとってくる
次にスクレイピングで値をとっていきましょう。
楽天ハンドが入荷したら、「現在入荷待ち」という表記が変わります。なので、「現在入荷待ち」のテキストデータが欲しいです。
そこで、「現在入荷待ち」と書かれているボタンのproduct-detail-Layout_Btn-modalというクラス名を取得していきます。
実際のhtmlは以下の感じでした。
<div class="product-detail-Layout_Btn-modal" aria-disabled="true"><a>現在入荷待ち</a></div>
追記
追記:2021年3月15日
楽天ハンドのクラス名が変わっています。
本記事で紹介したクラス名は、product-detail-Layout_Btn-modalですが、
2021/3/15現在では、c-Btn_Primary-autoとproduct-Rakuten-hand_Nav-btnになっています。
つぎに、soup.findで指定した値(今回はclass)のついたhtmlを取得します。
そのまま出力すると、文字を含んだhtmlが表示されますが、現在入荷待ちという文字だけを取り出したいので、categoryの後ろに.textをつけました。
category = soup.find_all('div',{'class': 'product-detail-Layout_Btn-modal'})
print(category.text)
stock = category.text
ちなみにsoup.find_allにすると、複数取り出すことができます。
今回の例でいうと、product-detail-Layout_Btn-modalのクラス名がついたすべてのhtmlが対象です。
webスクレイピングした値をLineに通知させる方法
続いて、スクレイピングした値をLineに通知させる方法は以下の手順です。
- トークンを取得する
- 通知を送る
- 条件分岐
トークンを取得する
まずはLINE Notifyにログインします。
LINEアカウントのメールアドレスとパスワードを入力しましょう。
次にマイページを開いて、トークンを発行します。
マイページの下の方にトークンを発行する場所があります。
トークン名を入力し、通知を受け取るライングループを選びます。
自分宛てにする場合は、一番上の1:1を選びましょう。
トークンを発行して画面を閉じたら見れなくなるので、コピーを忘れずに。
通知を送る
send_line_notifyには、LINEで送られてくるメッセージを入れることができます。
今回はstockを入れて「現在入荷待ち」か「購入する」のどちらかスクレイピングしたものが入るようにしました。
def main():
send_line_notify(stock)
def send_line_notify(notification_message):
line_notify_token = 'LINEのトークン'
line_notify_api = 'https://notify-api.line.me/api/notify'
headers = {'Authorization': f'Bearer {line_notify_token}'}
data = {'message': f'message: {notification_message}'}
requests.post(line_notify_api, headers = headers, data = data)
条件分岐
スクレイピングで得た値が「現在入荷待ち」でなければ、main()処理を呼び出します。
if ("現在入荷待ち" != stock):
print("入荷したみたい")
if __name__ == "__main__":
main()
else:
print("入荷待ち")
if __name__ == “__main__”:は、他のファイルにインポートするときにプログラムが勝手に動かないようにするものなので、付けても付けなくても動きます。
さいごに
お疲れさまです!
追加で「10分おきに処理を行うループ処理を加えて、在庫が入ったら自動でLINEに通知するプログラム」も作れたので、下記に載せておきます。
※10分おきに処理をするというプログラムを使いたかったので、scheduleとtimeも追加でインポートしています。
import schedule
import time
from bs4 import BeautifulSoup
import requests
def loop():
r = requests.get("https://network.mobile.rakuten.co.jp/product/smartphone/rakuten-hand/")
c = r.content
soup = BeautifulSoup(c, "html.parser")
# print(soup)
category = soup.find_all('div',{'class': 'product-detail-Layout_Btn-modal'})
print(category.text)
stock = category.text
def main():
send_line_notify(stock)
def send_line_notify(notification_message):
line_notify_token = 'LINEのトークン'
line_notify_api = 'https://notify-api.line.me/api/notify'
headers = {'Authorization': f'Bearer {line_notify_token}'}
data = {'message': f'message: {notification_message}'}
requests.post(line_notify_api, headers = headers, data = data)
if ("現在入荷待ち" != stock):
print("入荷したみたい")
if __name__ == "__main__":
main()
else:
print("入荷待ち")
schedule.every(10).minutes.do(loop)
while True:
schedule.run_pending()
time.sleep(1)
以上です。
ご覧いただきありがとうございました。
※さらにサイトの自動ログインについても知りたい方は、こちらの記事もどうぞ。
- PythonでHTMLを解析してデータ収集してみる? スクレイピングが最初からわかる『Python 2年生』
- 【Python】Webスクレイピングの挑戦準備!BeautifulSoupをインストール
- 【Python】BeautifulSoupライブラリを使ってWebスクレイピング入門
- PythonでLINE Notifyへ通知を送る
- 【※絶対に自動化してはいけない】自動化禁止サイトまとめ!
- 【Python】scheduleを使ってモジュールを定期実行させよう
- Python Scheduleライブラリでジョブ実行
- Pythonのif __name__ == “__main__” とは何ですか?への回答
コメント