Seleniumを使ってPythonでデータ収集botを作る

**Seleniumウェブドライバ**は**Python**ツールキットの拡張機能です。**Selenium**を使用することで、ユーザーの行動を模倣し、データスクレイピングのような日々の反復的なタスクを自動化することができます.

#概要
この記事でお伝えすること

1) Alibaba Cloud Windowsインスタンスのインスタンス化

2）インストール

- Firefox
- Python 3
- Selenium
- Gecko Webdriver
- Notepad ++

3) Python Seleniumスクリプトを書いて、暗号市場をチェック

- 私たちの "Bot "のためのクラスを書く
- クラス内の Get_crypto_data 関数
- リアルタイムデータをローカルクラウドファイルに書き込むクラスのWrite_file関数。

Alibaba Cloud Windowsインスタンスにログオンして開始します。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/data-collection-bot-with-python-and-selenium_594948)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

#Installation
Internet Explorerを開き、mozilla.orgに移動します。Firefox インストーラのダウンロードを有効にするには、内蔵の Windows ファイアウォールにいくつかの例外を追加する必要があるかもしれません。

Firefox を www.mozilla.org からダウンロードします。

Python 3.7.1 MSI インストーラを [http://www.python.org/download/ ](https://www.python.org/downloads/)からダウンロードします。

インストーラを実行します。インストール中にPythonをPATHに追加するオプションに必ずチェックを入れてください。

Windows 版の Python 3.7.1 には pip インストーラが含まれています。これを使えば、必要なPythonモジュールをすべてインストールすることが簡単にできます。具体的にはSeleniumのWebドライバです。

Windows の Power Shell インターフェイスに移動して、Python が正常にインストールされたことを確認します。

```
python --version
```
ここではPython3.7.1を例に、
早速pipでSeleniumをインストールしてみましょう。

```
pip install selenium
```
ここで、Selenium用の適切なウェブドライバをインストールする必要があります。ブラウザにMozillaを使用しているので、Geckodriverが必要です。プロセスはChromeのウェブドライバをインストールするのと似ています。

[https://github.com/mozilla/geckodriver/releases/download/v0.23.0/geckodriver-v0.23.0-win64.zip]()

リンクをAlibaba Windowsインスタンス上のローカルファイルに保存します。その後、zipを展開します。デスクトップに解凍し、Power Shellのシステムパスにファイルを追加して確認してください。

```
setx path "%path%;c:\Users\Administrator\Desktop\geckodriver.exe"
```
さて、開発環境を整理してみましょう。コードを書くためにnotepadを使うこともできます。私は、シンタックスハイライトのためのフリーのオープンソースIDEであるnotepad++を使用することを好みます。

[https://notepad-plus-plus.org/downloads/v7.8.2/](https://notepad-plus-plus.org/downloads/v7.8.2/?spm=a2c65.11461447.0.0.3ec2517bVlP6bB)

#Pythonスクリプト
では、Python Selenium "Web Bot "に何をさせたいかを決めてみましょう。さて、私たちの「bot」が、私たちのためにいくつかの暗号通貨の市場データを取得してくれるとしたら、それはクールです。そのデータをローカルファイルに書き込みます。そして、そのデータを他のアリババのクラウドサービスにプラグインすることができます。入力の準備をしましょう。

では、早速コーディングに取り掛かりましょう。IDEを起動して、Seleniumをインポートします。後ほど説明するように、timeとdatetimeもインポートします。

```
from selenium import webdriver
import datetime
import time
```
まず、Seleniumに実際に何かを実行させて、何を期待するかを知ることができます。

```
browser = webdriver.Firefox()
browser.get("http://www.baidu.com/")
```
ファイルを.pyという拡張子で保存します。

ファイルをダブルクリックします。

3行のコードでSeleniumのWebドライバがプログラム的にWebページを開くようになりました。

では、"Bot "クラスを作成しましょう。

プログラムが何を達成したいのかを考えてみるのは良いアイデアです。

私はこれを段階的に行うのが好きです。そして、これらのステップをボットの機能に分解していきます。
1) プログラムでウェブページに行きたい
2) いくつかのデータをスクレイプしたい
3) そのデータを変数として渡したい
4）そのデータをクラウド上のファイルに保存したい

まずは基本的なSeleniumの「Bot」クラスを定義してみましょう。

```
from selenium import webdriver

class Bot():
    def __init__(self,url):
        self.browser = webdriver.Firefox()
        self.url = url
    def get_web_page(self):
        self.browser.get(self.url)
bot = Bot("http://www.baidu.com/")
bot.get_web_page()
```
以上が私たちのプログラムを編成するためのより合理的なクラスベースの構成です。

