wed上の情報を集めるにはスクレイピングという方法がありますが、JavaScriptでリンクが形成されていたりするとソースを解析しただけでは、リンク先のアドレスが分からないので目的の情報にたどり着くことはできません。
そこで使うのがseleniumになります。
seleniumではソースを取得することももちろんできますが、JavaScriptで形成されたリンクを動かすことができます。
これができることでpythonでプログラミングすることで、ブラウザを自動操作できます。
ブラウザーのインスタンスを作成
前回のseleniumの記事ではPhantomJSをを使用しましたが、開発も停止しているということで、開発者も他の物をつかってくれと言っているらしいので、今後はfirefoxを使おうと思います(いまのところ)。s51517765.hatenadiary.jp
s51517765.hatenadiary.jp
PhantomJSはヘッドレスブラウザですが、firefoxは画面あり・なしの両方が使えるので、Debugは画面ありで行い、運用は画面なしでおこなうということも切り替えることができます。
firefoxのwindowsでのヘッドレスの使い方は↓を参考にしました。
Python+seleniumでwebdriverとしてheadlessなFirefoxを使う方法 | Sakaki333.com
引数で、ブラウザの種類と画面ありなしを指定します。
以下の関数でブラウザの切り替えをします。
firefoxにのみ最適化されていますので、chromeとPhantomJSは途中でErrorが出ることもあります。
from selenium.webdriver.support.ui import WebDriverWait from selenium import webdriver from selenium.webdriver.firefox.options import Options def browserOpen(driver): if driver== "h": options = Options() options.set_headless(Options.headless) geckodriver_path = "C:/ProgramData/Anaconda3/geckodriver.exe" #各自の環境での実行ファイルのパスを設定 driver = webdriver.Firefox(executable_path=geckodriver_path, options=options) print("Headless Firefox") elif driver =="f": driver = webdriver.Firefox() print("Firefox") elif driver== "c": print("Chrome") options = Options() driver=webdriver.Chrome() else: driver = webdriver.PhantomJS() print("PhantomJS") return driver
seleniumで要素を取得してデータを送る
Amaz〇nにログインするところを例に説明しますhttps://www.amaz〇n.co.jpのトップページから始めても構いませんが、プログラミングの工数を削減するため直アドレスで入れるところから始めます。
ログインしていない状態で、画面の下のほうに「サインイン」があるので、この先からスタートします。
ここからスタート
firefoxの画面上で右クリックすると、「要素を調査」というメニューを起動すると、HTMLが現れて、HTMLのタグをポイントすると、これに対応する画面上の要素がハイライトされます。
これより、このインプットボックスの要素のタグがinput id ="ap_email"
であることが分かり、id ="ap_email"
であることが分かります。
HTMLの画面上のタグ上で右クリックで、「コピー¥CSSセレクタ」と選択するとクリップボードに取得できます。
同様のことはchromeでもできます。
ここにメールアドレスを入れたいのでseleniumのsend_key
でデータを送ります。
email="aaa@gmail.com" driver.find_element_by_id("ap_email").send_keys(email)
その次は、「次へ進む」をクリックします。
これも同様に要素を探し、クリックを送ります。
driver.find_element_by_id("continue").click()
これがseleniumの基本と言っていいと思います。
タグのidは名前のようなもので、タグを特定することができます。
idがみつけられれば確実ですが、結構idがないのかどこにあるのかわからないとき、idではどうしてもうまくいかないときはX-pathを使うとうまくいきます。
たとえば、検索ボックスの虫眼鏡マーク。
driver.find_element_by_id("twotabsearchtextbox").send_keys(keyword) driver.find_element_by_xpath("/html/body/header/div/div[1]/div[3]/div/form/div[2]/div/input").click()
虫眼鏡はid="nav-search-submit-text
のようなのですが、これでid指定しても ”is not clickable”というErrorが返ってきました。
ポップアップや子windowに対応する
検索結果画面から、例えば一つ目の結果をクリックしたときは、その後扱うべき画面は2つ目の画面(タブ)になります。このとき、アクティブなタブを移動しなければなりません。
普段、人間向けのブラウザでは自動的に新しいタブがアクティブになったりしますが、ここでは明示的に遷移しなければなりません。
最初、ここで躓きました。
画面ありfirefoxでデバックしていると、画面は新しいタブに切り替わるのでidが見つからないのが気付きにくいです。
このようなときは、現在のアドレスを表示したり、タブの数をprint()したりするとわかりやすくなります。
検索画面から結果の1つ目をクリックし、新しいタブをアクティブにするには次のようになります。
ここで、新しいタブを立ち上げるには時間がかかることがあるのでsleepを入れるとうまくいくことがあります。
driver.find_element_by_id("result_0").click() time.sleep(3) driver.switch_to.window(driver.window_handles[1]) #2つ目のタブに移動、1つ目は[0] print(len(driver.window_handles)) #今認識されているタブの数を表示 -->2 とでる
時間をおいてもダメなときはスクロールしたり、適当な位置にクリックすると上手くいくという話もある。
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") #スクロール
ウィンドウの数を見て増えるまで待つ
WebDriverWait(driver, 3).until(lambda d: len(d.window_handles) > 1)
メインプログラム
def main(driver, keyword): driver =browserOpen(driver) # ログイン情報 login.pyに保存してある情報を読み込む email=login.email password=login.password twitter=login.twitter #twitter id tw_password=login.tw_password #twitter pass # ログイン url = "長いので省略" driver.get(url) driver.find_element_by_id("ap_email").send_keys(email) driver.find_element_by_id("continue").click() driver.find_element_by_id("ap_password").send_keys(password) driver.find_element_by_id("signInSubmit").click() time.sleep(3) driver.find_element_by_id("twotabsearchtextbox").send_keys(keyword) driver.find_element_by_xpath("/html/body/header/div/div[1]/div[3]/div/form/div[2]/div/input").click() # 検索結果の1つ目 driver.find_element_by_id("result_0").click() time.sleep(3) driver.switch_to.window(driver.window_handles[1]) # 検索結果の2つ目 # id="result_1" #Twiiter shere driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") time.sleep(15) driver.find_element_by_xpath('//*[@id="amzn-ss-twitter-share"]/div/a/i').click() time.sleep(3) #ポップアップが現れるまで待ち、アクティブ画面を遷移する WebDriverWait(driver, 3).until(lambda d: len(d.window_handles) > 2) driver.switch_to.window(driver.window_handles[2]) # テキストを取得 text=driver.find_element_by_id("status").text print("Original = "+text) driver.find_element_by_xpath('//*[@id="username_or_email"]').send_keys(twitter) driver.find_element_by_id("password").send_keys(tw_password) screen_shot(driver, 9) driver.find_element_by_xpath('/html/body/div[2]/form/div[3]/fieldset[2]/input').click() #ログインしてツイート text=text.replace("@さんから","") text = text.replace("Amazon.co.jp", "") text=text +" //python + seleniumによる自動投稿テスト" time.sleep(3) driver.find_element_by_id("status").clear() print("Shaping = "+text) driver.find_element_by_id("status").send_keys(text) driver.find_element_by_xpath('/ html / body / div[2] / form / div[3] / fieldset / input').click() print("Sucess get Twitter link!")
参考
qiita.comqiita.com
qiita.com
qiita.com