使用Python+Selenium爬取Twitter推文回复的滚动加载问题排查
问题排查结论
你的两段代码分别存在以下逻辑错误,导致无法爬取滚动加载的回复:
- 初始代码错误点:
all_tweets元素列表仅在进入while循环前获取1次,页面滚动后新加载的回复元素不会自动更新到这个列表里- 滚动操作写在了遍历回复的for循环内部,每处理1条回复就触发一次滚动,逻辑顺序完全混乱
- 无限循环没有设置合理终止条件,运行时会出现逻辑死锁直接返回空结果
- 更新后代码错误点:
- 滚动目标错误:Twitter的时间线滚动容器不是全局
body节点,直接调用window.scrollTo滚动页面无法稳定触发后续内容加载 - 没有做爬取去重:每次全量获取当前DOM里的推文元素,都会重复爬取已经存过的回复,新加载的内容被重复数据覆盖
- 滚动后等待时长不足:触发滚动后没有等新内容渲染完成就获取页面高度、抓取元素,很容易误判已经到达页底
- Twitter采用虚拟滚动机制,滚出视口的旧回复会从DOM树中移除,全量抓取当前DOM元素的方式天然会漏数据
- 滚动目标错误:Twitter的时间线滚动容器不是全局
修正后可运行代码
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
相关产品推荐
相关产品推荐

