使用 python selenium 查找 Twitter 文本框元素

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

我制作了自己的 Twitter 投诉机器人,如果网络掉线,它会向我的 ISP 发送推文。 代码运行得非常完美,直到它必须找到 Twitter 文本框来输入推文。 主要错误是:

StaleElementReferenceException: Message: stale element reference: element is not attached to the page document

我已经尝试过:

  • 添加时间延迟
  • 使用 Firefox 驱动程序而不是 Google
  • 在 tweet_at_provider() 查找文本框之前添加页面刷新
  • 单击“推文”按钮调出文本框,然后尝试在其中输入内容
  • 使用 find.element_by_id 但 Twitter 每次页面加载都会更改 id

当我注释掉第一个要测试的函数调用时,它将查找并键入 6/10 次。 但是,当调用这两个函数时,tweet_at_provider() 总是无法抓取文本框,并且我收到 StaleElement 错误。

import selenium, time, pyautogui
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import ElementClickInterceptedException, NoSuchElementException, StaleElementReferenceException


PROMISED_DOWN = 200
PROMISED_UP = 10
CHROME_DRIVER_PATH = "C:\Development\chromedriver.exe"
GECKODRIVER_PATH = "C:\\Users\\meeha\\Desktop\\geckodriver\\geckodriver.exe"
TWITTER_USERNAME = "my_username"
TWITTER_PASSWORD = "my_password"


class InternetSpeedTwitterBot():

    def __init__(self, driver_path):
        self.driver = webdriver.Chrome(executable_path=driver_path)
        self.down = 0
        self.up = 0

    def get_internet_speed(self):
        self.driver.get("https://www.speedtest.net/")
        self.driver.maximize_window()
        time.sleep(2)
        go = self.driver.find_element_by_xpath("//*[@id='container']/div/div[3]/div/div/div/div[2]/div[3]/div[1]/a/span[4]")
        go.click()
        time.sleep(40)

        self.down = self.driver.find_element_by_xpath("//*[@id='container']/div/div[3]/div/div/div/div[2]/div[3]/div[3]/div/div[3]/div/div/div[2]/div[1]/div[2]/div/div[2]/span")
        self.up = self.driver.find_element_by_xpath("//*[@id='container']/div/div[3]/div/div/div/div[2]/div[3]/div[3]/div/div[3]/div/div/div[2]/div[1]/div[3]/div/div[2]/span")

        print(f"Download Speed: {self.down.text} Mbps")
        print(f"Upload Speed: {self.up.text} Mbps")
        time.sleep(3)

    def tweet_at_provider(self):
        self.driver.get("https://twitter.com/login")
        self.driver.maximize_window()
        time.sleep(3)
        username = self.driver.find_element_by_name("session[username_or_email]")
        password = self.driver.find_element_by_name("session[password]")
        username.send_keys(TWITTER_USERNAME)
        password.send_keys(TWITTER_PASSWORD)
        password.submit()
        time.sleep(5)

        tweet_compose = self.driver.find_element_by_xpath('//*[@id="react-root"]/div/div/div[2]/header/div/div/div/div[1]/div[3]/a/div/span/div/div/span/span')
        tweet_compose.click()
        time.sleep(2)
        textbox = self.driver.find_element_by_xpath('//*[@id="layers"]/div[2]/div/div/div/div/div/div[2]/div[2]/div/div[3]/div/div/div/div[1]/div/div/div/div/div[2]/div[1]/div/div/div/div/div/div/div/div/div/div[1]/div/div/div/div[2]/div/div/div/div')
        textbox.send_keys(f"Hey @Ask_Spectrum, why is my internet speed {self.down.text} down / {self.up.text} up when I pay for {PROMISED_DOWN} down / {PROMISED_UP} up???")


bot = InternetSpeedTwitterBot(CHROME_DRIVER_PATH)

bot.get_internet_speed()
bot.tweet_at_provider()
python-3.x selenium
3个回答
0
投票

我也遇到了同样的错误,并发现只要我在 Twitter 文本框中输入内容,HTML 标签就会立即发生变化。

使用在我这边输入空格后显示的跨度标签的 XPATH 来解决这个问题。当您没有提示任何文本时,break
标记是初始标记,只有在您键入任何内容
后才会变成,此时您必须复制 XPATH 并将其用于您的应用程序


0
投票

按类名搜索,而不是 XPath。

将最后 5 行更改为以下内容:

#First line is all that you need =)
tweet_compose=self.driver.find_element(By.CSS_SELECTOR,'br[data text="true"]')
tweet_compose.send_keys(f"Yak Yak {self.down} {self.up}...")


0
投票

对我来说,我使用了一种解决方案,您可以单击文本区域,然后使用名为 Pyautogui 的库来编写一些内容,该库模拟在键盘上书写 这是一个例子

from selenium import webdriver
import time
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
import pyautogui
# Initialize Chrome WebDriver
driver = webdriver.Chrome(ChromeDriverManager().install())


editor_field = driver.find_element(By.CSS_SELECTOR,'div[class="DraftEditor-editorContainer"]')
editor_field.click()
# Wait for a few seconds before typing
time.sleep(5)

# Type "hello twitter" with a 0.1-second interval between each keypress
pyautogui.typewrite('hello twitter', interval=0.1)time.sleep(5)
post_button = driver.find_element(By.XPATH,'//span[text()="Post"]')
post_button.click()
time.sleep(15)

#editor_field.send_keys('any')
time.sleep(30)
driver.quit()
© www.soinside.com 2019 - 2024. All rights reserved.