You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Selenium无法点击Twitter评论按钮的技术求助

Twitter机器人评论按钮定位问题解决方法

问题描述

我正在开发一款Twitter机器人,目前遇到无法点击评论按钮的问题。无论复制使用哪种XPATH,都会出现元素找不到的错误。当前用于定位评论按钮的代码为:

comment_button = driver.find_element(By.XPATH, '//*[@id="id__pm1tufstyp"]/div[1]/div')

以下是完整代码(运行时需填入邮箱、用户名和密码):

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys
import time
import random

URL = "https://twitter.com/"

user_agents = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
]

service = Service()
options = webdriver.ChromeOptions()
options.add_argument(f"user-agent={random.choice(user_agents)}")
driver = webdriver.Chrome(service=service, options=options)

driver.get(URL)
time.sleep(random.uniform(3, 5))

accept_cookies = driver.find_element(By.XPATH, '//*[@id="layers"]/div/div/div/div/div/div[2]/div[1]/div')
accept_cookies.click()

sign_in = driver.find_element(By.XPATH, '//*[@id="react-root"]/div/div/div[2]/main/div/div/div[1]/div[1]/div/div[3]/div[5]/a/div')
sign_in.click()
time.sleep(2)

email = driver.find_element(By.XPATH, '//*[@id="layers"]/div[2]/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div/div/div/div[5]/label/div/div[2]/div/input')
email.click()
email.send_keys('YOUR EMAIL')
time.sleep(1)

next_button_1 = driver.find_element(By.XPATH, '//*[@id="layers"]/div[2]/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div/div/div/div[6]/div')
next_button_1.click()
time.sleep(1)

#Twitter sometimes asks for username sometimes doesn't
try:
    user_name = driver.find_element(By.XPATH, '//*[@id="layers"]/div/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div[1]/div/div[2]/label/div/div[2]/div/input')
    user_name.click()
    user_name.send_keys('YOUR USERNAME')

    next_button_2 = driver.find_element(By.XPATH, '//*[@id="layers"]/div[2]/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div[2]/div/div/div/div/div')
    next_button_2.click()
    time.sleep(1)
except:
    print("Username input field not found. Twitter may not have requested it.")

password = driver.find_element(By.XPATH, '//*[@id="layers"]/div[2]/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div[1]/div/div/div[3]/div/label/div/div[2]/div[1]/input')
password.click()
password.send_keys('YOUR PASSWORD')

sing_in_button = driver.find_element(By.XPATH, '//*[@id="layers"]/div[2]/div/div/div/div/div/div[2]/div[2]/div/div/div[2]/div[2]/div[2]/div/div[1]/div/div/div/div')
sing_in_button.click()
time.sleep(5)

search_button = driver.find_element(By.XPATH, '//*[@id="react-root"]/div/div/div[2]/header/div/div/div/div[1]/div[2]/nav/a[2]/div')
search_button.click()
time.sleep(1)

search_bar = driver.find_element(By.XPATH, '//*[@id="react-root"]/div/div/div[2]/main/div/div/div/div/div/div[1]/div[1]/div/div/div/div/div/div[1]/div[2]/div/div/div/form/div[1]/div/div/div/label/div[2]/div/input')
search_bar.click()
search_bar.send_keys('elon musk')
search_bar.send_keys(Keys.ENTER)
time.sleep(3)

driver.execute_script(f"window.scrollTo(0, 300);")

time.sleep(2)

comment_button = driver.find_element(By.XPATH, '//*[@id="id__pm1tufstyp"]/div[1]/div')
comment_button.click()
time.sleep(1)

reply_message = driver.find_element(By.XPATH, '//*[@id="layers"]/div[2]/div/div/div/div/div/div[2]/div[2]/div/div/div/div[3]/div[2]/div[2]/div/div/div/div[1]/div[2]/div/div/div/div/div/div/div/div/div/div/div/label/div[1]/div/div/div/div/div/div[2]/div/div/div/div')
reply_message.click()
reply_message.send_keys('hello')

reply = driver.find_element(By.XPATH, '//*[@id="layers"]/div[2]/div/div/div/div/div/div[2]/div[2]/div/div/div/div[3]/div[2]/div[2]/div/div/div/div[2]/div[2]/div/div/div/div[2]')
reply.click()
time.sleep(15)

问题原因

你使用的XPATH依赖动态生成的元素ID(id__pm1tufstyp),Twitter基于React渲染的页面会随机生成这类ID,每次刷新或会话都会变化,因此无法稳定定位元素。

解决方法

1. 用稳定属性定位评论按钮

Twitter的交互元素通常带有aria-label或data-testid属性,这些属性是专为功能测试设计的,不会随页面刷新变化。定位第一条推文的评论按钮可以用以下方式:

# XPATH方式
comment_button = driver.find_element(By.XPATH, '//article[@data-testid="tweet"]//button[@aria-label="回复"]')

# CSS选择器方式(更简洁)
comment_button = driver.find_element(By.CSS_SELECTOR, 'article[data-testid="tweet"] button[aria-label="回复"]')

2. 替换硬等待为显式等待

time.sleep()是不可靠的等待方式,页面加载速度波动会导致元素未就绪就执行操作。改用WebDriverWait等待元素可点击,提升代码稳定性:
首先在代码开头导入相关模块:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

然后替换原有的等待逻辑,比如定位评论按钮时:

# 等待10秒,直到评论按钮可点击
comment_button = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, 'article[data-testid="tweet"] button[aria-label="回复"]'))
)
comment_button.click()

3. 修正回复框和发送按钮的定位

同样,回复框和发送按钮也需要用稳定属性定位:

# 等待回复输入框加载并输入内容
reply_box = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, 'div[data-testid="tweetTextarea_0"]'))
)
reply_box.click()
reply_box.send_keys('hello')

# 定位并点击发送按钮
send_button = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, 'button[data-testid="tweetButton"]'))
)
send_button.click()

完整优化后的代码片段

替换原代码中从driver.execute_script(...)到最后的部分:

driver.execute_script(f"window.scrollTo(0, 300);")

# 等待评论按钮可点击并点击
comment_button = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, 'article[data-testid="tweet"] button[aria-label="回复"]'))
)
comment_button.click()

# 等待回复框并输入内容
reply_box = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, 'div[data-testid="tweetTextarea_0"]'))
)
reply_box.click()
reply_box.send_keys('hello')

# 等待发送按钮并点击
send_button = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, 'button[data-testid="tweetButton"]'))
)
send_button.click()

time.sleep(5)
driver.quit()

额外建议

  • 避免使用基于层级结构的长XPATH,这类路径容易因页面布局变化失效
  • 优先使用data-testid、aria-label这类专为测试设计的属性定位元素
  • 所有元素操作前都用显式等待,替代time.sleep(),提升代码稳定性

内容的提问来源于stack exchange,提问作者SolidOpt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 10:17:42