ツタヤの在庫検索が使いづらいのでPythonでどうにかしてみた
※この記事のプログラムをGUIアプリにしてみました↓
hanatasdiary.hatenablog.com
突然ですが皆さん、TSUTAYAの在庫検索システムを利用したことがありますか?
レンタル・販売 在庫検索 - TSUTAYA 店舗情報
これはCDやDVDの在庫を、店舗を指定して調べることができるスグレモノです。
しかし1つだけ欠点があります。。。
このシステム、在庫がある店だけを絞り込むことができません。そのため、在庫がある店を探し出すには、全ての店のページを見る必要があります。
5店舗ぐらい調べてみるものの、どこも取扱していないから「この商品はレンタル終わったんだ…」って諦めることが多々あります。
というわけで今回は、在庫がある店の情報のみを抽出し、csvにするプログラムを書いてみました。
スクレイピングの前に
使用するライブラリ
必要なライブラリは以下の通りです。
from bs4 import BeautifulSoup import requests from selenium import webdriver import time import os import csv
今回はスクレイピングしたいページが、JavaScriptでレンダリングされていたので、seleniumを利用します。ブラウザはPhantomJSを使用しました。ただし、PhantomJSは更新が終了してしまい、現在使用が推奨されていないので、他のヘッドレスブラウザを使用したほうが良いと思います。
スクレイピングの流れ
①下図の店舗一覧ページにある店舗URLを全て取得②店舗URLを開いて、真ん中らへんの「お店の在庫情報」から店名と在庫情報を抽出
③在庫情報が[○]か[×]だったらcsvに店名と在庫情報を書き込む
④店舗一覧ページを次のページに遷移させる
以上の①~④を繰り返します。今回は抽出する情報が少ないので、クローリングは行っていません。
コード
というわけで、全体のコードはこんな感じになります↓
from bs4 import BeautifulSoup import requests from selenium import webdriver import time import os import csv # グローバル変数 item_id = '005570850' item_type = 'rental_cd' prefecture_id = '13' csv_save_dir = './csv/' driver = webdriver.PhantomJS() # 在庫情報を取得する def get_zaiko_info(url): # urlを開いてsoupへ driver.get(url) driver.implicitly_wait(10) html = driver.page_source soup = BeautifulSoup(html,'html.parser') # 店の名前と在庫情報を取得 shop_name = soup.find('h3',class_='green clearfix').find('a').string zaiko = soup.find('div',class_='state').find('span').string # 取扱がない場合0をreturn、取扱がある場合はcsvに店名と在庫情報を書き込む if '-' in zaiko: print('{0}では取扱していません'.format(shop_name)) return 0 else: with open(csv_save_dir+'zaiko.csv','a',newline='') as file: writer = csv.writer(file) writer.writerow([shop_name,zaiko]) if '○' in zaiko: print('{0}では在庫があります'.format(shop_name)) else: print('{0}では取扱していますが、現在在庫がありません'.format(shop_name)) return 1 def main(): # csvの保存場所作成 os.makedirs(csv_save_dir,exist_ok=True) # 店一覧のページをsoupへ shop_search_url = 'https://store-tsutaya.tsite.jp/tsutaya/articleList?account=tsutaya&'\ 'accmd=1&arg=https%3A%2F%2Fstore-tsutaya.tsite.jp%2Fitem%2F{0}%2F{1}'\ '.html&ftop=1&adr={2}'\ .format(item_type,item_id,prefecture_id) driver.get(shop_search_url) driver.implicitly_wait(10) # 更新待機 html = driver.page_source soup = BeautifulSoup(html, 'html.parser') # 掲載ページ数を求める search_result_num = soup.find(class_='txt_k f_left').string total_shop_num = int(search_result_num.split('件')[1].split('全')[-1]) if total_shop_num % 20 == 0: lastpage = total_shop_num / 20 else: lastpage = int(total_shop_num/20) + 1 cnt = 0 # 掲載されてる店舗数を数える # ページごと処理 for page in range(1, lastpage+1): # 店舗一覧ページに戻る driver.get(shop_search_url) driver.implicitly_wait(10) # 更新待機 # ページを更新 driver.execute_script("ExecuteAjaxRequest('./articleList', 'account=tsutaya&accmd=1&"\ "arg=https%3a%2f%2fstore-tsutaya.tsite.jp%2fitem%2f{0}%2f{1}.html"\ "&searchType=True&adr={2}&pg={3}&pageSize=20&pageLimit=10000&"\ "template=Ctrl%2fDispListArticle_g12', 'DispListArticle'); return false;"\ .format(item_type,item_id,prefecture_id,page)) driver.implicitly_wait(10) # 更新待機 time.sleep(5) # 更新待機 # ページのsoupを取得する p_html = driver.page_source p_soup = BeautifulSoup(p_html, 'html.parser') # ページに掲載されている全店舗のURL取得 table = p_soup.find('div', id='DispListArticle').find('table') links = table.find_all('a') for link in links: shop_url = link.get('href') cnt += get_zaiko_info(shop_url) # 在庫情報を取得 print('{0}件の店舗で取扱しています'.format(cnt)) driver.quit() # ブラウザを閉じる if __name__ == '__main__': main()