如何在Jsoup中设置延迟以等待JSON加载完成后抓取数据?
问题解决思路
Jsoup本身不支持等待异步JavaScript加载的功能——它只是发送HTTP请求获取页面的初始静态HTML,不会执行页面里的JS代码,自然也等不到异步加载的内容。针对你的问题,有两种更靠谱的解决方式:
1. 直接请求数据接口(推荐)
NBA Stats页面的球队数据都是通过后端API异步返回的,你可以直接抓这个接口的JSON数据,比模拟页面加载高效得多:
- 打开浏览器开发者工具(F12),切换到「Network」标签,刷新页面
- 过滤「XHR/Fetch」请求,找到返回球队四要素数据的接口(参数通常包含
MeasureType=Four%20Factors) - 用Jsoup或者Java的Http客户端直接请求这个接口,拿到JSON后解析成
Team对象即可。
2. 使用支持JS渲染的工具
如果一定要模拟浏览器加载页面,可以用Selenium或HtmlUnit这类工具,它们能执行页面JS并等待内容加载:
Selenium示例代码
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.support.ui.WebDriverWait; import org.openqa.selenium.support.ui.ExpectedConditions; import java.util.ArrayList; import java.time.Duration; public class Comparison { public void loadTeams() { // 配置ChromeDriver路径,需提前下载对应版本的驱动 System.setProperty("webdriver.chrome.driver", "path/to/chromedriver"); WebDriver driver = new ChromeDriver(); WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); try { driver.get("https://www.nba.com/stats/teams/four-factors"); // 等待目标元素加载完成 wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("[field='TEAM_NAME']"))); ArrayList<Team> NBA = new ArrayList<>(30); // 提取数据 java.util.List<WebElement> teamElements = driver.findElements(By.cssSelector("[field='TEAM_NAME']")); java.util.List<WebElement> shootingElements = driver.findElements(By.cssSelector("[field='EFG_PCT']")); java.util.List<WebElement> turnoversElements = driver.findElements(By.cssSelector("[field='TM_TOV_PCT']")); java.util.List<WebElement> reboundsElements = driver.findElements(By.cssSelector("[field='OREB_PCT']")); java.util.List<WebElement> freethrowsElements = driver.findElements(By.cssSelector("[field='FTA_PCTS']")); for (int i = 0; i < teamElements.size(); i++) { String name = teamElements.get(i).getText(); double shootingScore = Double.parseDouble(shootingElements.get(i).getText()); double turnoversScore = Double.parseDouble(turnoversElements.get(i).getText()); double reboundsScore = Double.parseDouble(reboundsElements.get(i).getText()); double freethrowsScore = Double.parseDouble(freethrowsElements.get(i).getText()); NBA.add(new Team(name, shootingScore, turnoversScore, reboundsScore, freethrowsScore)); } // 测试输出 for(Team team : NBA) { System.out.println(team.getName()); } } catch (Exception e) { e.printStackTrace(); } finally { driver.quit(); } } }
对你现有代码的说明
你当前用getElementsByAttributeValue查找的元素,是页面JS执行后动态生成的,初始HTML里根本不存在,所以Jsoup直接抓取会返回空集合——就算你在Jsoup.connect().get()前加Thread.sleep(),拿到的还是初始静态HTML,一样没有目标内容。
内容的提问来源于stack exchange,提问作者ReginaldRey
相关产品推荐
相关产品推荐

