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

Selenium Twitter爬虫启动后立即关闭且无法检测新推文问题求助

Selenium Twitter爬虫启动后立即关闭且无法检测新推文问题求助

嘿,我看了你的代码和遇到的问题,帮你梳理几个核心问题点,应该能解决浏览器闪退、抓不到推文的情况:

1. 最关键的问题:Twitter(X)现在需要登录才能访问用户推文

你现在直接访问用户主页,大概率会被跳转到登录页面,或者加载不出任何推文内容。这就导致WebDriverWait找不到<article>元素,触发异常后scroll_attempts快速累加,很快达到max_scrolls上限,浏览器就直接关闭了。

解决办法:

  • 最简单的方式:先手动打开Chrome登录X,然后让Selenium复用这个已登录的浏览器会话(需要设置Chrome的用户数据目录);
  • 或者在代码里添加登录逻辑,模拟输入用户名、密码(注意X有验证码机制,可能需要手动处理或者用打码服务)。

2. 不稳定的元素选择器

你用的article和time标签选择器太宽泛了,X的页面结构经常变动,而且<time>标签可能嵌套在多个层级里,直接找会出错。建议改用X官方用于测试的data-testid属性,这个属性更稳定:

  • 推文容器:div[data-testid="tweet"]
  • 推文时间:time[data-testid="timestamp"]
  • 推文文本:div[data-testid="tweetText"]

3. 重复处理推文+等待逻辑不完善

你现在每次滚动后都会重新获取所有推文,会重复处理已经看过的旧推文。另外固定time.sleep(5)不够灵活,应该用显式等待等待新推文加载完成,而不是硬等时间。

修改后的参考代码

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
import pandas as pd
import time
from datetime import datetime, timezone

class TwitterScraper:
    def __init__(self, username, max_scrolls=10):
        self.username = username
        self.max_scrolls = max_scrolls
        self.start_time = datetime.now(timezone.utc)
        # 复用已登录的Chrome会话(需要替换成你的Chrome用户数据路径)
        options = webdriver.ChromeOptions()
        options.add_argument("--disable-gpu")
        options.add_argument("--no-sandbox")
        options.add_argument("--disable-dev-shm-usage")
        # 关键:添加用户数据目录,复用登录状态(Windows路径示例)
        options.add_argument(r"user-data-dir=C:\Users\你的用户名\AppData\Local\Google\Chrome\User Data")
        # options.add_argument(r"user-data-dir=/Users/你的用户名/Library/Application Support/Google/Chrome") # Mac路径示例
        self.driver = webdriver.Chrome(options=options)
        self.url = f'https://twitter.com/{username}'
        self.processed_tweet_ids = set() # 记录已处理的推文ID,避免重复

    def start(self):
        self.driver.get(self.url)
        # 先等待页面加载完成,等待登录状态下的推文容器出现
        try:
            WebDriverWait(self.driver, 20).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, 'div[data-testid="tweet"]'))
            )
        except Exception as e:
            print("页面加载失败,可能未登录?错误信息:", e)
            self.driver.quit()
            return

        scroll_attempts = 0
        last_scroll_height = self.driver.execute_script("return document.body.scrollHeight")

        while scroll_attempts < self.max_scrolls:
            try:
                # 获取所有推文容器
                tweets = self.driver.find_elements(By.CSS_SELECTOR, 'div[data-testid="tweet"]')
                for tweet in tweets:
                    # 获取推文唯一ID(从元素的data-testid提取)
                    tweet_id = tweet.get_attribute("data-testid")
                    if tweet_id in self.processed_tweet_ids:
                        continue
                    self.processed_tweet_ids.add(tweet_id)

                    # 获取推文时间
                    try:
                        timestamp_element = tweet.find_element(By.CSS_SELECTOR, 'time[data-testid="timestamp"]')
                        tweet_time = datetime.fromisoformat(timestamp_element.get_attribute("datetime"))
                    except NoSuchElementException:
                        print("找不到推文时间元素,跳过该推文")
                        continue

                    # 统一时区
                    if tweet_time.tzinfo is None:
                        tweet_time = tweet_time.replace(tzinfo=timezone.utc)
                    else:
                        tweet_time = tweet_time.astimezone(timezone.utc)

                    # 检查是否是脚本启动后的新推文
                    if tweet_time > self.start_time:
                        # 获取纯净的推文文本
                        try:
                            tweet_text = tweet.find_element(By.CSS_SELECTOR, 'div[data-testid="tweetText"]').text
                        except NoSuchElementException:
                            tweet_text = "无文本内容"
                        
                        print("New Tweet Detected:")
                        print(tweet_text)
                        print(f"发布时间: {tweet_time}")
                        
                        # 保存到CSV,格式化时间字符串
                        df = pd.DataFrame([{ "text": tweet_text, "time": tweet_time.strftime("%Y-%m-%d %H:%M:%S UTC") }])
                        df.to_csv('latest_tweet.csv', mode='a', header=False, index=False)
                        print("Latest tweet saved to latest_tweet.csv\n")
                
                # 滚动页面
                self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
                # 等待新内容加载,判断页面高度是否变化
                WebDriverWait(self.driver, 10).until(
                    lambda d: d.execute_script("return document.body.scrollHeight") > last_scroll_height
                )
                last_scroll_height = self.driver.execute_script("return document.body.scrollHeight")
                scroll_attempts += 1
            
            except Exception as e:
                print(f"循环中出现错误: {e}")
                scroll_attempts += 1
                time.sleep(3) # 出错后稍等再继续

        print("爬虫结束,关闭浏览器")
        self.driver.quit()

if __name__ == "__main__":
    scraper = TwitterScraper("FabrizioRomano", max_scrolls=20)
    scraper.start()

额外建议

  • 不要用宽泛的except Exception,尽量捕获具体的异常(比如NoSuchElementException、TimeoutException),这样能更精准定位问题;
  • 后续切换无头模式时,记得添加options.add_argument("--headless=new")(Chrome 112+的新无头模式更接近正常浏览器);
  • X的反爬机制比较严格,不要频繁滚动或请求,适当增加等待时间,避免被封号。

备注:内容来源于stack exchange,提问作者HamidBee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.15 03:19:58