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

Python使用Selenium等工具爬取动态网页无法获取完整文本问题求助

可行解决方案

方案1:直接抓取后端接口(最优推荐)

该站点的所有卡片数据都是通过GraphQL接口动态拉取的,不需要解析前端渲染的HTML,直接请求接口就能拿到结构化的全量数据,是效率最高、最稳定的方案。
操作逻辑:

  • 打开浏览器F12开发者工具,切换到「网络」面板,筛选「Fetch/XHR」请求,刷新页面后找到名称带graphql的列表请求
  • 复制该请求的请求头、请求参数,直接用requests库模拟请求即可,返回的JSON数据里直接包含所有套餐的ID、名称、份额、购买链接等所有需要的字段
  • 定时请求接口后,对比两次返回的套餐ID列表的差异,就能直接判断是否有新套餐上线

示例代码:

import requests
import time

# 接口地址
url = "https://staking.pocketfives.com/api/graphql"
# 复制浏览器里的请求头,主要保证user-agent和浏览器一致即可
headers = {
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
    "content-type": "application/json"
}
# 复制浏览器里的请求体参数,即查询套餐列表的GraphQL语句
payload = {
    "operationName": "getStakeListings",
    "variables": {"page":1,"limit":100,"filter":{"type":"all","sort":"newest","search":"","tournamentSite":"","gameType":"","stakeType":"","buyin":{"min":0,"max":10000},"return":{"min":0,"max":100},"markup":{"min":0,"max":100},"sold":{"min":0,"max":100}}},
    "query": "query getStakeListings($page: Int, $limit: Int, $filter: StakeListingFilter) {\n  stakeListings(page: $page, limit: $limit, filter: $filter) {\n    items {\n      id\n      title\n      buyinAmount\n      markupPercent\n      totalSoldPercent\n      __typename\n    }\n    total\n    __typename\n  }\n}\n"
}

*注:如果接口返回异常,可以重新从浏览器里复制最新的请求头和请求体参数替换即可,一般只要User-Agent和请求体的查询语句正确就能正常返回。*

# 存储上一次的套餐ID集合
last_ids = set()

while True:
    resp = requests.post(url, json=payload, headers=headers)
    data = resp.json()
    current_list = data['data']['stakeListings']['items']
    current_ids = set([item['id'] for item in current_list])
    
    # 第一次运行初始化ID集合
    if not last_ids:
        last_ids = current_ids
        print(f"初始化完成,当前共有{len(current_list)}个套餐")
    else:
        new_ids = current_ids - last_ids
        if new_ids:
            print(f"检测到新套餐上线,ID为:{new_ids}")
            # 此处可自行添加提醒逻辑,比如发邮件、企业微信/钉钉通知等
            last_ids = current_ids
        else:
            print("暂无新套餐上线")
    # 每10分钟检查一次,可自行调整间隔时长
    time.sleep(600)

该方案不需要启动浏览器,资源占用极低,也不会出现内容加载不全的问题。

方案2:优化Selenium实现(如果一定要用浏览器渲染的话)

之前的写法问题在于用复制粘贴的方式拿内容,且固定sleep无法保证内容完全加载,优化后的写法直接从渲染后的DOM里提取卡片元素,用显式等待保证元素加载完成:
示例代码:

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 webdriver_manager.chrome import ChromeDriverManager
import time

# 启动无头模式,不需要打开浏览器窗口
options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument("--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36")

driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
driver.get("https://staking.pocketfives.com/staking/market-place")
wait = WebDriverWait(driver, 20)

# 等待卡片元素加载出来
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".stake-listing-card")))

# 滚动加载所有内容,每次滚动后等待新内容加载
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    time.sleep(2)
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        break
    last_height = new_height

# 提取所有卡片的内容
cards = driver.find_elements(By.CSS_SELECTOR, ".stake-listing-card")
current_data = []
for card in cards:
    # 提取卡片里需要的字段,比如标题、购买按钮存在与否等
    card_text = card.text
    card_id = card.get_attribute("data-id") # 如果有ID属性可直接提取
    current_data.append(card_id if card_id else card_text)

driver.quit()

# 后续对比两次current_data的差异即可判断是否有新内容上线

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 10:36:03