我制作了自己的 Twitter 投诉机器人,如果网络掉线,它会向我的 ISP 发送推文。 代码运行得非常完美,直到它必须找到 Twitter 文本框来输入推文。 主要错误是:
StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
我已经尝试过:
当我注释掉第一个要测试的函数调用时,它将查找并键入 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()
我也遇到了同样的错误,并发现只要我在 Twitter 文本框中输入内容,HTML 标签就会立即发生变化。
使用在我这边输入空格后显示的跨度标签的 XPATH 来解决这个问题。当您没有提示任何文本时,break
标记是初始标记,只有在您键入任何内容
后才会变成,此时您必须复制 XPATH 并将其用于您的应用程序
按类名搜索,而不是 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}...")
对我来说,我使用了一种解决方案,您可以单击文本区域,然后使用名为 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()