无法使用 Selenium 点击 Reddit 登录按钮

问题描述 投票:0回答:1

我正在尝试使用 Selenium 单击登录按钮,但不知何故它不起作用。我检查了其他存储库以及以前的线程,但找不到解决方案。这是我的代码:

import time

from selenium import webdriver
from selenium.webdriver.common.by import By


class Bot:
    def __init__(self):
        self.driver = webdriver.Chrome()

    def interact(self, selector: str, text: str=None, wait=2, by=By.CSS_SELECTOR):
        element = self.driver.find_element(by=by, value=selector)
        if text is None:
            element.click()
        else:
            element.send_keys(text)
        time.sleep(wait)


class RedditBot(Bot):
    def __init__(self):
        super().__init__()
        self.driver.get("https://www.reddit.com/login/")


if __name__ == "__main__":
    rb = RedditBot()
    rb.interact("input[id='login-username']", text="Brave_Primary1797")
    rb.interact("input[id='login-password']", text="EcOjllIrz3M87q9S08M")
    rb.interact("#login > auth-flow-modal > div.w-100 > faceplate-tracker > button") # this line errors

python css selenium-webdriver bots reddit
1个回答
0
投票

问题是因为它使用

shadow-root
来保护某些元素免受其他元素的意外更改。它允许制作
templates
slots
- Web 开发人员的工作可能会更简单。

但是在网页抓取期间访问这些元素会出现问题。

您已经找出哪些元素使用了

shadow-root
(您可以在 Chrome/Firefox 中的
HTML
中的
DevTools
中看到它)并使用
find_element(...).shadow_root.find_element(...)

我发现所有带有

shadow-root
的元素在我开始检查哪个元素需要使用
.shadow_root
- 所以最后我创建了这样的东西:

(对我有用)

def get_item(driver, selector, shadow=True):
    print('##### selector:', selector, shadow)
    
    item = driver.find_element(*selector)
    
    for child in item.find_elements(By.CSS_SELECTOR, '*'):
        print(f'child: <{child.tag_name}>')
        
    if shadow:
        print('!!! getting shadow root')
        item = item.shadow_root
        
    return item

if __name__ == "__main__":
    try:
        rb = RedditBot()
        time.sleep(2)
        
        rb.interact("input[id='login-username']", text="Brave_Primary1797")
        rb.interact("input[id='login-password']", text="EcOjllIrz3M87q9S08M")
        time.sleep(1)
        
        #rb.interact("#login > auth-flow-modal > div.w-100 > faceplate-tracker > button") # this line errors
        item = rb.driver        
        item = get_item(item, (By.CSS_SELECTOR, 'shreddit-overlay-display'))
        item = get_item(item, (By.CSS_SELECTOR, 'shreddit-signup-drawer'))
        item = get_item(item, (By.CSS_SELECTOR, 'shreddit-drawer'), False)
        item = get_item(item, (By.CSS_SELECTOR, 'div'), False)
        item = get_item(item, (By.CSS_SELECTOR, 'shreddit-async-loader'), False)
        item = get_item(item, (By.CSS_SELECTOR, 'div'), False)
        item = get_item(item, (By.CSS_SELECTOR, 'shreddit-slotter'))
        item = get_item(item, (By.CSS_SELECTOR, 'span'), False)
        item = get_item(item, (By.CSS_SELECTOR, 'shreddit-async-loader'), False)
        item = get_item(item, (By.CSS_SELECTOR, 'auth-flow-login'), False)
        item = get_item(item, (By.CSS_SELECTOR, 'faceplate-tabpanel'), False)
        item = get_item(item, (By.CSS_SELECTOR, 'faceplate-form'), False)
        item = get_item(item, (By.CSS_SELECTOR, 'auth-flow-modal'), False)
#        item = get_item(item, (By.CSS_SELECTOR, 'div.w-100'), False)   # it finds different element
        item = get_item(item, (By.CSS_SELECTOR, 'div[slot]'), False)  # OK
#        item = get_item(item, (By.CSS_SELECTOR, 'div[slot="primaryButton"]'), False)  # OK
        item = get_item(item, (By.CSS_SELECTOR, 'faceplate-tracker'), False)
        item = item.find_element(By.CSS_SELECTOR, 'button')
        item.click()        
            
    except Exception as ex:
        print("Exception", ex)            

因为在函数中

get_item()
我显示了孩子,这样我就可以看到我可以将其减少到

if __name__ == "__main__":
    try:
        rb = RedditBot()
        time.sleep(2)
        
        rb.interact("input[id='login-username']", text="Brave_Primary1797")
        rb.interact("input[id='login-password']", text="EcOjllIrz3M87q9S08M")
        time.sleep(1)
            
        item = (
            rb.driver        
            .find_element(By.CSS_SELECTOR, 'shreddit-overlay-display').shadow_root
            .find_element(By.CSS_SELECTOR, 'shreddit-signup-drawer').shadow_root
            .find_element(By.CSS_SELECTOR, 'shreddit-slotter').shadow_root
            .find_element(By.CSS_SELECTOR, "button")
        )
        item.click()
            
    except Exception as ex:
        print("Exception", ex)   
© www.soinside.com 2019 - 2024. All rights reserved.