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

如何通过Python Jupyter Notebook爬取单条推特的所有回复

你运行代码后得到如下输出:

Empty DataFrame
Columns: [Date of Tweet, Replying to, Tweet]
Index: []

问题根因

返回空结果是以下几个逻辑错误导致的:

  • 筛选条件完全不匹配:你遍历节点时要求div标签带href=True属性,但div是块级布局标签,原生不存在href属性,该筛选条件直接匹配不到任何有效节点,循环体从未执行。另外你选用的css-1dbjc4n是Twitter全站通用布局类,会匹配到数百个无关DOM节点,并非回复专属容器。
  • 未等待动态渲染完成:Twitter是前端动态渲染的单页应用,打开链接后需要等待接口返回、DOM绘制完成才能获取到内容,你打开页面后立刻抓取源码,此时回复区域还未加载。
  • 未处理懒加载机制:Twitter回复采用滚动触发的懒加载逻辑,不触发滚动操作只会加载首屏的少量回复,无法获取全量340条数据。
  • 定位方式稳定性差:你抓取的带r-前缀的class是Tailwind编译生成的动态类,Twitter每次前端发版都可能变更,用这类属性定位很容易失效。
  • 缺少校验与过滤逻辑:没有判断子节点是否存在就直接调用.text会触发空指针报错,也没有加过滤规则排除楼中楼里回复其他用户的内容。
修正实现

以下代码可直接在Jupyter Notebook中运行,适配你的采集需求:

  1. 前置依赖安装:先在Notebook中执行!pip install selenium beautifulsoup4 pandas openpyxl安装所需包,提前配置好ChromeDriver,保证和本地Chrome大版本一致。
  2. 代码逻辑说明:用显式等待替代固定等待,自动滚动加载全量回复,用稳定的data-testid属性做元素定位,自动筛选直接回复@BBCWorld的内容,最终导出为Excel文件。
import time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
import pandas as pd

# 初始化浏览器
driver = webdriver.Chrome()
driver.maximize_window()
target_url = "https://twitter.com/BBCWorld/status/1534777385249390593"
driver.get(target_url)

# 等待首屏内容加载
wait = WebDriverWait(driver, 20)
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '[data-testid="tweet"]')))

# 自动滚动加载所有回复
last_height = driver.execute_script("return document.body.scrollHeight")
scroll_pause_time = 2
while True:
    # 滚动到底部
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(scroll_pause_time)
    # 计算新的页面高度,判断是否加载完成
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        break
    last_height = new_height

# 全量内容加载完成后解析
content = driver.page_source
soup = BeautifulSoup(content, "html.parser")
all_tweets = soup.find_all(attrs={"data-testid": "tweet"})

dates = []
replying_to = []
tweet_texts = []

for tweet in all_tweets:
    # 跳过原推文,只处理回复
    is_original = tweet.find("a", href="/BBCWorld/status/1534777385249390593")
    if is_original:
        continue
    
    # 提取回复日期
    time_tag = tweet.find("time")
    if not time_tag:
        continue
    reply_date = time_tag.get("datetime", "")
    
    # 提取回复对象,筛选仅直接回复BBC的内容
    reply_target_tag = tweet.find(string=lambda text: text and "Replying to" in text)
    if not reply_target_tag:
        continue
    reply_target = reply_target_tag.find_parent().find_all("span")[-1].text
    if reply_target != "@BBCWorld":
        continue
    
    # 提取回复文本
    text_tag = tweet.find(attrs={"data-testid": "tweetText"})
    if not text_tag:
        continue
    reply_content = text_tag.text.replace("\n", " ").strip()
    
    dates.append(reply_date)
    replying_to.append(reply_target)
    tweet_texts.append(reply_content)

# 关闭浏览器
driver.quit()

# 导出为Excel
df = pd.DataFrame({
    "回复日期": dates,
    "回复对象": replying_to,
    "回复文本": tweet_texts
})
df.to_excel("BBC推文回复.xlsx", index=False)
print(f"共采集到{len(df)}条直接回复BBC的有效内容")
print(df.head())
注意事项
  • 如果运行时遇到登录拦截,可以在初始化浏览器后手动扫码登录Twitter,再继续执行后续逻辑,未登录状态下Twitter会限制内容展示。
  • 滚动等待时间可以根据你的网络情况调整,网络较差时可以把scroll_pause_time调大到3-5秒,避免漏加载内容。
  • 不要频繁短时间大量爬取,会触发Twitter的反爬限制,导致IP被临时封禁。

内容的提问来源于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 14:06:21