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
相关产品推荐
相关产品推荐

