使用InputStream.openStream()获取YouTube页面返回非HTML代码的问题
解决YouTube页面爬取播放量的问题
问题根源
直接用URL.openStream()请求YouTube页面,会因为以下两个原因导致拿到的内容和浏览器检查元素不一致:
- YouTube会识别非浏览器请求,返回简化版静态HTML,播放量这类核心数据不会直接出现在初始响应里;
- 你的代码存在**重复调用
readLine()**的错误,导致一半页面内容被跳过,无法完整获取响应。
解决步骤
1. 修复内容读取错误
你的循环里,while(in.readLine() != null)已经读取了一行,之后又调用String s = (in.readLine()),这会跳过下一行数据。正确的读取方式应该是把读取的行存下来判断:
String line; while ((line = in.readLine()) != null) { code.add(line); c++; }
2. 模拟浏览器请求头
YouTube会验证请求的User-Agent字段,非浏览器请求会返回不同内容。改用HttpURLConnection设置请求头,模拟浏览器访问。
3. 解析页面中的JSON数据
YouTube的初始静态页面里,会把视频核心数据(包括播放量)放在名为ytInitialData的JavaScript变量里,我们可以提取这个变量的内容,解析JSON拿到播放量,不需要处理动态渲染的内容。
修改后的完整代码
package Project; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; public class WebScraper { public static void main(String[] args) throws IOException { URL website = new URL("https://www.youtube.com/watch?v=9h5JC-GLR6g"); HttpURLConnection connection = (HttpURLConnection) website.openConnection(); // 设置请求头,模拟Chrome浏览器 connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"); connection.setRequestProperty("Accept-Language", "en-US,en;q=0.9"); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); StringBuilder pageContent = new StringBuilder(); String line; // 正确读取所有行,避免丢行 while ((line = in.readLine()) != null) { pageContent.append(line); } in.close(); connection.disconnect(); // 提取ytInitialData变量的内容 Pattern pattern = Pattern.compile("ytInitialData\\s*=\\s*(.*?);\\s*</script>"); Matcher matcher = pattern.matcher(pageContent.toString()); if (matcher.find()) { String jsonData = matcher.group(1); // 从JSON中提取播放量,正式项目建议用Gson/Jackson等JSON库解析 Pattern viewCountPattern = Pattern.compile("\"viewCount\":\"([^\"]+)\""); Matcher viewMatcher = viewCountPattern.matcher(jsonData); if (viewMatcher.find()) { System.out.println("播放量:" + viewMatcher.group(1)); } else { System.out.println("未找到播放量"); } } else { System.out.println("未找到ytInitialData"); } } }
补充说明
- 正式项目中,建议使用JSON解析库(比如Gson、Jackson)处理
ytInitialData的JSON内容,正则匹配容易因页面结构变化失效; - YouTube页面结构可能随时调整,若上述方法失效,需重新检查页面数据存储位置;
- 频繁爬取可能触发反爬机制,建议控制请求频率,遵守网站
robots.txt规则。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

