Android Studio中Java类下载TikTok视频异常:仅获取HTML文件
问题:TikTok视频下载代码仅获取HTML而非视频文件
我编写了一段用于下载TikTok视频的Java代码,但未能成功下载视频——仅获取了对应页面的HTML文件并命名为tiktok_video.mp4,视频播放器打开报错,文本阅读器可看到完整网页代码。
现有代码
DownloadTask.java
package com.zk.tiktokstudio; import android.os.AsyncTask; import android.os.Environment; import android.util.Log; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class DownloadTask extends AsyncTask<String, Integer, String> { private static final String TAG = "DownloadTask"; @Override protected String doInBackground(String... urls) { String videoUrl = urls[0]; String fileName = "tiktok_video.mp4"; try { URL url = new URL(videoUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.connect(); int fileLength = connection.getContentLength(); File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName); FileOutputStream fos = new FileOutputStream(outputFile); InputStream is = connection.getInputStream(); byte[] buffer = new byte[1024]; int len; long total = 0; while ((len = is.read(buffer)) != -1) { total += len; publishProgress((int) (total * 100 / fileLength)); fos.write(buffer, 0, len); } fos.close(); is.close(); return outputFile.getAbsolutePath(); } catch (Exception e) { Log.e(TAG, "Error downloading file: " + e.getMessage()); } return null; } @Override protected void onProgressUpdate(Integer... progress) { super.onProgressUpdate(progress); // 更新进度条或UI元素 } @Override protected void onPostExecute(String result) { super.onPostExecute(result); // 下载完成后的操作 } }
调用代码
String videoUrl = "https://www.tiktok.com/@username/video/1234567890"; DownloadTask downloadTask = new DownloadTask(); downloadTask.execute(videoUrl);
解决方案
核心问题
你传入的是TikTok网页URL,而非真实的视频文件URL,所以代码下载的是网页HTML。需要先从网页源码中提取真实视频地址,再传入下载任务。
具体修改步骤
添加HTML解析依赖
在app的build.gradle(Module级别)中添加Jsoup依赖,用于解析TikTok网页:dependencies { implementation 'org.jsoup:jsoup:1.17.2' }提取真实视频URL
新增方法从TikTok网页中提取视频的真实播放地址。注意TikTok可能会调整页面结构,以下两种方式可供尝试:import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; private String getRealVideoUrl(String webUrl) throws IOException { // 设置User-Agent模拟浏览器请求,避免被反爬拦截 Document doc = Jsoup.connect(webUrl) .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") .get(); // 方式1:从OG元数据中提取视频URL Element ogVideo = doc.select("meta[property=\"og:video\"]").first(); if (ogVideo != null) { return ogVideo.attr("content"); } // 方式2:从页面的JSON数据中提取(TikTok常用方式) Element nextDataScript = doc.select("script[id=\"__NEXT_DATA__\"]").first(); if (nextDataScript != null) { String jsonContent = nextDataScript.html(); // 这里可以用Gson/Jackson等JSON库解析字符串,提取video的playAddr字段 // 示例(需引入JSON解析库): // JsonObject jsonObject = new Gson().fromJson(jsonContent, JsonObject.class); // return jsonObject.getAsJsonObject("props") // .getAsJsonObject("pageProps") // .getAsJsonObject("videoData") // .getAsJsonObject("itemInfo") // .getAsJsonObject("itemStruct") // .getAsJsonObject("video") // .get("playAddr").getAsString(); } return null; }修改调用逻辑
先获取真实视频URL,再传入下载任务:String tiktokWebUrl = "https://www.tiktok.com/@username/video/1234567890"; new AsyncTask<String, Void, String>() { private static final String TAG = "VideoUrlFetcher"; @Override protected String doInBackground(String... strings) { try { String realVideoUrl = getRealVideoUrl(strings[0]); if (realVideoUrl != null) { new DownloadTask().execute(realVideoUrl); return realVideoUrl; } } catch (IOException e) { Log.e(TAG, "Failed to fetch real video URL: " + e.getMessage()); } return null; } }.execute(tiktokWebUrl);增强下载任务的兼容性
在DownloadTask的doInBackground方法中,添加User-Agent请求头,避免视频请求被拦截:HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 添加User-Agent connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"); connection.connect();
注意事项
- TikTok的页面结构可能会随时变化,若上述提取方式失效,需要重新分析页面源码找到新的视频URL位置。
- AsyncTask已被Android官方废弃,建议在新项目中使用Coroutines或ExecutorService替代。
- 确保应用已申请
WRITE_EXTERNAL_STORAGE(Android 10及以下)或使用MediaStore(Android 10+)的存储权限。
内容的提问来源于stack exchange,提问作者Mr Zohaib Khan
相关产品推荐
相关产品推荐

