web-dev-qa-db-ja.com

Selenium:Cookieを使用してログインしようとしています-「現在のドメインにのみCookieを設定できます」

私が達成しようとしていること

Seleniumヘッドレスを使用してCookieを有効にする必要があるWebサイトにログインしようとしていますが、ドライバーにPhantomJSを使用しています。

問題

最初にSelenium IDEを使用して手順を記録しました。Firefoxを使用すると正常に動作します(ヘッドレスではありません)。次に、コードをPython 「現在のドメインにのみCookieを設定できます」というエラーがスローされるため、ログインします。なぜこの問題が発生するのかわかりません。正しいドメインにいないのですか?

コード

from Selenium import webdriver
from Selenium.webdriver.common.by import By
from Selenium.webdriver.common.keys import Keys
from Selenium.webdriver.support.ui import Select
import unittest, time, re

        self.driver = webdriver.PhantomJS()
        self.driver.implicitly_wait(30)
        self.base_url = "https://login.example.com"

        driver = self.driver
        driver.get(self.base_url)

        all_cookies = self.driver.get_cookies()

        # It prints out all cookies and values just fine
        for cookie in all_cookies
            print cookie['name'] + " --> " + cookies['value']

        # Set cookies to driver
        for s_cookie in all_cookies:
            c = { s_cookie['name'] : s_cookie['value']}
            # This is where it's throwing an error saying "Can only set Cookies for current domain
            driver.add_cookie(c)

        ...

私が試したこと

DictにCookieを保存し、別のドメインに移動し、元のドメインに戻ってCookieを追加してからログインしようとしましたが、それでも機能しません( このスレッド で提案されているように) =)

どんな助けでも大歓迎です。

12
simeg

各Cookieのペアを調査します。私は同様の問題に遭遇し、いくつかのクッキーはグーグルのものでした。 Cookieが現在のドメインにのみ追加され、同じドメインに属していることを確認する必要があります。その場合、あなたの例外が予想されます。ちなみに、正しく思い出せば、localhostを使用してCookieを追加することはできません。 IPアドレスに変更します。また、特別に取得しているCookieのドメインと有効期限の情報を調べてください。彼らがnullを返しているかどうかを確認してください

編集

Gmailでこの簡単なテストを行って、あなたが間違ったことを示しました。一見したところ、部分的なCookieとペアを取得して、それをドメインに追加しようとしていることに気づきませんでした。 Cookieにはドメイン、パス、有効期限などの情報が含まれていないため、現在のドメイン(127.0.0.1)にCookieを追加しようとして、意味をなさない誤解を招く情報をスローしていました。注意:有効なCookieであるためには、欠落している正しいドメインと有効期限の情報が必要です。

import unittest
from Selenium.webdriver.common.by import By

from Selenium import webdriver


__author__ = 'Saifur'


