PythonでSelenium

Python3の環境でSeleniumを使ったのでメモとして記しておきます。UbutnuServerで実行したので基本的にheadlessな環境です。
プログラミング全般について言えることですが、英語のドキュメントを読めば大抵解決します。しかし、その時間をとられたくない・大まかに日本語でとらえておきたい方にこの記事は役に立つと思います。メモ書きのようなものなので、全てのことを網羅することはできませんがよく使うと思ったことだけに重点を置いてまとめました。

Ubuntu 16.04LTS
Python3.52+Selenium3.12.0+PhatomJS2.1.1


Seleniumは僕達の分身、PhantomJSはブラウザです
(Seleniumを使ってPhantomJS,Chrome,Firefoxを操作する)
***
#Seleniumの導入

```
pip3 install selenium
```
#ブラウザの導入
PhantomJS
http://phantomjs.org/download.html
Chrome
https://sites.google.com/a/chromium.org/chromedriver/downloads
Firefox
https://github.com/mozilla/geckodriver/releases
好きなものをダウンロードし、解凍して/usr/local/bin/(パスの通っているところ echo$PATHで確認できる)にコピーする

***
#Seleniumを使ってみる
まずひな形がこんな感じ

```Python
from selenium import webdriver
#ブラウザを指定して起動
driver = webdriver.PhantomJS()
#Googleのサイトにアクセス
driver.get('https://www.google.com/')
#この下のdriver.quitまでの間にいろいろな処理を書いていく

#ブラウザを終了させる
driver.quit()
```

driver = で指定した名前を使って(driver.getなどの.getの前の文字)を統一する(ほかのサイトではdriver = の場合が多い)
webdriver.の後のところには導入したブラウザを書く(下の場合PhantomJS,Chromeの場合Chrome,FirefoxだったらFirefox)
webdriver.PhantomJS()のカッコの中にはPhantomJSでダウンロードして解凍したものがあるディレクトリを書いておく(下の場合'/usr/local/bin/phantomjs')


#各種処理

(driver.getからdriver.quitの間に書く)

```Python:ブラウザを指定して起動
driver = webdriver.Chrome()
```
```Python:サイトにアクセス
#()の中にURLを''で囲んで指定する
driver.get()
```
```Python:ブラウザを終了させる
driver.quit()
```

```Python:現在のブラウザを閉じる
driver.close()
```

```Python:アクティブなウインドウに切り替え
driver.switch_to.window(driver.window_handles[1])
```

```Python:一番下までスクロールする
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
```

```Python:スクリーンショットをとる
#()の中に保存先のファイルを''で囲んで指定する
driver.save_screenshot()
```

```Python:ブラウザを更新する
driver.refresh()
```

```Python:現在のサイトのURLを取得
url = driver.current_url
```


```Python:現在のサイトのHTMLを取得
html = driver.page_source
```

htmlを取得してBeautifulSoupに渡すことも可能

```Python:ボタンをクリックする
.click()
```

```Python:【例】btnAというnameを指定してクリックする
driver.find_element_by_name('btnA').click()
```

```Python:文字を入力する
#()の中に文字を''で囲んで指定
.send_keys()
```

```Python:【例】txtNameというidを指定してPythonという文字を入力する
driver.find_element_by_id('txtName').send_keys('Python')
```

```Python:textを取得する
.text
```

```Python:【例】spanタグのidが"js_paramExpNum"である要素のtextを取得する
ExpNum = driver.find_element_by_xpath('//span[@id="js_paramExpNum"]').text
```

```Python:テキストを削除する
.clear
```

```Python:idで取得
#()の中にidを''で囲んで指定
driver.find_element_by_id()
```

```Python:classで取得
#()の中にclassを''で囲んで指定
driver.find_element_by_class_name()
```

```Python:nameで取得
#()の中にnameを''で囲んで指定
driver.find_element_by_name()
```

```Python:要素を指定して探す
from selenium.webdriver.common.by import By
#idがsrchtxtのものを上から1つ探す(下の2つの例は同じ意味)
driver.find_element_by_xpath("//*[@id='srchtxt']")
driver.find_element(By.XPATH, "//*[@id='srchtxt']")
```

```Python:idがsrchtxtのものを全て探す。タグは指定していない(//*の部分)
driver.find_elements_by_xpath("//*[@class='srchtxt']")
```

```Python:aタグのclassがbtnNormalのものを見つける。タグはaタグを指定している(//aの部分)
driver.find_element_by_xpath("//a[@class='btnNormal']")
```

#待機処理

Webサイトにはajaxを使用してページを読み込んでから画面を書き換えるといったことが行われているものもある。
Seleniumは要素が存在しない状態で参照した場合に、NoSuchElementExceptionを発生させるので、それを回避するためにSeleniumで待機処理を行う。

```Python:例
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver.get('https://www.yahoo.co.jp/')
#指定された要素(id=myDynamicElement)が表示状態になるまで待機する
element = WebDriverWait(driver, 10).until( expected_conditions.presence_of_element_located((By.ID, "myDynamicElement")) )
```

この処理では、最大10秒間指定した要素が存在するまで待機します。

```Python:例
driver.implicitly_wait(10)
```
time.sleep()と同じ処理です。
指定した待ち時間(10秒)の間、要素が見つかるまで(ロードされるまで)待機させる方法です。
デフォルトでは0になっていますが、設定すると各処理で待機処理をしなくて済むので便利になります。

urlが変わったら次の操作に移行する。

```Python:例
if 'https://vcard.ameba.jp/raid/boss/discovery-animation?eventId=' in driver.current_url:
  print("True")
  driver.get('https://vcard.ameba.jp/raid/quest/detail?eventId=76')
else:
  print("False")
  pass
```

よく使う待機処理

```Python:テキストボックスが表示状態になるまで待機する
#スクリプトの先頭で
#from selenium.webdriver.support import expected_conditions
#が必要になる
id = WebDriverWait(driver, 10).until(expected_conditions.visibility_of_element_located((By.NAME, "accountId")))
```


```Python:例
try:
  #div要素のclassがjs_attackBtnが存在するならばクリックする
  #存在しないならexcept以下の処理を行う。
  driver.find_element_by_xpath('//div[@class="js_attackBtn"]')
  driver.find_element_by_xpath('//div[@class="js_attackBtn"]').click()
  print("ボタンが存在するよ")
except:
  print("ボタンが存在しないよ")
  driver.find_element_by_id("canvas").click()

```


これらを組み合わせると
1.[Google](https://www.google.com/)のサイトに行く
2.検索の枠に文字を入力する
3.検索する
という処理が書けるようになります
基本的に上記の処理を組み合わせることでスクリプトを書いていきます。

```Python:各種処理の組み合わせ例
#coding: utf-8
#!/usr/bin/env python
from selenium import webdriver
#ブラウザを指定して起動
browser = webdriver.PhantomJS()
#Googleのサイトにアクセス
driver.get('https://www.google.com/')
#検索テキストボックスの要素をname属性名から取得して検索の枠に文字を入力
driver.find_element_by_name('q').send_keys("妹欲しい")
#検索ボタンをnameで指定して押す
driver.find_element_by_name('btnK').click()
#スクリーンショットを'/home/yasudaak/ダウンロード/にtest.pngという名前で保存'
driver.save_screenshot('/home/yasudaak/test.png')
#ブラウザを終了させる
driver.quit()
```
#close(), quit()してもchromeが裏で動いてた
```
killall -v chrome chromedriver
```

をcronのコマンドの後ろに&&の後に書いた。同時並行させて動かしているseleniumのスクリプトがある場合は注意

参考にしたサイト
[Selenium with Python](http://selenium-python.readthedocs.io/)
[Selenium 日本語ドキュメント](http://www.seleniumqref.com/api/webdriver_abc_python.html)
[Seleniumクイックリファレンス](http://oss.infoscience.co.jp/seleniumhq/docs/index.html)

#クローリングとスクレイピングで使える道具

[requests](https://bit.ly/1VAZCX9)
[BeautifulSoup](https://bit.ly/2xiK0mN)
[feedparser](https://bit.ly/2krLJwI)
[MySQL+mysqlclient](https://bit.ly/2shYIo3)
[MongoDB](https://bit.ly/1VKPNp7)
[CacheControl](https://bit.ly/2IR1c3Z)
[Mecab](https://bit.ly/2KXQCZz)
[pandas](https://bit.ly/2hH6dDN)
[matplotlib](https://bit.ly/2slaQVI)
[pdfminer.six](https://bit.ly/2L0X2qV)
[RoboBrowser](https://bit.ly/2IQfVw0)
[selenium](https://bit.ly/2xh4RHb)
[feedgenerator](https://bit.ly/2IOOsuM)
[Scrapy](https://bit.ly/2sat1xU)
[BigQuery+bigquery-python](https://bit.ly/2kuhkh6)