Seleniumを用いた自己満足のオークションショッピング

# Seleniumを用いた自己満足のオークションショッピング

<ヤフオクをクローリングしてみた>

## 免責

この文章に紹介された方法と実装はヤフオクと出品者をいじるための偉いことではありません。

また、こちらのソースを使用することと生じる結果は全部実行者の**ご自分自身の責任**でございます。

## 経緯

要件A : 最近、ヤフーオークションサイトでよく生活雑貨を買います。実店舗でも買えるものですが、ちょっと気になるデザインのものを安く買いたいという気持ちが出ています。ただし、沢山の中古商品が検索結果に出ていて、どちらを買えば一番良いのは商品や出品者への調査には時間かかりました。もちろん、商品情報は必ず自分で確認しないといけないですが、良い出品者をまず絞りたいです。

要件B : Seleniumにご存知の方は沢山いると思います。ウェブテストでよく使われているツールですが、人間の力を使わずに(AIではない)自動的にロボットのようにウェブ操作もやってくれられます。ウェブゲームで使われたら、物理チーターと言われます。ですから、ウェブ操作の手間も減らしたいです。

では、Seleniumを使って、良い出品者を絞っていきます。

## 目標

ヤフオクである商品を検索する時に、沢山のユーザの商品をパスして、取引をスムーズに最後まで行われる出品者の商品だけ確認します。その検索のアシスタントツールを作成し、良い出品者を絞ります。もちろん、全部出品者の情報もわかりやすく確認できるようにします。

こちらの良い出品者は以下と定義されます。

<*総合的に、悪い評価は0、良い評価の数は100点以上* >

本当に厳密的に、出品者としての良い評価の数を取得したいですが、全体(出品と落札)の良い評価の数を取得しています。また、実際にある検索条件で良い出品者を選ぶ時、こちらで定義した出品者は存在しない場合もあります。本当に悪戯入札の被害者、良くなった出品者等も選べられますが、どうしても人間の判断が必要だから、こちらの文章から離れています。

## 開発環境

開発環境の要件は下記のものです。

