网页分析过程
看过部分教程分析是通过APP抓包,所需数据较为麻烦,其实网页访问抖音也有无水印的地址返回。浏览器使用在F12访问抖音分享的链接,使用手机模式,链接首先会被重定向到iesdouyin.com,请求的JSON数据中,如图的两条链接为无水印的视频地址。
代码实现解析
Java语言版本我已经实现,通过上面分析可以知道在客户端能够完成视频解析,搞一个Windows的客户端,决定用C#写个控制台程序
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
namespace douyindlcli
{
class Program
{
static string fileName = "";
static void Main(string[] args)
{
Console.WriteLine("抖音无水印视频下载客户端,视频文件与软件在同一目录。查看更新https://ishare20.net/archives/131.html");
string text="";
while (text != "exit")
{
Console.WriteLine("请复制粘贴文本,自动解析:");
text = Console.ReadLine();
//Console.WriteLine(text);
string p = "https://v.douyin.com/\\S*";
if (Regex.IsMatch(text, p))
{
download(Regex.Match(text, p).Value);
Console.WriteLine();
Console.WriteLine();
}
else
{
Console.WriteLine("输入有误,请重新输入");
Console.WriteLine();
}
}
}
static void download(string url)
{
HttpWebRequest request =
(HttpWebRequest)WebRequest.Create(url);
request.UserAgent = "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36";
CookieContainer cookieContainer = new CookieContainer();
// Get the response.
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// Display the status.
Console.WriteLine(response.Headers.Get("Location"));
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
//string cc = response.GetResponseHeader("set-cookie");
//Console.WriteLine(cc);
//Console.WriteLine(cookieContainer.GetCookies(new Uri("https://www.iesdouyin.com")).ToString());
string p = "itemId: \"\\d*";
string itemIds = Regex.Match(responseFromServer, p, RegexOptions.None).Value.Replace("itemId: \"", "");
p = "dytk: \"\\w*";
string dytk = Regex.Match(responseFromServer, p, RegexOptions.None).Value.Replace("dytk: \"", "");
// Console.WriteLine(itemIds);
// Console.WriteLine(dytk);
request =
(HttpWebRequest)WebRequest.Create("https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=" + itemIds + "&dytk=" + dytk);
HttpWebResponse response2 = (HttpWebResponse)request.GetResponse();
string res2 = new StreamReader(response2.GetResponseStream()).ReadToEnd();
//Console.WriteLine(res2);
p = "url_list\":\\[\"https://aweme.snssdk.com/aweme/v1/play/\\?video_id.*?PackSourceEnum_PUBLISH";
MatchCollection matches = Regex.Matches(res2, p);
/* for (int ctr = 0; ctr < matches.Count; ctr++)
{
Console.WriteLine(ctr+" url is "+matches[ctr].Value);
}*/
string videoUrl = matches[1].Value.Replace("url_list\":[\"", "");
//Console.WriteLine(videoUrl);
WebClient webClient = new WebClient();
webClient.Headers.Add("user-agent", "Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Mobile Safari/537.36");
Console.WriteLine("正在下载......");
fileName = DateTime.Now.ToString("yyyyMMddHHmmss") + ".mp4";
webClient.DownloadFile(new Uri(videoUrl), fileName);
Console.WriteLine("下载完成,文件名:" + fileName);
//webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadProgressCallback);
// Cleanup the streams and the response.
reader.Close();
dataStream.Close();
response.Close();
response2.Close();
}
}
}