Selenium代码本地正常,部署到Heroku+Celery环境后登录失败
问题:Heroku上Celery调度的Selenium Twitter登录任务失败,本地正常
我正在使用Django开发网站,其中有一个通过Celery调度的Selenium任务,用于登录Twitter账号并发布推文。该任务在本地机器上运行完全正常,但部署到Heroku后,任务虽能运行却出现异常,无法完成登录操作。以下是我的Selenium代码:
def test_login(self): driver = self.driver driver.get("https://twitter.com/i/flow/login") flag = True while flag: try: WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.XPATH, "//input[@name='text']"))).send_keys(self.username) time.sleep(1) driver.find_element(By.XPATH, "//span[contains(text(),'Next')]").click() print("Username") password = WebDriverWait(driver, 5).until( EC.presence_of_element_located( (By.XPATH, "//input[@name='password']")) ) if password: flag = False except: driver.refresh() password = WebDriverWait(driver, 20).until( EC.presence_of_element_located( (By.XPATH, "//input[@name='password']")) ) password.send_keys(self.password) print("Password") time.sleep(1) driver.find_element(By.XPATH, "//span[contains(text(),'Log in')]").click() try: email = WebDriverWait(driver, 5).until( EC.presence_of_element_located( (By.XPATH, "//input[@autocomplete='email']")) ) email.send_keys(self.email) time.sleep(1) driver.find_element(By.XPATH, "//span[contains(text(),'Next')]").click() except: pass time.sleep(5) # Change to be url like login if driver.current_url == "https://twitter.com/i/flow/login": driver.close() driver.quit() return False if driver.current_url == "https://twitter.com/home": driver.close() driver.quit() return True
请问有人知道为何在Heroku上无法正常工作吗?
可能的原因及解决方法
Heroku浏览器环境配置缺失
Heroku默认没有安装Chrome浏览器和ChromeDriver,必须添加对应的buildpack:- 登录Heroku控制台,找到目标应用,在
Settings->Buildpacks中添加:https://github.com/heroku/heroku-buildpack-google-chrome.githttps://github.com/heroku/heroku-buildpack-chromedriver.git
- 初始化WebDriver时必须启用无头模式,适配Heroku环境:
from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument("--headless=new") chrome_options.add_argument("--no-sandbox") chrome_options.add_argument("--disable-dev-shm-usage") chrome_options.add_argument("--window-size=1920,1080") chrome_options.add_argument("--disable-gpu") driver = webdriver.Chrome(options=chrome_options)
- 登录Heroku控制台,找到目标应用,在
Twitter反爬机制拦截
Heroku服务器IP属于云服务商IP段,很容易被Twitter识别为自动化工具,触发人机验证或登录限制:- 添加真实浏览器的User-Agent伪装:
chrome_options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36") - 替换固定
time.sleep()为WebDriverWait显式等待,避免操作过快触发检测; - 长期来看,建议改用Twitter官方API完成发推操作,这是合规且稳定的方案,避免被反爬机制拦截。
- 添加真实浏览器的User-Agent伪装:
元素定位不稳定
代码中依赖文本内容(如contains(text(),'Next'))定位元素,Twitter界面可能因地区、语言或版本更新变化,导致定位失败:- 改用Twitter页面元素的
data-testid属性定位,这类属性更稳定:- 用户名输入框:
(By.CSS_SELECTOR, "[data-testid='ocfEnterTextTextInput']") - Next按钮:
(By.CSS_SELECTOR, "[data-testid='ocfEnterTextNextButton']") - 密码输入框:
(By.CSS_SELECTOR, "[data-testid='LoginFormPassword']")
- 用户名输入框:
- 移除全局
except:捕获,改为捕获特定异常(如TimeoutException)并打印日志,方便通过heroku logs --tail查看具体错误:from selenium.common.exceptions import TimeoutException try: # 你的元素操作代码 except TimeoutException as e: print(f"元素加载超时: {str(e)}") driver.refresh()
- 改用Twitter页面元素的
Heroku资源限制
免费或基础版dyno内存、CPU资源有限,Selenium运行时可能因资源不足导致浏览器加载缓慢、元素超时:- 查看Heroku日志是否有内存溢出或超时相关报错;
- 考虑升级dyno规格,或优化Selenium代码减少资源占用(如关闭不必要的浏览器选项)。
内容的提问来源于stack exchange,提问作者Mazen Tayseer
相关产品推荐
相关产品推荐