クラスを設定します。ブラウザ変数を Firefox Webdriver と定義します。クラスに渡すURLを定義します。次に、基本的なウェブページ取得関数を作成し、初期化時に定義した URL でブラウザを呼び出します。

スクリプトを実行してみましょう。スクリプトはBotクラスを初期化して実行します。Selenium webdriverはFirefoxブラウザのウィンドウを開き、www.baidu.com にアクセスします。

その前に、暗号データ取得関数を定義します。www.coinwatch.com にアクセスして、データを取得したい要素のxpathを取得します。そして、ビットコインのマーケットデータをスクレイプします。

このタスクには、Firefoxのウェブ開発者ツールが適しているので、それを使って必要な要素のxpathを見つけます。

www.coinwatch.com にアクセスし、右上の検索バーの上にマウスを移動します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/5580602d-783d-08be-3147-46fb54c2a71e.png)

検索ボックスの要素を右クリックし、メニューから「Inspect Element」を選択します。

ページの下部に、要素がハイライトされたインスペクタウィンドウが開きます。インスペクタでハイライトされたテキストを右クリックします。コピーサブメニューに移動し、Xpathをコピーを選択します。これで、その要素の Xpath がクリップボードに保存され、Python Selenium スクリプトに貼り付けられます。投稿ボタンへのxpathも取得しておきましょう。

さあ、作業を始めましょう

```
from selenium import webdriver
class Bot():
    def __init__(self,crypto):
        self.browser = webdriver.Firefox()
        ### CRYPTO TO SEARCH FOR
        self.crypto = crypto
    def get_crypto_data(self):
        self.browser.get("https://www.coinwatch.com/")
        ### FIND SEARCH FORM AND IMPUTE KEY WORD
        print("FINDING SEARCH FORM")
        element = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/header/section[3]/div/div/div/div[1]/div/input")
        element.clear()
        element.send_keys(self.crypto)
        element = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/header/section[3]/div/div/div/div[1]/div/div/button")
        element.click()


bot = Bot("BTC")
bot.get_crypto_data()
```
上記では、ウェブドライバを初期化しています。ここでは、暗号通貨の検索語となる変数 crypto を定義します。次に、このcrypto変数をクラスに渡し、selfパラメータを指定してget_crypto_data関数に渡します。get_crypto_data関数では、Webブラウザを呼び出して https://www.coinwatch.com/ を取得します。Webページを呼び出したら、コピーしたxpathから要素を探します。最初の要素は検索ボックスです。最初に検索要素をクリアしてから、引数としてcrypto変数を送信します。次に、送信ボタンを見つけてクリックします。botをbotとしてインスタンス化し、検索したいcryptoとして "BTC "を渡します。

ビットコインのメインページに移動する必要があります。今、私たちがデータを収集したいすべての要素にすべてのXpathsを取得し、コピーする機会を得てみましょう。私は今のところ、私たちは価格、キャップ、24時間のボリュームと24時間の変化が必要だと考えています。私たちのスクリプトでこれらの値を保持するために変数を作成してみましょう。次に、クラス全体の変数をget_crypto_data関数に渡します。要素が配置されたら、Seleniumの.textメソッドで要素のテキスト内容を取得します。そして、ターミナルでプリントアウトします。Webページによっては、DOMの要素を読み込むのに時間がかかる場合があるので、要素が見つからないなどのエラーが発生した場合は、一定期間待つ必要があるかもしれません。これを行う最もシンプルな方法は time.sleep() を使うことです。

これを実行して何が起こるか見てみましょう。

```
from selenium import webdriver
import datetime
import time

class Bot():
    def __init__(self,crypto):
        self.browser = webdriver.Firefox()
        ### CRYPTO TO SEARCH FOR
        self.crypto = crypto
        self.price = None
        self.cap = None
        self.volume_24h = None
        self.change_24h = None
    def get_crypto_data(self):
        self.browser.get("https://www.coinwatch.com/")
        ### FIND SEARCH FORM AND IMPUTE KEY WORD
        print("FINDING SEARCH FORM")
        elem = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/header/section[3]/div/div/div/div[1]/div/input")
        elem.clear()
        elem.click()
        elem.send_keys(self.crypto)
        elem = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/header/section[3]/div/div/div/div[1]/div/div/button")
        time.sleep(1)
        elem.click()
        ### GET MARKET DATA
        print("GETTING MARKET DATA")
        time.sleep(5)
        self.price = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/main/div/div/article/div[1]/div/div[3]/div/div/span").text
        self.cap = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/main/div/div/article/div[2]/div/main/div[1]/section/div[1]/div/div[2]/div/div[1]/span[2]").text
        self.volume_24h = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/main/div/div/article/div[2]/div/main/div[1]/section/div[1]/div/div[2]/div/div[2]/span[2]").text
        self.change_24h = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/main/div/div/article/div[2]/div/main/div[1]/section/div[1]/div/div[2]/div/div[8]/span[2]").text
        print("PRINTING MARKET DATA")
        print("PRICE " + str(self.price))
        print("CAP " + str(self.cap))
        print("24H VOLUME " + str(self.volume_24h))
        print("24H CHANGE " + str(self.change_24h))
        self.browser.close()
        return
bot = Bot("BTC")
bot.get_crypto_data()
```
これで、Botクラス全体に渡すことができる変数としてのデータを手に入れることができました。これをwrite_file関数に渡してみましょう。そして、システムのタイムスタンプを付けてアリババのクラウド上のローカルファイルに保存します。

