Skip to content

Instantly share code, notes, and snippets.

@tokchin
Last active November 29, 2019 07:05
Show Gist options
  • Save tokchin/a7dc211ca2560d6c373217cc2b50a196 to your computer and use it in GitHub Desktop.
Save tokchin/a7dc211ca2560d6c373217cc2b50a196 to your computer and use it in GitHub Desktop.
#Selenium関連のモジュール読み込み
from selenium import webdriver #ブラウザ制御
from selenium.webdriver.firefox.options import Options #ブラウザ制御を始める時のオプション設定
from selenium.webdriver.common.by import By #要素の選択方法
from selenium.webdriver.support.ui import WebDriverWait #待機
from selenium.webdriver.support import expected_conditions as EC #待機条件指定
from time import sleep
import os
class MiimeDutchAuctionBot:
def __init__(self, token_address, token_id, headless=False):
#値段を書き換える、トークンのアドレスとIDを指定
self.token_address = token_address
self.token_id = token_id
#ブラウザを描画するかどうか指定
if headless:
#ブラウザ制御のオプション設定を読み込み
options = Options()
#オプション設定に-headlessを追加
options.add_argument("-headless")
#ブラウザ制御オプションをブラウザ(webdriver)に設定して、ブラウザを起動
self.browser = webdriver.Firefox(options=options)
else:
#オプション無しでブラウザ(webdriver)を読み込む
self.browser = webdriver.Firefox()
#metamaskのエクステンションをwebdriverに読み込む
#gecko driver(firefox)が絶対パスしか受け付けないので、相対パスから絶対パスに変換
abspath = os.path.abspath('./lib/metamask-firefox.zip')
#ブラウザにmetamaskをインストール
self.browser.install_addon(
abspath, temporary=True)
#価格を下げるfunction(今回使うメイン関数)
def deduct_price(self, dummy_backup_phrase, dummy_password, privatekey, deduction):
#メタマスク初期化
self.metamask_init(dummy_backup_phrase, dummy_password, privatekey)
#miime.ioを開く
self.open_miime()
#metamaskをミームと繋ぐ
self.metamask_connect()
#価格を下げるtアイテムのページを
self.open_item_page(self.token_address, self.token_id)
#価格変更
self.change_price(deduction)
#メタマスクで署名する
self.metamask_sign()
#メタマスクで承認する
self.metamask_approve()
#完了報告
print("price_changed")
#表示されたら、指定したXpathのボタンをクリックする。
def wait_and_click(self, xpath):
#seleniumの待機用のオブジェクトを呼び出し
wait = WebDriverWait(self.browser, 10)
#xpathの要素がクリック可能になるまで待ってから、その要素をelementにいれる
element = wait.until(EC.element_to_be_clickable((By.XPATH, xpath)))
#elementに保存されている要素をクリックする。
element.click()
#表示されたら、指定したXpathに入力する。
def wait_and_input(self, xpath, value):
wait = WebDriverWait(self.browser, 10)
#xpathの要素が出現するまで待ってから、その要素をelementにいれる
element = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
#elementに保存されている要素にvalueを入力する。
element.send_keys(value)
#num個の画面が出現するまで待つ
def wait_for_window(self, num):
wait = WebDriverWait(self.browser, 10)
#windowの数がnumになるまで待つ
#wait.until()の中身はfunctionにしておかないと、動かない。Boolだとだめ。
wait.until(lambda x: len(self.browser.window_handles)==num)
#xpathにテキストが出現するまで待ってから、テキストを返す
def wait_for_text(self, xpath):
wait = WebDriverWait(self.browser, 10)
element = wait.until(EC.presence_of_element_located((By.XPATH, xpath)))
#elementに保存されている要素のtextを返す。
return element.text
#N番目のウィンドウに変更する。0スタートなので、[a,b,c]でbが欲しい場合1を指定
def change_window(self, num):
#num番目のウィンドウを取得しhandleに保存
handle = self.browser.window_handles[num]
#handleに保存されているウィンドウに移動
self.browser.switch_to_window(handle)
#メタマスク初期化
def metamask_init(self, dummy_backup_phrase, dummy_password, privatekey):
#新しいwindowが出現する場合少しsleepを入れておかないとたまに失敗する。
#0.1秒待機
sleep(0.1)
#windowが2個表示されるまで待つ
self.wait_for_window(2)
#0から数えて1番目のwindowに移動,[a,b,c]のb
self.change_window(1)
#'/html/body/div/div/div[3]/div/div/div/button'はXpath
#このxpathのボタンが出現したら、ボタンをクリックする。
self.wait_and_click(
'/html/body/div/div/div[3]/div/div/div/button')
#xpathを探してクリックする。
self.browser.find_element_by_xpath(
'/html/body/div/div/div[3]/div/div/div[2]/div/div[2]/div[1]/button').click()
self.browser.find_element_by_xpath(
'/html/body/div/div/div[3]/div/div/div/div[5]/div[1]/header/button[1]').click()
#xpathが表示されるまで待ってから、バックアップフレーズを入力する。
#waitを入れないと、たまに入力に失敗するのでwait_and_inputを指定
self.wait_and_input(
'/html/body/div/div/div[3]/div/div/form/div[4]/textarea',dummy_backup_phrase)
#xpathを探してパスワードを入力する
self.browser.find_element_by_xpath(
'//*[@id="password"]').send_keys(dummy_password)
#xpathを探して確認用パスワードを入力する
self.browser.find_element_by_xpath(
'//*[@id="confirm-password"]').send_keys(dummy_password)
#ボタンをクリックして画面を遷移させる
self.browser.find_element_by_xpath(
'/html/body/div/div/div[3]/div/div/form/div[7]/div').click()
self.browser.find_element_by_xpath(
'/html/body/div/div/div[3]/div/div/form/button').click()
self.wait_and_click('/html/body/div/div/div[3]/div/div/button')
self.wait_and_click('/html/body/div/div/div[1]/div/div[2]/div[2]')
self.browser.find_element_by_xpath(
'/html/body/div/div/div[4]/div[7]/div[2]').click()
#xpathを探して、プライベートキーを入力する。
self.browser.find_element_by_xpath(
'//*[@id="private-key-box"]').send_keys(privatekey)
self.browser.find_element_by_xpath(
'/html/body/div/div/div[4]/div/div[2]/div/div[3]/div[2]/button[2]').click()
def open_miime(self):
#ミームのページを開く
self.browser.get("https://miime.io")
#メタマスク接続
def metamask_connect(self):
#お約束、新ウィンドウ開くときは0.1秒待機
sleep(0.1)
#ウィンドウの個数が3個になるまで待つ
self.wait_for_window(3)
#0から数えて2番目のウィンドウに移動(メタマスクの接続承認ウィンドウ)が出てくるまで待つ
self.change_window(2)
#接続ボタンを押す
self.wait_and_click(
'/html/body/div/div/div[3]/div/div[3]/header/button[2]')
#ウィンドウの個数が2個になるまで待つ
self.wait_for_window(2)
#0から数えて1番目のウィンドウに移動
self.change_window(1)
def metamask_sign(self):
#お約束、新ウィンドウ開くときは0.1秒待機
sleep(0.1)
#ウィンドウの個数が3個になるまで待つ
self.wait_for_window(3)
#0から数えて2番目のウィンドウに移動(メタマスクの署名ウィンドウ)が出てくるまで待つ
self.change_window(2)
#0から数えて2番目のウィンドウに移動(メタマスクの署名ウィンドウ)が出てくるまで待つ
self.wait_and_click('/html/body/div/div/div[3]/div/div[4]/button[2]')
#0から数えて1番目のウィンドウに移動
self.change_window(1)
def metamask_approve(self):
#お約束、新ウィンドウ開くときは0.1秒待機
sleep(0.1)
#ウィンドウの個数が3個になるまで待つ
self.wait_for_window(3)
#0から数えて2番目のウィンドウに移動(メタマスクの接続承認ウィンドウ)が出てくるまで待つ
self.change_window(2)
#署名ボタンを押す
self.wait_and_click('/html/body/div/div/div[3]/div/div[3]/button[2]')
#0から数えて1番目のウィンドウに移動
self.change_window(1)
def open_item_page(self, token_address, token_id):
#変数token_addressとtoken_idを入力して
self.browser.get(f"https://miime.io/assets/{token_address}/{token_id}")
#今回は使わない出品機能
def sell(self, price):
#アイテムページで出品ボタンが出現したら、出品ボタンを押す
self.wait_and_click('/html/body/div[1]/div/div/main/div/div/button')
#入力欄が出現したら価格を入力する。
self.wait_and_input(
'/html/body/div[1]/div/div/main/div/div[2]/div[2]/div/input', price)
#購入ボタンがクリック可能状態になったら、ボタンを押す
self.wait_and_click('/html/body/div[1]/div/div/main/div/div[3]/button')
#価格をdeuctionの金額だけ、減らす機能
def deduct_price(self, deduction):
#金額変更ボタンを押す
self.wait_and_click('/html/body/div[1]/div/div/main/div/div/button')
#xpathの位置に保管されている、現在の価格を取得して、current_priceに保存
current_price = self.wait_for_text(
'/html/body/div[1]/div/div/main/div[2]/div[2]/div/div[1]')
#現在価格をコンソールに出力
print(f"current price:{current_price}")
#現在価格から、deduction削減価格を差し引いた値を小数点2桁で切り上げする
new_price = round(float(current_price) - deduction, 2)
#新価格をコンソールに出力
print(f"current price:{new_price}")
#新価格を入力スル
self.wait_and_input(
'/html/body/div[1]/div/div/main/div[2]/div[3]/div/input', str(new_price))
#価格変更ボタンを押す
self.wait_and_click('/html/body/div[1]/div/div/main/div[3]/button')
def main():
#環境変数に保存してあるプライベートキーを読み込む。
privatekey = os.environ['privatekey']
#使い捨てのバックアップフレーズを読み込む
privatekey = os.environ['privatekey']
dummy_backup_phrase = "cart vicious rebuild traffic gospel wheat nice true sand concert drastic sentence"
dummy_password = "password"
#価格を変更したいアイテムのトークンアドレスとIDを実装する。
token_address = '0xdceaf1652a131f32a821468dc03a92df0edd86ea'
token_id = '10141042'
bot = MiimeDutchAuctionBot(token_address, token_id)
bot.deduct_price(dummy_backup_phrase, dummy_password, privatekey, 0.01)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment