Selenium

下位ページ

Content

selenium

JavaScriptも動かしてページを表示させているページだったので、ブラウザも一旦起動する方法をとった。その際に使った。


  1. browser を動かせる状態にする
  2. ブラウザ上の要素を取得する
  3. 走査を加える
  4. 2,3を繰り返す

webdriver

ブラウザを開く(操作する?)ためのドライバーも準備(selenuimのぺーじからダウンロードした)
自動でパスが通る場所においていなかったので、バスを通す
from selenium import webdriver


# version 2.0 は webdriver付属、みたいに書いてあったのだが・・・
driver = webdriver.Firefox(executable_path="C:/Users/.../geckodriver.exe")
driver.get(url)
print(driver.find_element_by_id("zansu6").text)
driver.close()

ページを取得する(開く)

driver.get(url)

ウィンドウを閉じる

driver.close()


要素の取得


要素の取得には2種類ある。
driver.find_element_...
driver.find_elements_...
elementは最初に出会った要素を取得している。
一方、elementsは出会ったすべての要素を取得している。なので、forでまわしたりして使う。(一度にすべての要素になにか操作を加えることは出来るんだろうか?)
なお、elementsでタグを取得すると、子要素だけでなく、孫・ひ孫、、、まで取得している模様。

idで

classで

cheeses = driver.find_elements_by_class_name("cheese")

tagで


要素を操作する

取得した要素を element とする。

要素をクリックする

element.click()

テキストを取得する

element.text
textプロパティで取得できる。このとき、タグは含んでいない。
Getting text values - Selenium

テキストを入力する

element.send_keys(string)

キー操作を入れる


from selenium.webdriver.common.keys import Keys

element.send_keys(Keys.ENTER)


ヘッドレス化

データを取得するだけなら、ウィンドウを開く必要はない。「ヘッドレスブラウザ」は画面を表示しないブラウザ。
Chrome や Firefox はヘッドレスブラウザとして動かすことができる。

Firefoxの場合
from selenium.webdriver.firefox.options import Options
 
# selenium と geckodriver を つかって、firefox を開く(ヘッドレス)
options = Options()
options.add_argument("--headless")
driver = webdriver.Firefox(executable_path="/PathOfFirefox/geckodriver.exe", \
                           firefox_options=options)
 

2段階認証が必要な必要なサイトを何とかする

  • やりたかったこと
    • 自分があるサイトに構築している、複数ページに渡るリストを取得すること
  • 現状
    • リスト取得に対してはAPIが公開されていない。
    • リストは単純な追加作業ばかりでなく、途中で部分的に削除することもある
    • しかしながら、そのサイトは「独自のアカウント」がない
      • googleだったりYahooだったりDocomoだったりのアカウントを使っての登録が必須
    • 自分が使っているgoogleのアカウントで入ろうとすると、スマホ端末での認証が必要となり、ウェブの範囲を超えている。

思いつく、「ステップ」としては次くらいか?
  1. とりあえず認証を手作業でやる
  2. 一度認証できたら、cookieなどで記憶させて次回以降のログインを飛ばす
  3. (最初から自動ログインにする←2ができていたら、多分、この作業はあまり意味がない)

とりあえず認証作業は手作業で行って、途中から自動にする

作業の途中からseleniumに任せる方法がわからなかったので、最初はログインの認証画面に遷移されたタイミングで
import time
time.sleep(60)
 
sleepメソッドで止めようとしたが、「確立された接続が。。。。」というエラーメッセージで止まってしまう。さらに言えば、selenium IDEで作業を追ってみても、「次へ」ボタンがうまく特定できない。この辺は実力の無さか?

WebDriverWait

WebDriverWaitで作業を止めて、作業ができる状態になったら、再スタートするようにした。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
...
wait = WebDriverWait(driver,120)
wait.until(EC.title_contains("リスト"))
 

流れは
  • ログインができるページに飛ぶ(自動)
  • google認証のページに飛ぶ(手動)
  • googleのアカウント名を入力→確認ボタン(手動)
  • googleのアカウントのパスワードを入力→確認ボタン(手動)
  • スマホで2段階認証(当然手動)
  • リダイレクト
  • トップページ→目的のページへのリンククリック(手動)
  • 目的にページが開かれたら、発火(ここから自動化)
  • 認証を済ませる。そのあと、リストのあるページに行く。
まだまだ自動化できる部分もあるが、エラーもぼちぼち出て、面倒になって、この方法に。

wait.until(value)
value が真になったら発火させる

何で発火させるかは、expected_conditions を使って指定している。
本来の使い方は、動的に表示データを生成するようなページに向けての模様。

使い方の分類としては明示的な待機になるのか?「何を待つか」に関して、準備されているものもあれば、独自に作ることもできるらしい。



expected_conditions 要素が表示されたら発火

要素の表示で使い場合は、
EC.presence_of_element_located


ログイン情報に cookie を使用する

普段はログイン作業を通らずにリストが表示される、ということは、クッキーにセッション情報か何かが残っているわけで、一度ログインをすればクッキーが使えるはず。

※最初からログインした状態のブラウザから読み出した cookie 情報でログインすればよかったのだが、後述のミスで、cookie 情報の読み込みができなかった。。。

cookie 情報を書き出す

driver.get_cookies()
複数クッキーがあるかもしれないので、読み出した後 for か何かで回したものを print すればOK
.get_cookies() - selenium

driver.get_cookie(name)
もあるが、nameがわからないと呼び出せないので、上が良い?

cookie 情報を読み込む

driver.add_cookie(cookie)

cookie の情報としては、dict 型で記述した cookie を準備しておいて、読み込ませる。
読み込ませる(書き込む)タイミングは、関連付けるドメインで get した後。まだ開いていない状態で add_cookie をすると
Document is cookie-abverse
とエラーが出て止まってしまう。

最終更新:2019年01月04日 22:21