見出し画像

#005 ハンドメイド販売サイトの在庫連携をどうしていますか?④(minne操作編)

在庫連携の目次

「在庫連携」の記事が長いため、複数の記事に分けて投稿しています。
一連の流れになっていますので、①から読んでいただけると助かります。

①(在庫連携につついて) https://note.com/tamaworks/n/n911d62818345
②(ブラウザ操作編) https://note.com/tamaworks/n/nbe954b7b6412
③(selenium導入編) https://note.com/tamaworks/n/nd0c40ef1a2fd
④(minne操作編) 現在の記事
⑤(Creema操作編) https://note.com/tamaworks/n/nd6262ea6c583
⑥(完成編) https://note.com/tamaworks/n/n54975f0c257a

HTMLの取得

(1) HTMLについて

ブラウザに表示されるWebの情報は基本的にはHTML ((Hypertext Markup Language)と呼ばれる言語で書かれています。これはminneに関しても同様で、Chromeの場合ブラウザの画面上で右クリックをしてメニューから"ページのソースを表示"か、キーボード⌨の"Ctrl+U"ボタンを押します。

ページのソースを表示
HTMLのイメージ

見慣れないとナニコレ?となりますが、HTMLの内容が表示されます。
HTMLは基本的に<>で表示されるタグで囲まれた構成になっています。
上記のHTMLでは<dl>~</dl>や<dt>~</dt>、<a>~</a>が一対になっています。
この情報を元にして、PythonSeleniumを使って商品名や在庫数、ボタン操作を行うことになります。

(2) HTMLの取得方法

HTMLから必要な情報を取得する一番簡単な方法はタグ内にあるid(識別子)を使う方法です。idが使われているHTMLは以下のようになります。

<div id="kakaku">5000円</div>

idはHTML中に1回のみの使用になります。同じように使われているclassがありますが、こちらはHTML内で何回でも使用可能です。

Seleniumで上記の価格を取得する場合は次のようになります。
価格の5000円をコンソールに表示するソースです。

driver = webdriver.Chrome()

result = driver.find_element_by_id('kakaku')

print(result)

idが無い場合はどのように取得するのかですが、SeleniumではXPathと呼ばれる便利なツールが用意されています。こちらは後程紹介したいと思います。

minneの操作

(1) 商品ページでの在庫数取得について

まずはminneの販売ページを開いてみます。そこから在庫数が掛かれた箇所を探します。

購入画面のイメージ

右上に「残り1点」と書かれたところが在庫数になります。ご購入される場合はお早めに(プチ告知💦)

この部分のHTMLファイルを覗いてみます。Chromeの場合は、F12キーを押して、ディベロッパーツールを開きます。左上の矢印の付いたボタン(Ctrl + Shift + C)をクリックした後、調べたHTMLの箇所にマウスを合わせます。

Chromeディベロッパーツール
選択された箇所のHTML情報

10,000円にマウスを合わせると、色やテクストのサイズ等の情報がポップアップ上に表示され、ディベロッパーツール上に対象のHTMLの箇所が表示されます。取得されたHTMLは次のようになります。

<span class="red_text mg_r_10 strong">残り1点</span>

「残り1点」文字を取得したいのですが、sapnタグ内にidがなくclassしかないため取得が難しいです。ここまで書いておいてですが、個数を変更する場合は販売ページではなく、管理者用の作品登録ページに移動する必要があります。作品登録ページは新規登録や変更に使われるページなので比較的idが多く使われています。
販売ページの方は、ページのデザイン変更が多く、仮に個数を取得できてもすぐにプログラムが使えなくなる可能性すらあります。

今回はせっかくなので販売ページから作品登録ページにPythonを使って変更します。

販売用ページ:https://minne.com/items/29777231
作品登録ページ:https://minne.com/account/products/29777231

minneのドメイン部と商品コードの29777231は同じで、
"items"と"account/products"の箇所が変更部分になります。
replace関数を使って"items"と"account/products"を置換します。

# 商品ページから作品登録ページにURLを変更する(minne)
def replace_minne_URL(url):
newURL = url.replace('items', 'account/products')
return newURL

(2) 自動ログインの方法

作品登録ページが開くと、selenium環境だと最初ログイン状態でないため、ログイン画面が表示されます。

ログイン画面

まずはHTMLを確認してみます。メールアドレス部とパスワード部のHTMLは以下の通りです。

<input type="email" value="" name="user[email]" id="user_email">
<input type="password" name="user[password]" id="user_password">

両方とも識別子のidがあるのでそのまま要素を取得することができます。
自動でログインページを開いて、メールとパスワードに自動でパスワードを入力して、ログインを行ってみます。

# Chromeドライバーのセッションを開始
driver = webdriver.Chrome()
#メールアドレスとパスワードの設定
minneMail = 'xxxx@xxxx.com'
minnePassword = 'yyyy'
# minneのログイン
driver.get("https://minne.com/signin")
# minneのメールアドレス入力
driver.find_element_by_id("user_email").send_keys(minneMail)
# minneのパスワード入力
driver.find_element_by_id("user_password").send_keys(minnePassword)
# minneのメールアドレスとパスワードの送信
driver.find_element_by_xpath("//*[@id='session_new']/div/div[4]/input").submit()

Chromeドライバーのセッションを開始します。

driver = webdriver.Chrome()

変数にメールアドレスとパスワードの設定をおこないます。
ここではダミー値を使用しています。

minneMail = 'xxxx@xxxx.com'

minnePassword = 'yyyy'

minneのログインページを開きます。
ログインページのURLは、"https://minne.com/signin"です。

driver.get("https://minne.com/signin")

driver.find_element_by_id("user_email") の箇所でidを元にメールの入力フォームを取得します。
次に取得したフォームに.send_keys(minneMail) で先程設定したメールアドレスを送り込みます。

driver.find_element_by_id("user_email").send_keys(minneMail)

メールアドレスとパスワードを自動で入力したら最後に「ログイン」のボタンをクリックします。
このクリックはもちろんSeleniumを使って自動で行います。

ログインボタンのHTMLですがinputタブの箇所を確認するとメールアドレスやパスワードと違いidが設定されていません。
ここでは先述したXPathを使ってinputタグを取得します。

<input type="submit" name="commit" value="ログイン" method="post" 
class="c-button c-button--block" data-tracking-category="ログイン" 
data-tracking-action="click" data-tracking-label="メールアドレスでログイン"
 data-disable-with="ログイン">

Chromeの場合F12キーを押してディベロッパーツール起動します。
対象のソースコードの箇所を右クリックすると、コンテキストメニューが表示されるので、"Copy" → "Copy XPath"の順にクリックします。

コンテキストメニュー1
コンテキストメニュー2

inputタブを取得するのに必要となる、XPathがペーストされるのでソースコード内にコピーして利用できます。

# XPathの内容
//*[@id="session_new"]/div/div[4]/input

XPathを使った要素の取得にはfind_element_by_xpath()関数の引数(半角括弧内)に先程取得したXPathをコピーすることで可能です。

driver.find_element_by_xpath("//*[@id='session_new']/div/div[4]/input").submit()

取得した後はsubmit()関数を使うことで、自動的に「ログイン」のボタンを押すことができます。

(3) 在庫数の変更

ここまででidとXPathを使ってHTML内の要素を取得してみました。
ログイン画面が終わりましたので、本番の作品登録ページで作品の個数の確認、及び変更を行ってみます。
作品登録ページには、ログイン画面の時と同様にget関数でURLを指定して開くことができます。URLは「(2) 自動ログインの方法」で触れた販売ページのURLを作品登録ページのURLに置換した方法でも可能です。

# 直接URLを指定する場合
driver.get("https://minne.com/account/products/29777231")

実際の作品登録ページの一部は以下になります。

作品登録画面

在庫数と単位の箇所に在庫数が、数字で「1」と表示されています。
在庫数は'product_stock_num'という名前のidがあるので、idを使って取得します。

# idを使って要素を取得
element = driver.find_element_by_id('product_stock_num')

# 要素からvalue(値)を取り出す
element.get_attribute("value")

当初の目的(忘れそうでした💦)は、複数の販売サイトで作品を販売しているときに在庫数を合わせるでしたので、この「1」個という数字を変更する必要があります。
Seleniumで入力フォームを書き換える場合は、一度フォームの中をクリアにする必要があり、clear()関数で中身を空にします。
次にsend_keys()関数の引数の中に、変更したい数字を入れます。
下記のソースコードでは「2」個に変更しています。

# 在庫数の設定
driver.find_element_by_id('product_stock_num').clear()
driver.find_element_by_id('product_stock_num').send_keys('2')

これで個数が取得できたと思いますが、一つ大きな問題があります。
個数の上の方にある「公開設定」と「販売設定」です。
それぞれ「公開する」と「販売する」になっていれば問題はありませんが、もし「公開しない」や「販売しない」が選ばれていると、それは販売しないことになるので、実質在庫は「0」扱いになります。

この「公開設定」と「販売設定」についてまとめてみます。
実はこの部分がCSSの疑似要素と呼ばれるものが使われていて複雑になっています。簡単に書くとCSSを使ってボタンのON、OFFに合わせてボタン部の表示サイズが変わる仕組みになっています。

Seleniumではそのまま取得することが難しく、まずXPathを使って該当する要素を取得します。次にそのCSSのスタイルをget_attribute()関数を使って取得します。
「公開する」の状態では、取得できるスタイルが「width: 252px; margin-left: 0px;」となります。
「公開しない」の状態では、取得できるスタイルが「width: 252px; margin-left: -84px;」となります。
このスタイルの差を使って「公開する」か「公開しない」かを判断します。
(もう少しスマートな方法が何かあるかもしれませんが‥💦)

# 「公開設定」の場合
# XPathを使って要素の取得
element = driver.find_element_by_xpath('//*[@id="product-form"]/section[1]/div/div/div/div[7]/div[2]/div/div')
# CSSのスタイルの取得
result = element.get_attribute("style")
# 取得結果
print(result)

# コンソールに「公開する」の場合は「width: 252px; margin-left: 0px;」
#「公開しない」の場合は「width: 252px; margin-left: -84px;」と表示されます。

販売設定は次の通りです。

# 「販売設定」の場合
# XPathを使って要素の取得
element = driver.find_element_by_xpath('//*[@id="product-form"]/section[1]/div/div/div/div[8]/div[2]/div/div')
# CSSのスタイルの取得
result = element.get_attribute("style")
# 取得結果
print(result)

# コンソールに「販売する」の場合は「width: 252px; margin-left: 0px;」
# 「販売しない」の場合は「width: 252px; margin-left: -84px;」と表示されます。

これで「公開設定」と「販売設定」の状態が確認でき、実質在庫数が「0」の場合を判断できます。 公開する or しないを変更する場合は、XPathで取得した要素にclick()を使うことで変更することができます。

element = driver.find_element_by_xpath('//*[@id="product-form"]/section[1]/div/div/div/div[8]/div[2]/div/div')
element.click()


最後に「作品登録ページ」の下部にある「この内容で登録・更新する」のボタンをクリックします。
まずXPathでボタンの要素を取得して、次にclick()関数でクリックを行います。

「この内容で登録・更新する」ボタン
submit = driver.find_element_by_xpath('//*[@id="product-form"]/div[1]/input')
submit.click()

上手く更新されると「作品登録ページ」が更新され上部に「作品の更新をおこないました。」の表示が出てきます。

「作品の更新を行いました。」

これでminneの主な操作は終わりです。次はCreemaの操作について同様にまとめたいと思います。
長くなってしまいましたが、不明な点等ございましたらコメント欄に書いていただけるとなるべく返事をしたいと思います💦

(次回なるべく早く更新したいのですが記事を書く時間があまり取れず遅れています)

この記事が気に入ったらサポートをしてみませんか?