首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用Selenium和Python访问多个shadowRoot中嵌套的html

如何使用Selenium和Python访问多个shadowRoot中嵌套的html
EN

Stack Overflow用户
提问于 2022-01-19 13:36:58
回答 2查看 1K关注 0票数 1

我正在尝试建造一个机器人来解决网站上的字谜(https://www.powerlanguage.co.uk/wordle/)。

我正在使用selenium输入一个猜测,然后尝试检查页面,看看哪些猜测是正确的和不正确的。

当我检查chrome上的元素时,我可以看到这个信息,但是使用selenium返回的html要短得多,并指向javascript应用程序?是否有一种方法返回selenium中的检查html?这是我的密码。

代码语言:javascript
运行
复制
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import TimeoutException
from selenium.common.exceptions import ElementClickInterceptedException
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome(executable_path=r"/Users/1/Downloads/chromedriver", options=chrome_options)
driver.get("https://www.powerlanguage.co.uk/wordle/")
time.sleep(1)
sends=driver.find_element_by_xpath("/html/body")
sends.click()
sends.send_keys("adieu")
sends.send_keys(Keys.ENTER)
sends.get_attribute('innerHTML')

这就是内部html返回的内容。

这就是我在网站上看到的

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-19 16:17:05

innerHTML的所需信息区间在多个#阴影-根(打开)中。

解决方案

要提取需要使用shadowRoot.querySelectorAll()的信息,可以使用以下定位器策略

  • 代码块: Driver.get(https://www.powerlanguage.co.uk/wordle/") time.sleep(1) sends=driver.find_element(By.XPATH )"/html/body") sends.click() sends.send_keys("adieu") sends.send_keys(Keys.ENTER) inner_texts = [my_elem.get_attribute("outerHTML") for my_elem in driver.execute_script(“返回inner_text in inner_texts: print(inner_text) )
  • 控制台输出:

参考文献

您可以在以下几个方面找到相关的讨论:

票数 0
EN

Stack Overflow用户

发布于 2022-01-20 07:22:59

如果您正在寻找一个完整的Python解决方案,以编程方式解决Wordle游戏,那么这里有一个使用SeleniumBase框架的解决方案。该解决方案附带了一个YouTube视频:用SeleniumBase求解Wordle,以及解决方案的Python代码,以及一个GIF:

代码使用特殊的SeleniumBase ::shadow选择器来穿透多层Shadow-DOM。下面的代码可以在调用pip install seleniumbase以获取所有Python依赖项之后运行:

代码语言:javascript
运行
复制
import ast
import random
import requests
from seleniumbase import __version__
from seleniumbase import BaseCase

class WordleTests(BaseCase):
    word_list = []

    def initalize_word_list(self):
        js_file = "https://www.powerlanguage.co.uk/wordle/main.e65ce0a5.js"
        req_text = requests.get(js_file).text
        start = req_text.find("var La=") + len("var La=")
        end = req_text.find("],", start) + 1
        word_string = req_text[start:end]
        self.word_list = ast.literal_eval(word_string)

    def modify_word_list(self, word, letter_status):
        new_word_list = []
        correct_letters = []
        present_letters = []
        for i in range(len(word)):
            if letter_status[i] == "correct":
                correct_letters.append(word[i])
                for w in self.word_list:
                    if w[i] == word[i]:
                        new_word_list.append(w)
                self.word_list = new_word_list
                new_word_list = []
        for i in range(len(word)):
            if letter_status[i] == "present":
                present_letters.append(word[i])
                for w in self.word_list:
                    if word[i] in w and word[i] != w[i]:
                        new_word_list.append(w)
                self.word_list = new_word_list
                new_word_list = []
        for i in range(len(word)):
            if (
                letter_status[i] == "absent"
                and word[i] not in correct_letters
                and word[i] not in present_letters
            ):
                for w in self.word_list:
                    if word[i] not in w:
                        new_word_list.append(w)
                self.word_list = new_word_list
                new_word_list = []

    def test_wordle(self):
        self.open("https://www.powerlanguage.co.uk/wordle/")
        self.click("game-app::shadow game-modal::shadow game-icon")
        self.initalize_word_list()
        keyboard_base = "game-app::shadow game-keyboard::shadow "
        word = random.choice(self.word_list)
        total_attempts = 0
        success = False
        for attempt in range(6):
            total_attempts += 1
            word = random.choice(self.word_list)
            letters = []
            for letter in word:
                letters.append(letter)
                button = 'button[data-key="%s"]' % letter
                self.click(keyboard_base + button)
            button = 'button[data-key="↵"]'
            self.click(keyboard_base + button)
            self.sleep(1)  # Time for the animation
            row = 'game-app::shadow game-row[letters="%s"]::shadow ' % word
            tile = row + "game-tile:nth-of-type(%s)"
            letter_status = []
            for i in range(1, 6):
                letter_eval = self.get_attribute(tile % str(i), "evaluation")
                letter_status.append(letter_eval)
            if letter_status.count("correct") == 5:
                success = True
                break
            self.word_list.remove(word)
            self.modify_word_list(word, letter_status)

        self.save_screenshot_to_logs()
        print('\nWord: "%s"\nAttempts: %s' % (word.upper(), total_attempts))
        if not success:
            self.fail("Unable to solve for the correct word in 6 attempts!")
        self.sleep(3)

由于更新的Shadow-DOM方法,此解决方案需要最小的SeleniumBase版本2.4.0 (或更新版本)。(以下是该版本的发行说明。)

注意,SeleniumBase测试是使用pytest运行的。此外,Wordle网站在使用无头Chrome打开时看起来略有不同,所以在运行此示例时不要使用Chrome的无头模式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70771587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档