```
def write_file(self):
    save_file = open(self.crypto + "_market.txt","a")
    time_stamp = str(datetime.now())
    save_file.write("\n" + time_stamp + "\n")
    save_file.write("\nPRICE: " + str(self.price))
    save_file.write("\nCAP: " + str(self.cap))
    save_file.write("\n24H VOLUME: " + str(self.volume_24h))
    save_file.write("\n24H CHANGE: " + str(self.change_24h))
```
上記のコードでは、crypto変数をmarket.txtに連結したファイルを、書き込むファイル名としてオープンしています。a "は付録モードでファイルを開きますので、前のデータを上書きしないようにします。次に、日付と時刻を文字列として呼び出すためにtime_stamp変数を作成します。次に、市場データを文字列としてsave_fileに書き込みます。n」を連結した部分が改行になっているので、すべてが1行に収まらないようになっています。

もちろん、Botクラスを初期化する際に引数を変更することで、この方法でどんな暗号もスクレイプすることができます。Etheriumのマーケットデータをスクレイプしてみましょう。

```
btc_bot = Bot("BTC")
eth_bot = Bot("ETH")
btc_bot.get_crypto_data()
btc_bot.write_file()
eth_bot.get_crypto_data()
eth_bot.write_file()
```
これで、データセットを取得して変数として返す自動化された方法ができました。これをローカルファイルに書き込むことができます。このデータは、例えばデータ分析のためのアリババ機械学習サービスや、トラッキングのためのリレーショナルデータベースに差し込むことができます。

以下は最終的なコードです。

```
from selenium import webdriver
from datetime import datetime
import time

class Bot():

    def __init__(self,crypto):
        self.browser = webdriver.Firefox()
        ### CRYPTO TO SEARCH FOR
        self.crypto = crypto
        self.price = None
        self.cap = None
        self.volume_24h = None
        self.change_24h = None
    def get_crypto_data(self):
        self.browser.get("https://www.coinwatch.com/")
        ### FIND SEARCH FORM AND IMPUT KEY WORD
        print("FINDING SEARCH FORM")
        elem = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/header/section[3]/div/div/div/div[1]/div/input")
        elem.clear()
        elem.click()
        elem.send_keys(self.crypto)
        elem = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/header/section[3]/div/div/div/div[1]/div/div/button")
        time.sleep(1)
        elem.click()
        ### GET MARKET DATA
        print("GETTING MARKET DATA")
        time.sleep(5)
        self.price = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/main/div/div/article/div[1]/div/div[3]/div/div/span").text
        self.cap = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/main/div/div/article/div[2]/div/main/div[1]/section/div[1]/div/div[2]/div/div[1]/span[2]").text
        self.volume_24h = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/main/div/div/article/div[2]/div/main/div[1]/section/div[1]/div/div[2]/div/div[2]/span[2]").text
        self.change_24h = self.browser.find_element_by_xpath("//html/body/div[1]/div/div/div/div/main/div/div/article/div[2]/div/main/div[1]/section/div[1]/div/div[2]/div/div[8]/span[2]").text
        print("PRINTING MARKET DATA")
        print("PRICE " + str(self.price))
        print("CAP " + str(self.cap))
        print("24H VOLUME " + str(self.volume_24h))
        print("24H CHANGE " + str(self.change_24h))
        self.browser.close()
        return

    def write_file(self):

        time_stamp = str(datetime.now())

        save_file = open(self.crypto + "_market.txt","a")
        save_file.write(self.crypto)
        save_file.write("\n" + time_stamp + "\n")
        save_file.write("\nPRICE: " + str(self.price))
        save_file.write("\nCAP: " + str(self.cap))
        save_file.write("\n24H VOLUME: " + str(self.volume_24h))
        save_file.write("\n24H CHANGE: " + str(self.change_24h) + "\n")

btc_bot = Bot("BTC")
eth_bot = Bot("ETH")

btc_bot.get_crypto_data()
btc_bot.write_file()

eth_bot.get_crypto_data()
eth_bot.write_file()
```
*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*