app1/views.py
1 from django.shortcuts import render, redirect, HttpResponse 2 from django.http import StreamingHttpResponse, FileResponse 3 import json 4 import re 5 import requests 6 7 8 header = { 9 \'accept\': \'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\', 10 \'accept-language\': \'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7\', 11 \'pragma\': \'no-cache\', 12 \'upgrade-insecure-requests\': \'1\', 13 \'user-agent\': \'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Mobile Safari/537.36\' 14 } 15 16 17 def douyinurlpars(url, version=1): 18 url = re.findall(\'(https?://[^\s]+)\', url)[0] 19 20 print(url) 21 res = requests.get(url, headers=header, allow_redirects=True).url 22 # print(requests.headers) 23 # 视频id 24 item_id = res.split(\'/\')[5] 25 26 html_url = \'https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=\' + item_id 27 28 29 res2 = requests.get(html_url, headers=header).text 30 response_title = json.loads(res2)[\'item_list\'][0][\'desc\'] 31 # print(response) 32 if version == 1: 33 34 # 无水印视频url 35 video_url = json.loads(res2)[\'item_list\'][0][\'video\'][\'play_addr\'][\'url_list\'][0].replace(\'/playwm/\', \'/play/\') 36 else: 37 # 有水印视频url 38 video_url = json.loads(res2)[\'item_list\'][0][\'video\'][\'play_addr\'][\'url_list\'][0] 39 return video_url, response_title 40 41 42 def douyin(request): 43 if request.method == \'POST\': 44 url = request.POST.get(\'url\') 45 if not url: 46 return render(request, \'index.html\', {\'msg\': \'输入的链接地址不能为空!!!\'}) 47 res_url, title = douyinurlpars(url) 48 # res_url = \'https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200fg10000c3ourrbc77uf4e6l8s8g&ratio=720p&line=0\' 49 # title = \'很多事是科学无法解释的%诡异 %经典港剧\' 50 51 # 将url 进行编码,这里是为了res.html中给后端get传参,因为url中有特殊字符& (最开始想用来着,后来download函数没用,所以这一步其实也用不到了) 52 date = res_url.replace(\'&\', \'renew\') 53 54 return render(request, \'res.html\', {\'url\': res_url, \'title\': title, \'quote_url\': date}) 55 return render(request, \'index.html\') 56 57 # 备注下,download func 暂时没用,如果有想用的自己研究下也行。小事儿。。。 58 def download(request): 59 60 head = { 61 \'Accept\': \'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\', 62 \'Accept-Encoding\': \'gzip, deflate\', 63 \'Accept-Language\': \'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7\', 64 \'Cache-Control\': \'max-age=0\', 65 \'Connection\': \'keep-alive\', 66 \'Upgrade-Insecure-Requests\': \'1\', 67 \'User-Agent\': \'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.164 Mobile Safari/537.36\', 68 } 69 70 quote_url = request.GET.get(\'quote_url\') 71 # print(type(quote_url), str(quote_url)) 72 73 url = quote_url.replace(\'renew\', \'&\') 74 file_name = request.GET.get(\'title\') + \'1.mp4\' 75 # file_name = \'a.mp4\' 76 print(quote_url) 77 print(url) 78 print(file_name) 79 # url = \'https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200fg10000c3ourrbc77uf4e6l8s8g&ratio=720p&line=0\' 80 81 # 文件迭代,减少内存压力 82 def generate(url): 83 r = requests.get(url, headers=head, stream=True) 84 for chunk in r.iter_content(chunk_size=512): 85 if chunk: 86 yield chunk 87 88 response = StreamingHttpResponse(generate(url)) 89 response[\'content_type\'] = "application/octet-stream" 90 response[\'Content-Disposition\'] = \'attachment; filename="{}"\'.format(file_name) 91 return response
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>抖音解析</title> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> </head> <body> <h1 class="text-center">抖音无水印视频解析</h1> <form class="form-horizontal" action="{% url \'app1:douyin\' %}" method="post"> {% csrf_token %} <br> <div class="form-group form-group-lg"> <div> <input name="url" class="form-control input-lg text-center" type="text" id="formGroupInputLarge" placeholder="放入复制的链接,不用去除链接中的文字和符号"> <br> <button class="form-control btn btn-primary btn-lg">提交</button> </div> </div> {% if msg %} <div class="text-center alert alert-danger alert-dismissible " role="alert"> <strong>{{ msg }}</strong> </div> {% endif %} </form> <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) --> <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script> <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 --> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script> </body> </html>
res.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="referrer" content="no-referrer" /> <title>视频页</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> <style> html, body { background: #393D49; height: 100%; } </style> </head> <body> <div class="text-center"> <h3><a name="title">{{ title }}</a></h3> <!--<p class="lead"><a href="{{ url }}">查看视频</a></p>--> </div> <div class=" text-center"> <video width="240" height="420" controls="controls"> <source src="{{ url }}" type="video/mp4"/> </video> </div> <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) --> <script src="https://cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script> <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 --> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script> </body> </html>
备注
注意,用django写好后,自己部署完毕。这台机器尽量不要用固定的外网ip地址,抖音对固定的IP地址有做反扒。至于怎么每次运行时更换外网IP地址,有需要的可以留言,我们交流交流。