概要
大学のロボット部で部品を買うのですが、管理をしやすくするために個人でバラバラに買わずに購入品目をEXCELでまとめて購入担当にリストを渡すことで購入してもらっています。購入品をまとめる作業もリストからURLを一つ一つ通販サイトにコピーしてカートに入れるのも数が多くて面倒くさい!ということで、今回は既に作ってある商品リストのEXCELファイルを読み込ませて自動でカート追加まで行うプログラムを作成してみました。
簡単に書けそうだったので言語はpythonにしました。
環境
ASUS zenbook UX310U
Windows10 home (64bit)
CPU Intel core i5 7200U
Google Chrme 81.0.4044.92
ChromeDriver 81.0.4044.69
Python 3.7.3(Anaconda)
エディタ Sublime Text3
selenium
openpyxl
環境構築手順
Python 環境は Anaconda3です。Anaconadaをインストールしていない人はインストールしましょう。
必要パッケージのインストール
こちらを参考に必要パッケージおよびドライバーをインストールしました。
seleniumインストール
まずはanaconda promptを起動して新しく仮想環境を作ります。既にインストール済みのパッケージの依存関係によってはエラーが出ることがあるので新しい仮想環境にインストールすることを勧めます。
conda create -n selenium
仮想環境の切り替え
conda activate selenium
インストール
conda install selenium
ChromeDriver のインストール
今回はpipでインストールし、パス通さないでスクリプト内でインポートします。
https://qiita.com/hanzawak/items/2ab4d2a333d6be6ac760
を参考にしてインストールを進めていけばできます。
以下に一応やった手順を示します。
google chromeのバージョンを確認すると81.0.4044.92だったのでChromeDriverのダウンロードページで自分のchromeバージョンに近い番号を探してインストールします。(バージョンが下で近いものがいいかもしれません)
pip install chromedriver-binary==81.0.4044.69
ちなみに今回はpipでインストールしましたが、こちらのサイトにバイナリでダウンロードする方法も書いてあります。
openpyxlのインストール
pythonでEXCELファイルを読み書きするパッケージです。詳しい使い方はこの方の記事が参考になると思います。
以下のコマンドでインストールします。
conda install openpyxl
ExcelファイルにあるURLの取得
ひとまずExcelファイル内にある全てのURLと購入個数と購入場所の取得までやってみます。予めURLと購入個数のセルは決まっているので指定してリストにしています。何も書かれていないセルでエラーが出るのを防ぐためにfor文で取得しています。
import sys
from argparse import ArgumentParser as Parser
import openpyxl
parser = Parser(description='EXCELに書かれた商品リストを自動的にカートに入れるスクリプト')
parser.add_argument("path",type=str,help='excelファイルのパスを指定')
args = parser.parse_args()
wb = openpyxl.load_workbook(args.path)
sheet = wb['Sheet1']
url=[]
buy_quan=[]
site=[]
for sell in sheet.iter_rows(min_row=2,max_col=8):
values = []
for col in sell:
values.append(col.value)
if values[7] != None:
url.append(values[7])
if values[6] != None:
buy_quan.append(values[6])
if values[3] != None:
site.append(values[3])
print(url)
print(buy_quan)
print(state)
実行するときは以下のコマンドです。引数にはExcelのファイルパスを指定します。実行してURL、購入個数、購入場所の順番でリストが表示されれば成功です。
python listup_from_excel.py filepass
URL表示からカート追加まで
先程のプログラムの続きです。
今回は秋月電子の通販サイトでやってみます。まず、適当な商品ページで購入数量のテキストボックスを右クリックし、「検証」をクリックしてHTMLの要素を表示します。ハイライトされている部分で右クリックし、Xpathをコピーします。
詳しい方法は以下で解説されています。
https://youtu.be/AyicRGWa_70
driver.find_element_by_xpath('xpass')
の引数にコピーしたXpathを貼り付けます。ちなみにXpathはシングルクォーテーションで囲みます。ダブルクオーテーションはだめです。
from selenium import webdriver
import chromedriver_binary
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()#chromeを開く
driver.get('http://akizukidenshi.com/catalog/g/gM-06187/')
wait=WebDriverWait(driver, 10)
# 購入数量のxpathを指定する
element = driver.find_element_by_xpath('//*[@id="maincontents"]/div[2]/table/tbody/tr/td[3]/input')
element.clear()
element.send_keys("6")
element.send_keys(Keys.RETURN)
最後のelement.send_keys(Keys.RETURN)
は購入数量を入力した状態でEnterキーを押すとそのままカートに入るので横着しています。しかし、このままだと在庫切れでテキストボックスが表示されなかったときにカートに入れられません。
全体のコード
使い回せるようにクラスにまとめました。正常にカートに追加できなかったときのために例外処理を入れています。
from argparse import ArgumentParser as Parser
import openpyxl
from selenium import webdriver
import chromedriver_binary
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
url = []#URL
buy_quan = []#購入数量
site = []#購入サイト名
prduct_name = []#製品名
driver = webdriver.Chrome()# chromeを開く
def ListXlsElemet(url_row, buy_quan_row, site_row, proname_row):
parser = Parser(description='EXCELに書かれた商品リストを自動的にカートに入れるスクリプト')
parser.add_argument("path", type=str, help='excelファイルのパスを指定')
args = parser.parse_args()
wb = openpyxl.load_workbook(args.path)
sheet = wb['Sheet1']
for sell in sheet.iter_rows(min_row=2, max_col=8):
values = []
for col in sell:
values.append(col.value)
if values[url_row] != None:
url.append(values[url_row])
if values[buy_quan_row] != None:
buy_quan.append(values[buy_quan_row])
if values[site_row] != None:
site.append(values[site_row])
prduct_name.append(values[proname_row])
class GoToCart:
def __init__(self, arg_url, arg_quan, arg_site,arg_proname):
self.url = arg_url
self.buy_quan = arg_quan
self.site = arg_site
self.proname=arg_proname
def CharClassifi(self, ch, target): # 特定の文字列を含むかどうかを判定し、一致したらリストに追加する関数
relist = []
num = 0
for char in self.site:
if str(char) == ch:
relist.append(target[num])
num = num + 1
return relist
# サイト名とxpthsを渡すと必要数分カートに入れる関数
def AddCart(self, site_name, num_xpath, cart_xpath):
temp_url = self.CharClassifi(site_name, self.url)
temp_quan = self.CharClassifi(site_name, self.buy_quan)
temp_proname = self.CharClassifi(site_name, self.proname)
num = 0
helth=0
for t_url in temp_url:
try:
driver.get(t_url)
wait = WebDriverWait(driver, 10)
# 購入数量のxpathを指定する
t_element = driver.find_element_by_xpath(num_xpath)
t_element.clear()
t_element.send_keys(str(temp_quan[num]))
c_element = driver.find_element_by_xpath(cart_xpath)#カートボタンのxpath
c_element.click()
except:
print(temp_proname[num])
print("カートに入れられません。商品が存在しないか在庫がない可能性があります")
continue
num = num+1
class ChildGotoCart(GoToCart):
def Akiduki(self):
self.AddCart( "秋月", '//*[@id="maincontents"]/div[2]/table/tbody/tr/td[3]/input','//*[@id="maincontents"]/div[2]/table/tbody/tr/td[4]/input')
def Sengoku(self):
driver.execute_script("window.open()")#新規ウィンドウオープン
driver.switch_to.window(driver.window_handles[1])#新規タブに切り替え
self.AddCart("千石",'//*[@id="detail_price"]/tbody/tr/td[2]/input','//*[@id="detail_price"]/tbody/tr/td[3]/input')
def main():
buy_handle = ChildGotoCart(url, buy_quan, site,prduct_name)
ListXlsElemet(7, 6, 3,2)
buy_handle.Akiduki()
buy_handle.Sengoku()
print("完了しました")
return 0
if __name__ == "__main__":
main()
関数の使い方
ListXlsElemet(URL,購入数量,購入サイト名,製品名)
各対応するExcelの列番号が入ります。一番左列から0です。
AddCart(Excelに書いてあるサイト名,購入数量のXpath,カートボタンのXpath)
他のサイトを追加したい場合はChildGotoCart
クラスに追加してmain()
から呼び出すだけです。
実行するにはanadonda promptで引数にexcelのファイルパスを指定して実行します。
(selenium)C:\Users\username>python buy_from_excel.py filefass