class CookieManagerTest(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.PhantomJS("E:\\working\\Selenium.python\\Selenium\\resources\\phantomjs.exe")
        self.driver.get("https://accounts.google.com/ServiceLogin?service=mail&continue=https://mail.google.com/mail/")
        self.driver.find_element(By.ID, "Email").send_keys("userid")
        self.driver.find_element(By.ID, "next").click()
        self.driver.find_element(By.ID, "Passwd").send_keys("supersimplepassword")
        self.driver.find_element(By.CSS_SELECTOR, "[type='submit'][value='Sign in']").click()
        self.driver.maximize_window()

    def test(self):
        driver = self.driver
        listcookies = driver.get_cookies()

        for s_cookie in listcookies:
            # this is what you are doing
            c = {s_cookie['name']: s_cookie['value']}
            print("*****The partial cookie info you are doing*****\n")
            print(c)
            # Should be done
            print("The Full Cookie including domain and expiry info\n")
            print(s_cookie)
            # driver.add_cookie(s_cookie)


    def tearDown(self):
        self.driver.quit()

コンソール出力:

D:\ Python34\python.exe "D:\ Program Files(x86)\ JetBrains\PyCharm Educational Edition 1.0.1\helpers\pycharm\utrunner.py" E:\ working\Selenium.python\Selenium\python\FirstTest。 py :: CookieManagerTesttrueテストは午前9時59分に開始されました.。

*******あなたがしている部分的なクッキー情報*******

{'PREF': 'ID = *******:FF = 0:LD = en:TM = *******:LM = *******:GM = 1:S = ******* '}

ドメインと有効期限情報を含む完全なCookie

{'httponly':False、 'name': '*******'、 'value': 'ID = *******:FF = 0:LD = en:TM = **** ***:LM = 1432393656:GM = 1:S = iNakWMI5h_2cqIYi '、'パス ':'/'、'有効期限 ':' 2017年5月22日月曜日15:07:36GMT '、'セキュア ':False、'有効期限 ':*******、'ドメイン ':' .google.com '}

注意:意図的に一部の情報を*******に置き換えました

5
Saifur

一部のWebページでは、WebドライバーでサポートされていないCookieで使用するキーが多すぎると、現在のドメインにCookieを設定していることを100%確信している場合でも、「現在のドメインにのみCookieを設定できます」というエラーメッセージが表示されます。そのようなウェブページの例は " https://stackoverflow.com/ "です。この場合、以前のいくつかの投稿で述べたように、必要なキーのみがCookieに追加されていることを確認する必要があります。

driver.add_cookie({k: cookie[k] for k in   ('name', 'value', 'domain', 'path', 'expiry') if k in cookie}) 

対照的に、一部のWebページでは、Webドライバーに必要なCookieのキーが少なすぎるため、最初の問題を修正した後、「現在のドメインにのみCookieを設定できます」という「errorMessage」が表示されます。このようなWebページの例は「 https://github.com/ "」です。このWebページのCookieにキー「有効期限」を追加する必要があります。

    for k in ('name', 'value', 'domain', 'path', 'expiry'):
        if k not in list(cookie.keys()):
            if k == 'expiry':
                cookie[k] = 1475825481

それらをすべてまとめると、完全なコードは次のようになります。

# uncommented one of the following three URLs to test
#targetURL = "http://pythonscraping.com"
targetURL = "https://stackoverflow.com/"
#targetURL = "https://github.com/"

from Selenium import webdriver
driver = webdriver.PhantomJS()
driver.get(targetURL)
driver.implicitly_wait(1)
#print(driver.get_cookies())

savedCookies = driver.get_cookies()
driver2 = webdriver.PhantomJS()
driver2.get(targetURL)
driver2.implicitly_wait(1)
driver2.delete_all_cookies()

for cookie in savedCookies:
    # fix the 2nd problem
    for k in ('name', 'value', 'domain', 'path', 'expiry'):
        if k not in list(cookie.keys()):
            if k == 'expiry':
                cookie[k] = 1475825481
    # fix the 1st problem
    driver2.add_cookie({k: cookie[k] for k in ('name', 'value', 'domain', 'path', 'expiry') if k in cookie})    
print(cookie)   

driver2.get(targetURL)
driver2.implicitly_wait(1)
1
Jun-Lin Lin

@Saifurが上で言ったことの最後にコメントを追加するつもりでしたが、完全なコメントを保証するのに十分な新しいコンテンツがあると思いました。

これとまったく同じエラーが発生した私にとっての啓示は、Seleniumの使用は、実際にブラウザーを開いて物理的にクリックして入力する場合とまったく同じように機能することでした。これを念頭に置いて、ユーザー/パスをSeleniumに入力し、click()を押すと、Seleniumドライバーは、認証が成功すると、自動的にCookieを保持します。したがって、保存した(おそらく間もなく期限切れになる)Cookieを壊す必要がなくなります。これに気付くのは少しばかげた感じでした。すべてがとても簡単になりました。

上記の@Saifurのコードをテンプレートとして使用して、いくつかの調整を行い、この例で実行するための余分なクラス全体が少し過剰であると感じるものを削除しました。

url = 'http://domainname.com'
url2 = 'http://domainname.com/page'
USER = 'superAwesomeRobot'
PASS = 'superSecretRobot'

# initiates your browser 
driver = webdriver.PhantomJS() 
# browses to your desired URL
driver.get(url)             
# searches for the user or email field on the page, and inputs USER   
driver.find_element_by_id("email").send_keys(USER)
# searches for the password field on the page, and inputs PASS
driver.find_element_by_id("pass").send_keys(PASS)
# finds the login button and click you're in
driver.find_element_by_id("loginbutton").click()

ここから、アドレス指定するページを参照できます

driver.get(url2)

注意: 下にスクロールすると自動ロードされる最新のサイトがある場合は、これを使用すると便利な場合があります。

driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

また、@ simegは、Seleniumは、ページが読み込まれるまでページが返されるまで自動的に待機することになっていることに注意します(はい、参照されているAJAXの問題があります) 、そのため、数秒待つ必要がある場合があります-ロードに30秒以上かかるページはどれですか?!)waitコマンドを実行する方法は、実際のページ自体ではなく、PhantomJSがロードされるのを待つだけです。組み込み関数を考えると、私には役に立たないようです。

Driver.getメソッドは、URLで指定されたページに移動します。 WebDriverは、ページが完全にロードされる(つまり、「onload」イベントが発生する)まで待機してから、テストまたはスクリプトに制御を戻します。ページがロード時に大量のAJAXを使用している場合、WebDriverはいつ完全にロードされたかを認識できない可能性があることに注意してください。

ソース: http://Selenium-python.readthedocs.io/getting-started.html#example-explained

これが誰かに役立つことを願っています!

1
ntk4