Python+SeleniumでDMM電子書籍の購入済み書籍の一覧を取得する



前々から買った本の一覧を見たかったのだが、以前試行錯誤しても全く上手くいかなかったので、

『Pythonクローリング&スクレイピング[増補改訂版] -データ収集・解析のための実践開発ガイド』



を読んで勉強して再トライした[^1]。

[^1]: 本当に読んだけど、実際は参考リンクの方が役に立った。この本は法律や規約などのことについても触れられているのでタメになる。




<br>

## 実際のコードと実行結果



```python
from selenium import webdriver
import time
import dmm_user_pass

# ユーザー名、パスワードを漏洩しないための簡易的な方法
# (同ディレクトリのdmm_user_pass.pyを絶対公開しないようにする)
USER = dmm_user_pass.USER
PASS = dmm_user_pass.PASS

# PhantomJSのドライバーを得る
browser = webdriver.PhantomJS()
browser.implicitly_wait(5)

# ログインページにアクセス(ログインすると即購入済みページに遷移されるはず)
url_login = "https://accounts.dmm.com/service/login/password"
browser.get(url_login)
print("ログインページにアクセスしました")

# テキストボックスに文字を入力
e = browser.find_element_by_id("login_id")
e.clear()
e.send_keys(USER)
e = browser.find_element_by_id("password")
e.clear()
e.send_keys(PASS)
# フォームを送信
browser.find_element_by_xpath("//form[@name='loginForm']//input[@type='submit']").click()
print("情報を入力してログインボタンを押しました")
time.sleep(10)

# DMM電子書籍の購入済みページを表示
# page1からloopで存在しないページになった場合にはurlが自動的に、
# https://book.dmm.com/library/?age_limit=all&expired=1になる(遷移したいページとcurrent urlが不一致)
url_purchased = 'https://book.dmm.com/library/?age_limit=all&expired=1&sort=old&page='
for i in range(1, 100):
    page_i = url_purchased + str(i)
    browser.get(page_i)
    time.sleep(5)
    if page_i != browser.current_url:
        break # 上のコメント通りに抜ける処理
    # 購入済みのタイトルを列挙
    links = browser.find_elements_by_css_selector(
        ".m-boxListBookProductBlock__main__info__ttl > a")
    for a in links:
        title = a.text
        print("-", title)
```

    /usr/local/lib/python3.7/site-packages/selenium/webdriver/phantomjs/webdriver.py:49: UserWarning: Selenium support for PhantomJS has been deprecated, please use headless versions of Chrome or Firefox instead
      warnings.warn('Selenium support for PhantomJS has been deprecated, please use headless '


```markdown
ログインページにアクセスしました
情報を入力してログインボタンを押しました
- モブサイコ100
- おしえて！ ギャル子ちゃん
（以下省略）

```

警告については後述。


今までにDMM電子書籍で購入した本の一覧を購入日が古い順で全て取得できた。




もう少し工夫すればリンクを取得したり、金額を持ってくるようなことも可能だと思うが、時間もかかるし面倒なので今回はやらない。 [^2]

[^2]: DMM電子書籍は巻数が複数あるものはひとまとめになっているので、複数巻あるものはリンク先がそのシリーズのページになっているが、複数巻ないものは直接作品詳細ページにリンクしているため、リンクを取得したり金額を持ってくる場合はそこの条件分岐などが必要である。



<br>



元々はrequestsモジュールでクローリングしようと思ったが、ログインが上手くいかなくてやめ、Seleniumにしたことですんなり上手くいってよかった。



seleniumは実際の操作をコードに起こすだけなので、ユーザー名・パスワード・ログインボタンの位置(htmlタグのclassやidで特定)さえ分かれば、内部でどんな処理が行われていようとログインできるはずなので、ログインが必要なサイトのクローリングは全部Seleniumで良いや〜という気がする。





<br>

## 参考リンク

- [【Python3】ログイン機能付サイトでスクレイピング【requests】【BeautifulSoup】](https://qiita.com/syunyo/items/36af8bcb501baf8c7014)

  - 続きの[【Python3】ブラウザを経由したスクレイピング(動的なページなど)【Selenium】](https://qiita.com/syunyo/items/09cc636344212112a6fc)の方も参考にした

- [デイリーパチンコに接続するコンテナを作った話](https://zokibayashi.hatenablog.com/entry/2019/08/30/011556)

  - DMMログインの部分をまんま拝借

- [SeleniumからHeadless Chromeを使ってみた](https://qiita.com/orangain/items/db4594113c04e8801aad)

  - `UserWarning: Selenium support for PhantomJS has been deprecated, please use headless versions of Chrome or Firefox instead`の警告が出ていたが、どうやらPhantomJSは開発が終わっているらしい。今回は一応動いたが、今後はChromeを用いていく。
  - PhantomJSをChromeに変える際に参考にした。特に[準備](https://qiita.com/orangain/items/db4594113c04e8801aad#%E6%BA%96%E5%82%99)の部分。

  - 実際のコードはほとんど変化ない

    ```Python
    # # PhantomJSのドライバーを得る
    # browser = webdriver.PhantomJS()
    # browser.implicitly_wait(5)
    # ↓
    
    # Chromeのドライバーを得る
    options = webdriver.ChromeOptions()
    options.add_argument('--headless') # 画面を表示しないオプション
    browser = webdriver.Chrome(options=options)
    browser.implicitly_wait(5)
    ```