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

使用Python+Selenium爬取Twitter推文回复的滚动加载问题排查

问题排查结论

你的两段代码分别存在以下逻辑错误,导致无法爬取滚动加载的回复:

  • 初始代码错误点:
    1. all_tweets元素列表仅在进入while循环前获取1次,页面滚动后新加载的回复元素不会自动更新到这个列表里
    2. 滚动操作写在了遍历回复的for循环内部,每处理1条回复就触发一次滚动,逻辑顺序完全混乱
    3. 无限循环没有设置合理终止条件,运行时会出现逻辑死锁直接返回空结果
  • 更新后代码错误点:
    1. 滚动目标错误:Twitter的时间线滚动容器不是全局body节点,直接调用window.scrollTo滚动页面无法稳定触发后续内容加载
    2. 没有做爬取去重:每次全量获取当前DOM里的推文元素,都会重复爬取已经存过的回复,新加载的内容被重复数据覆盖
    3. 滚动后等待时长不足:触发滚动后没有等新内容渲染完成就获取页面高度、抓取元素,很容易误判已经到达页底
    4. Twitter采用虚拟滚动机制,滚出视口的旧回复会从DOM树中移除,全量抓取当前DOM元素的方式天然会漏数据
修正后可运行代码
from selenium import webdriver
from selenium.webdriver.common.by import By
import pandas as pd
import time

# 初始化浏览器
driver = webdriver.Chrome(executable_path=r"C:\Users\AppData\Local\SeleniumBasic\chromedriver")
driver.get("https://twitter.com/BBCWorld/status/1535676092450840578")
time.sleep(15) # 等待初始页面加载完成,可根据网络情况调整时长

tweets = []
# 用推文唯一链接做去重标识,避免重复爬取
collected_tweet_urls = set()
# 定位Twitter实际的时间线滚动容器
scroll_container = driver.find_element(By.XPATH, '//div[@aria-label="Timeline: Conversation"]')
last_height = driver.execute_script("return arguments[0].scrollHeight", scroll_container)
scroll_pause_time = 4

while True:
    # 抓取当前DOM里的所有推文元素
    current_tweets = driver.find_elements(By.XPATH, '//article[@data-testid="tweet"]')
    for item in current_tweets:
        # 提取推文唯一链接做去重判断
        try:
            tweet_link = item.find_element(By.XPATH, './/time/..').get_attribute('href')
            if tweet_link in collected_tweet_urls:
                continue
            collected_tweet_urls.add(tweet_link)
        except:
            continue
        
        # 跳过原推文,只抓取回复内容
        if tweet_link.endswith("1535676092450840578"):
            continue

        # 提取各字段内容
        try:
            date = item.find_element(By.XPATH, './/time').text
        except:
            date = '[empty]'
        
        try:
            text = item.find_element(By.XPATH, './/div[@data-testid="tweetText"]').text
        except:
            text = '[empty]'
        
        try:
            replying_to = item.find_element(By.XPATH, './/div[contains(text(), "Replying to")]//a').text
        except:
            replying_to = '[empty]'
        
        tweets.append([date, replying_to, text])
        print(f"已爬取回复数:{len(tweets)}  最新回复时间:{date}")
    
    # 滚动实际的时间线容器,而非全局window对象
    driver.execute_script("arguments[0].scrollTo(0, arguments[0].scrollHeight)", scroll_container)
    time.sleep(scroll_pause_time)
    
    # 计算新的滚动高度,判断是否到达页底
    new_height = driver.execute_script("return arguments[0].scrollHeight", scroll_container)
    if new_height == last_height:
        # 二次确认,避免因加载延迟误判到达页底
        time.sleep(2)
        new_height = driver.execute_script("return arguments[0].scrollHeight", scroll_container)
        if new_height == last_height:
            break
    last_height = new_height

# 保存结果到CSV
df = pd.DataFrame(tweets, columns=['Date of Tweet', 'Replying to', 'Tweet'])
df.to_csv(r'C:\Users\Downloads\Tweets.csv', index=False, encoding='utf-8')
print(f"爬取完成,共获取{len(tweets)}条回复")
driver.quit()
运行注意事项
  • 初始等待时间可根据本地网络速度调整,确保页面加载出第一批回复再开始爬取
  • 如果页面弹出登录窗口遮挡内容,可以在初始等待阶段手动关闭,也可以额外加代码自动处理弹窗
  • 滚动间隔不要设置过短,否则容易触发Twitter的反爬限制导致加载中断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 22:27:27