hetare
@hetare

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

selenium.common.exceptions.JavascriptException: Message: javascript error: Cannot set properties of null (setting 'value') (Session info: headless chrome=95.0.4638.54)

解決したいこと

いままで 動いていたコードが1ヶ月前?くらいから動かなくなってしまいました。
seleniumを使ったものです。
また動くように改善したいです。

発生している問題・エラー

% docker exec selenium python3 mail_de_point.py
Traceback (most recent call last):
  File "mail_de_point.py", line 68, in <module>
    main()
  File "mail_de_point.py", line 65, in main
    Operation('https://member.pointmail.rakuten.co.jp/box', user_name, user_passwd)
  File "mail_de_point.py", line 21, in Operation
    driver.execute_script('document.getElementById("loginInner_u").value="%s";' %user_name)
  File "/usr/local/lib/python3.8/dist-packages/selenium/webdriver/remote/webdriver.py", line 872, in execute_script
    return self.execute(command, {
  File "/usr/local/lib/python3.8/dist-packages/selenium/webdriver/remote/webdriver.py", line 418, in execute
    self.error_handler.check_response(response)
  File "/usr/local/lib/python3.8/dist-packages/selenium/webdriver/remote/errorhandler.py", line 243, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.JavascriptException: Message: javascript error: Cannot set properties of null (setting 'value')
  (Session info: headless chrome=95.0.4638.54)
Stacktrace:
#0 0x55e377916ac3 <unknown>
#1 0x55e3773f08f8 <unknown>
#2 0x55e3773f377c <unknown>
#3 0x55e3773f3576 <unknown>
#4 0x55e3773f4132 <unknown>
#5 0x55e377457993 <unknown>
#6 0x55e377443b02 <unknown>
#7 0x55e377456ca1 <unknown>
#8 0x55e3774439f3 <unknown>
#9 0x55e377419e14 <unknown>
#10 0x55e37741ae05 <unknown>
#11 0x55e37794825e <unknown>
#12 0x55e37795dafa <unknown>
#13 0x55e3779491b5 <unknown>
#14 0x55e37795f4c8 <unknown>
#15 0x55e37793d95b <unknown>
#16 0x55e37797a298 <unknown>
#17 0x55e37797a418 <unknown>
#18 0x55e377995bed <unknown>
#19 0x7fd3f0233609 <unknown>

または、問題・エラーが起きている画像をここにドラッグアンドドロップ

該当するソースコード

mail_de_point.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
import chromedriver_binary
import time

user_name = ''
user_passwd = ''

def Operation(url, user_name, user_passwd):
    op = Options()
    op.add_argument("--no-sandbox")
    op.add_argument('--headless')
    op.add_argument('--disable-dev-shm-usage')
    op.add_argument('--disable-gpu')
    driver = webdriver.Chrome(options=op)

    driver.get(url)
    driver.implicitly_wait(100)
    # driver.find_element_by_id('loginInner_u').send_keys(user_name)
    driver.execute_script('document.getElementById("loginInner_u").value="%s";' %user_name)
    # driver.find_element_by_id('loginInner_p').send_keys(user_passwd)
    driver.execute_script('document.getElementById("loginInner_p").value="%s";' %user_passwd)
    driver.find_element_by_class_name('loginButton').click()

    driver.implicitly_wait(100)
    driver.find_element_by_class_name('notRead').click()
    driver.implicitly_wait(20)
    add = 0
    while len(driver.find_elements_by_xpath('//div[@class="listCont"]/a')) > add:
        if driver.find_elements_by_xpath('//div[@class="listCont"]/a')[add].get_attribute('target') == '':
            try:
                driver.implicitly_wait(20)
                driver.find_elements_by_xpath('//div[@class="listCont"]/a')[add].click()
            except:
                driver.implicitly_wait(20)
                driver.find_elements_by_xpath('//div[@class="listCont"]/a')[add].click()
            driver.implicitly_wait(20)
            try:
                driver.implicitly_wait(20)
                driver.find_element_by_class_name('point_url').click()
            except:
                try:
                    driver.implicitly_wait(20)
                    driver.find_element_by_id('mailFrame').click()
                except:
                    pass
            time.sleep(5)
            try:
                driver.switch_to.window(driver.window_handles[1])
                driver.close()
                driver.switch_to.window(driver.window_handles[0])
                time.sleep(5)
            except:
                pass
            driver.back()
            time.sleep(5)
        else:
            add += 1

    print('finish!')
    driver.quit()

def main():
    Operation('https://member.pointmail.rakuten.co.jp/box', user_name, user_passwd)

if __name__ == '__main__':
    main()

自分で試したこと

"Message: javascript error: Cannot set properties of null (setting 'value')"で検索したりしているのですが、はっきりしたことがわかっていません。

どなたかお教えいただけたら幸いです。

0

5Answer

ターゲットのUIが変わったとかではないでしょうか?

document.getElementById("loginInner_u").value="%s";

エラーメッセージを見るとこの部分で「プロパティがnull」ということなので、idloginInner_uの要素が無くなったとかでは無いですか?

実際にURLを参照してみると「楽天会員ログイン画面が新しくなりました。」とあります。

楽天グループでは、セキュリティの向上を目的として、2021年7月以降、新しいログイン画面のご提供を開始いたします。

3Like

Comments

  1. @hetare

    Questioner

    ありがとうございます!
    ご指摘いただいたように楽天側のログイン画面の仕様変更の影響でした

chromeを最新にしてみてはどうでしょうか?
わたしのchromeのバージョンは104.0ぐらいです。

1Like

Comments

  1. @hetare

    Questioner

    ありがとうございます!
    バージョン変更して対応しました。

「Ctrl」+「Shift」+「i」キーを押して検証でコンソールに「document.getElementById("loginInner_u")」と入力して「null」が出ればid「"loginInner_u"」の要素は存在しないということになります。

1Like

@blue32a さんが言うように、ログイン・ページの仕様が変わったためのようのです。

まず、シェルから従来のページを確認してみました。

curl -sS "https://member.pointmail.rakuten.co.jp/box"
ログイン・ページの取得
$ curl -sS "https://member.pointmail.rakuten.co.jp/box"
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="refresh" content="0;url='https://login.account.rakuten.com/sso/authorize?nonce=nonce&amp;scope=openid%20profile%20email&amp;response_type=code&amp;client_id=rakuten_pointmail_web&amp;redirect_uri=https%3A%2F%2Fmember.pointmail.rakuten.co.jp%2Fauth%2Fcallback&amp;state=%2Fbox&amp;r10_audience=jid'" />

        <title>Redirecting to https://login.account.rakuten.com/sso/authorize?nonce=nonce&amp;scope=openid%20profile%20email&amp;response_type=code&amp;client_id=rakuten_pointmail_web&amp;redirect_uri=https%3A%2F%2Fmember.pointmail.rakuten.co.jp%2Fauth%2Fcallback&amp;state=%2Fbox&amp;r10_audience=jid</title>
    </head>
    <body>
        Redirecting to <a href="https://login.account.rakuten.com/sso/authorize?nonce=nonce&amp;scope=openid%20profile%20email&amp;response_type=code&amp;client_id=rakuten_pointmail_web&amp;redirect_uri=https%3A%2F%2Fmember.pointmail.rakuten.co.jp%2Fauth%2Fcallback&amp;state=%2Fbox&amp;r10_audience=jid">https://login.account.rakuten.com/sso/authorize?nonce=nonce&amp;scope=openid%20profile%20email&amp;response_type=code&amp;client_id=rakuten_pointmail_web&amp;redirect_uri=https%3A%2F%2Fmember.pointmail.rakuten.co.jp%2Fauth%2Fcallback&amp;state=%2Fbox&amp;r10_audience=jid</a>.
    </body>
</html>
curl -I "https://member.pointmail.rakuten.co.jp/box"
ヘッダー情報取得
$ curl -I "https://member.pointmail.rakuten.co.jp/box"
HTTP/1.1 302 Found
Date: Mon, 22 Aug 2022 01:32:18 GMT
Server: Apache
Cache-Control: no-cache, private
Set-Cookie: XSRF-TOKEN=eyJp**snip**dGFnIjoiIn0%3D; expires=Thu, 25-Aug-2022 01:32:18 GMT; Max-Age=259200; path=/; secure
Set-Cookie: poime_session=eyJp**snip**dGFnIjoiIn0%3D; expires=Thu, 25-Aug-2022 01:32:18 GMT; Max-Age=259200; path=/; secure; httponly
Location: https://login.account.rakuten.com/sso/authorize?nonce=nonce&scope=openid%20profile%20email&response_type=code&client_id=rakuten_pointmail_web&redirect_uri=https%3A%2F%2Fmember.pointmail.rakuten.co.jp%2Fauth%2Fcallback&state=%2Fbox&r10_audience=jid
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubDomains
Connection: close
Content-Type: text/html; charset=UTF-8

レスポンスを見ると、302https://login.account.rakuten.com/sso/authorize へ、ダイレクトされるようになっていました。

次に転送先のページを開いてみました。

curl -sS "https://login.account.rakuten.com/sso/authorize"
$ curl -sS "https://login.account.rakuten.com/sso/authorize"
<!DOCTYPE html>
<html>
<head>
    <link rel="shortcut icon" href="/widget/images/favicon.png">
    <link rel="stylesheet" type="text/css" href="/widget/css/style.css">
    <link rel="stylesheet" type="text/css" href="/widget/css/error.css">
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
    <meta name="theme-color" content="#bf0000">
    <title>Rakuten - Error</title>
</head>
<body>
<div id="main" style="margin: 50px auto; max-width: 400px;">
    <div class="background"></div>
    <h1 id="title" class="centerIfMobile"></h1>
    <h2 id="subTitle" class="centerIfMobile">Client ID is missing or invalid</h2>
    <hr>
    <div>
        <div id="Text1"></div>
        <div id="Text2">Please try the following options.</div>
        <ul>
            <li id="Point1">Click the Back button to try another link.</li>
            <li id="Point2">Check the address you entered to make sure it is spelled correctly.</li>
            <li id="Point3">Reload the page, or try again later.</li>
        </ul>
    </div>
</div>

<script>
    translations = [{
        codeLanguage: "en-US",
        language: "English",
        errors: [{
            codeError: "GENERIC",
            title: document.getElementById("title").innerText,
            subTitle: document.getElementById("subTitle").innerText,
        }],
        text1: document.getElementById("Text1").innerText,
        text2: document.getElementById("Text2").innerText,
        point1: document.getElementById("Point1").innerText,
        point2: document.getElementById("Point2").innerText,
        point3: document.getElementById("Point3").innerText,
        buttonText: null,
        buttonHref: null,
    }];
</script>
<script src="/widget/js/error.min.js"></script>
</body>
</html>

上記のように 400 で「クライアント ID が不足もしくは不正エラー」のページになるので、クッキー情報及び転送時の引数も渡さないとログイン・フォームが表示されないようです。

そこで、最後に、最初の従来のページを取得する際に -L オプションでリダイレクトに追随させるとフォームが表示されました。

curl -sSL "https://member.pointmail.rakuten.co.jp/box"
$ curl -sSL "https://member.pointmail.rakuten.co.jp/box"
<!DOCTYPE html>
<html lang="ja-JP">
<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
    <meta name="google" content="notranslate">
    <meta name="theme-color" content="#bf0000">
    <meta name="description" content="楽天 - ログイン">
    <title>楽天 - ログイン</title>
    <link rel="shortcut icon" href="/widget/images/favicon.png">
    <link rel="preload" href="/widget/js/4hk58wd8hqxo493p8gm5bej-2.5.8.2.min.js" as="script">
    <style> ** snip ** </style>
</head>
<body>
<noscript>
    <div style="** snip **">
        <span>Please enable JavaScript to use this page.</span>
    </div>
</noscript>
<div style="** snip **">
    <div id="omni-loader">
        <div id="logo">
            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 40 40">
                <path d="** snip **" />
            </svg>
        </div>
        <div class="circle" style="animation-delay: 0.0s"></div>
        <div class="circle" style="animation-delay: 0.5s"></div>
        <div class="circle" style="animation-delay: 1.0s"></div>
        <div class="circle" style="animation-delay: 1.5s"></div>
    </div>
</div>
<script>** snip **</script>
</body>
</html>

長いので中略(snip)していますが、ソースを見ると <body> タグの中身はすべて Javascript で描画するようになっていました。そのため loginInner_u の ID のタグもありません。

フォームを展開した最終的な状態を取得するため、ログインページを Chrome で開き、デベロッパーツールから @caleb7023 さんの手法で loginInner_u の ID を持つ要素を調べましたが、ありませんでした。

やはり、抜本的に構成が変わっているようですので、おそらく、フォームの解析からやり直さないといけないと思います。スクレイピングは、こういうのが大変ですよね。

1Like

Comments

  1. @hetare

    Questioner

    ありがとうございます!

    > loginInner_u の ID を持つ要素を調べましたが、ありませんでした。
    そのとおりでした。
    ありがとうございます!

Your answer might help someone💌