* **Windows** (OS)
* **Chrome** (ブラウザ)
* **ChromeのSeleniumドライバ**  ([ダウンロードリンク](https://sites.google.com/a/chromium.org/chromedriver/downloads))
* **Python 3** (言語、IDE)
* **Seleniumライブラリ**

AnacondaというツールがPythonの基本パッケージをまとめてインストールしてくれて、また「virtual env」みたいな複数の開発環境を簡単に用意してくれたので、その上に今回の環境を構築します。

まず、Python v3版のAnaconaを以下のページからダウンロードしてインストールします。


[  Downloads | Anaconda](https://www.anaconda.com/download/)

次に、Anaconda Prompt(ターミナル)から「selenium」という環境を作成し、切り替えて使用ます。

```
conda create -n selenium
activate selenium
```

また、seleniumのライブラリをインストールします。

```
pip install selenium
```

## 実装概要

### 1.ドライバの起動

ドライバでChromeを起動します。

```py
driver = webdriver.Chrome(CHROME_DRIVER_EXE)
```

### 2.ユーザ名の一覧を取得 (検索ページのページネーション)

すべてのユーザ名を取得するために、以下のように人間の操作をシミュレーションします。

---------------

1.検索ページを開く*
↓
*2.次の番号=1*
↓
*3.次の番号のリンクを押下*
↓
*4.現在のページにすべてのオークションのユーザ名を取得*
↓
*5.次の番号=次の番号+1*
↓
*6.次の番号のリンクを押下*
↓
*4～6 繰り返す*
...

-----

ソースコードの一部は以下となります。

```py
    driver.get('https://auctions.yahoo.co.jp/search/search?p=' + YAHOO_AUCTION_SEARCH_KEYWORD)
    
    next_page = 1
    user_list = {}
    while (True):
        tmp_list = yha_search_page_get_user_name(driver)
        for k,v in tmp_list.items():
            user_list[k] = v
        result = yha_nav_search_page_with_num(driver, next_page)
        if (result == None or result == 1):
            break
        next_page = next_page + 1
```

### 3.ユーザ情報の出品、落札のレビュー件数の取得
ユーザの評価ページは以下のように固定されているらしいです。(２０１８年３月２９日現在)

```
https://auctions.yahoo.co.jp/jp/show/rating?userID=ユーザ名
```

ユーザのレビュー件数は「非常に良い・良い」、「どちらでもない」と「非常に悪い・悪い」の３パターンで、以下のように抜き出します。

```py
    def yha_get_user_review_info(driver, xpath):
        user_total_review_list = {}
        total_review = driver.find_elements_by_xpath(xpath)
            
        for review in total_review:
           if (review.text.find('非常に良い・良い：') != -1 and
            review.text.find('どちらでもない：') != -1 and
            review.text.find('非常に悪い・悪い：') != -1):
                regex_text = '（([0-9]+)件）'
                pattern = re.compile(regex_text)
                review_list = pattern.findall(review.text)
                if (review_list != None and len(review_list) == 3):
                    user_total_review_list['positive'] = review_list[0]
                    user_total_review_list['neutral'] = review_list[1]
                    user_total_review_list['negative'] = review_list[2]
                break
        return user_total_review_list
```

### 4.出品者としてのネガチブコメントの取得(一部)

ユーザの出品者としてのネガチブコメントがあるページも以下のように固定されています。(２０１８年３月２９日現在)

```
https://auctions.yahoo.co.jp/jp/show/rating?userID=ユーザ名&role=seller&filter=-1
```

ネガチブコメントの「商品名」、「コメント」と「返答」セットのページ中のあるものを全部抜き出します。(１ページ最大２５件ですが、情報としては個人的に十分参考になります。)

```py
def yha_get_user_seller_negative_reviews(driver):
    user_negative_case_list = []
    line_list = driver.find_elements_by_xpath('//body//div//p//table//tbody//tr//td//table')
    for line in line_list:
        auction_item = {}
        if (line.get_attribute('innerHTML').find('RATING INFO') != -1):
            auction_name = get_element_by_xpath(line, './/tbody//tr//td//small//a')
            if auction_name:
                auction_item['商品名'] = auction_name.text
            comments = get_elements_by_xpath(line, './/tbody//tr//td//table//tbody//tr//td//small')
            last_label = 'コメント'
            for comment in comments:
                if (comment.text != 'すべてのコメント・返答を見る' and
                comment.text != 'コメント' and
                comment.text != '返答' and
                comment.text != '評価者'):
                    if last_label not in auction_item.keys():
                        auction_item[last_label] = comment.text
                else:
                    if (comment.text == 'コメント' or
                    comment.text == '返答' or
                    comment.text == '評価者'):
                        last_label = comment.text
        if len(auction_item) > 0:
            user_negative_case_list.append(auction_item)
    return user_negative_case_list
```

### 5.ドライバの終了

Chromeのウィンドウを終了させ、ドライバもオフします。

    driver.close()
    driver.quit()
## 結果とまとめ

このプログラムは簡単に個人的に一番ほしいユーザ情報をまとめました(JSON形式)。

実際の実行結果は以下となります。そして、「良い」出品者を絞り出しました。

```
おすすめの出品者 : b***e
非常に良い・良い : 310
どちらでもない : 0
非常に悪い・悪い : 0


おすすめの出品者 : b***g***
非常に良い・良い : 1266
どちらでもない : 2
非常に悪い・悪い : 0


おすすめの出品者 : n******
非常に良い・良い : 355
どちらでもない : 1
非常に悪い・悪い : 0

...
```

ログを見ると、以下のような商品データが貯められています。

```
{
   'b***e':{  
      'total_review':{  
         'positive':'310',
         'neutral':'0',
         'negative':'0'
      },
      'negative_case':[  

      ]
   },
   '*c**o':{  
      'total_review':{  
         'positive':'236',
         'neutral':'3',
         'negative':'1'
      },
      'negative_case':[  
         {  
            '商品名':'大人気*****************',
            'コメント':'商品は未発送*****。*******最悪*******。  (評価日時：6か月以内)'
         }
      ]
   },
   ...
}
```

## 最後

このSelenium勉強用のソースはGithubに公開されています。僕の遊びで、ライセンスはApache-2.0です。ソースの実行結果は今後保証しないので、ノークレームでお願いいたします。リンクは[ここ](https://github.com/qchin/crawling_yahoo_auction)です。