|
@@ -78,7 +78,7 @@
|
|
|
不支持win7及以下系统
|
|
|
</el-link>
|
|
|
<el-link v-if="menuIndex == '10'" :underline="false" type="danger" style="text-align: center; font-size: 12px;">
|
|
|
- 非会员功能,仅提供测试试用
|
|
|
+ 非会员功能,仅提供测试
|
|
|
</el-link>
|
|
|
|
|
|
</div>
|
|
@@ -108,7 +108,7 @@
|
|
|
</template>
|
|
|
<template v-if="row.status == '3'">
|
|
|
<i class="el-icon-loading" style="font-size: 16px; color: #999;"></i>
|
|
|
- <span>视频下载中..<span v-if="row.num > 0">第{{row.num}}个</span></span>
|
|
|
+ <span>视频下载中..</span>
|
|
|
</template>
|
|
|
<template v-if="row.status == '4'">
|
|
|
<i class="el-icon-success" style="font-size: 16px; color: #19be6b;"></i>
|
|
@@ -118,10 +118,6 @@
|
|
|
<i class="el-icon-error" style="font-size: 16px; color: #ed4014;"></i>
|
|
|
<span>网络异常,请重试!</span>
|
|
|
</template>
|
|
|
- <template v-if="row.status == '6'">
|
|
|
- <i class="el-icon-error" style="font-size: 16px; color: #ed4014;"></i>
|
|
|
- <span>验证码拦截,请手动验证!</span>
|
|
|
- </template>
|
|
|
</template>
|
|
|
</vxe-column>
|
|
|
<vxe-column title="操作" width="80">
|
|
@@ -142,7 +138,7 @@
|
|
|
<el-input v-model="formData.title" placeholder="为空则默认使用网页标题前50个字符"></el-input>
|
|
|
</el-form-item>
|
|
|
<el-form-item label="网页链接" prop="url">
|
|
|
- <el-input type="textarea" :rows="10" v-if="menuIndex < 10" :placeholder="'请输入网址链接(例:' + exampleUrl[menuIndex-1] + ')'" v-model="formData.url"></el-input>
|
|
|
+ <el-input type="textarea" :rows="10" v-if="menuIndex < 10" :placeholder="'(例:' + exampleUrl[menuIndex-1] + ')'" v-model="formData.url"></el-input>
|
|
|
<el-input type="textarea" :rows="10" v-else :placeholder="'请输入网址链接'" v-model="formData.url"></el-input>
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
@@ -192,6 +188,7 @@
|
|
|
<p class="m-title">{{tipsDesc}}</p>
|
|
|
</div>
|
|
|
<div class="member-btn">
|
|
|
+ <el-button size="small" style="margin:0 10px;" @click="exportFile(true)" round v-if="usageTimes > 0">继续试用</el-button>
|
|
|
<el-button size="small" round type="primary" @click="openVip()">开通会员</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -220,6 +217,7 @@
|
|
|
import pjson from '/package.json'
|
|
|
// import puppeteer from 'puppeteer'
|
|
|
import puppeteer from 'puppeteer-extra'
|
|
|
+ const axios = require('axios');
|
|
|
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
|
|
|
const listNameArr = ['douyin','kuaishou','weibo','','','','','', '' ,'common'];
|
|
|
|
|
@@ -242,8 +240,9 @@
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
+ usageTimes: 3,
|
|
|
tipsModal: false,
|
|
|
- tipsDesc: "非VIP用户不能下载视频,如需完整功能请开通VIP会员。",
|
|
|
+ tipsDesc: "试用次数已经用完,请开通VIP会员使用。",
|
|
|
settingArr: ['mainImg'],
|
|
|
loginVisible: false,
|
|
|
addVisible: false,
|
|
@@ -276,7 +275,9 @@
|
|
|
commentImg: false,
|
|
|
video: false,
|
|
|
},
|
|
|
- exampleUrl: ['https://www.douyin.com', 'https://www.kuaishou.com', 'https://www.weibo.com'],
|
|
|
+ exampleUrl: ['https://www.douyin.com | 复制打开抖音,看看【某某某的作品】https://v.douyin.com/xxx1234/ 12/26 L@W.CD EaP:/',
|
|
|
+ 'https://www.kuaishou.com | https://v.kuaishou.com/AbcDef 春天就要出门踏春..."某某某 点击链接,打开【快手】直接观看!',
|
|
|
+ 'https://www.weibo.com/xxxxxx | 请使用单个视频网址链接'],
|
|
|
|
|
|
fileList: [],
|
|
|
|
|
@@ -328,6 +329,16 @@
|
|
|
});
|
|
|
});
|
|
|
|
|
|
+ let name = pjson.softInfo.softMid + pjson.name;
|
|
|
+ fs.stat(os.tmpdir() + separator + name, (err, stats) => {
|
|
|
+ if(!stats){
|
|
|
+ let data = 3;
|
|
|
+ fs.writeFile(os.tmpdir() + separator + name, data, (err) => {
|
|
|
+ if (err) throw err;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
},
|
|
|
methods: {
|
|
|
// 实时获取浏览器路径
|
|
@@ -403,7 +414,7 @@
|
|
|
this.clearList();
|
|
|
}
|
|
|
}).catch(() => {
|
|
|
-
|
|
|
+
|
|
|
});
|
|
|
},
|
|
|
// 清除列表
|
|
@@ -495,22 +506,8 @@
|
|
|
}
|
|
|
});
|
|
|
},
|
|
|
- settingGroup(name){
|
|
|
- let authority = this.$refs.headerRef.authority.isAuthority;
|
|
|
- let index = name.indexOf('video');
|
|
|
- if(index > -1 && !authority){ // 非会员选中下载视频选项-提示
|
|
|
- this.tipsModal = true;
|
|
|
- name.splice(index, 1);
|
|
|
- }
|
|
|
- },
|
|
|
// 清除缓存的后续操作
|
|
|
async clearCache(){
|
|
|
- this.jdStatus = 3;
|
|
|
- this.tbStatus = 3;
|
|
|
- this.redStatus = 3;
|
|
|
- this.alibabaStatus = 3;
|
|
|
- this.aliguojiStatus = 3;
|
|
|
-
|
|
|
if(this.loginBrowser){
|
|
|
await this.loginBrowser.close();
|
|
|
this.loginBrowser = null;
|
|
@@ -558,6 +555,10 @@
|
|
|
await this.loginBrowser.close();
|
|
|
this.loginBrowser = null;
|
|
|
}
|
|
|
+ if(this.videoBrowser){
|
|
|
+ await this.videoBrowser.close();
|
|
|
+ this.videoBrowser = null;
|
|
|
+ }
|
|
|
let authority = this.$refs.headerRef.authority.isAuthority;
|
|
|
if (!fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName)) {
|
|
|
fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName);
|
|
@@ -567,30 +568,46 @@
|
|
|
let fileList = this[listNameArr[index]+'List'];
|
|
|
|
|
|
if(fileList.length > 0){
|
|
|
- if (!authority && !flag) { // 非会员点击转换弹出提示框
|
|
|
- this.$refs.headerRef.memberModel = true;
|
|
|
- this.$refs.headerRef.isClick = true;
|
|
|
+ if (!authority && !flag) {
|
|
|
+ this.tipsModal = true;
|
|
|
+ let name = pjson.softInfo.softMid + pjson.name;
|
|
|
+ fs.readFile(os.tmpdir() + separator + name, (err, data) => {
|
|
|
+ if (err) throw err;
|
|
|
+ let num = data.toString();
|
|
|
+ if(['1','2','3'].indexOf(num) > -1){
|
|
|
+ this.usageTimes = Number(num);
|
|
|
+ this.tipsDesc = '您共有3次试用机会,目前剩余'+this.usageTimes+'次';
|
|
|
+ }else{
|
|
|
+ this.usageTimes = 0;
|
|
|
+ this.tipsDesc = '试用次数已经用完,请开通会员使用';
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!authority && flag && this.usageTimes < 1){
|
|
|
+ this.tipsModal = true;
|
|
|
+ this.tipsDesc = '试用次数已经用完,请开通会员';
|
|
|
return false;
|
|
|
- } else {
|
|
|
- this.$refs.headerRef.memberModel = false;
|
|
|
- this.loading = true;
|
|
|
- setTimeout(() => {
|
|
|
- this.loading = false;
|
|
|
- }, 60000);
|
|
|
}
|
|
|
|
|
|
+ this.tipsModal = false;
|
|
|
+ this.loading = true;
|
|
|
+ setTimeout(() => {
|
|
|
+ this.loading = false;
|
|
|
+ }, 10000)
|
|
|
+
|
|
|
if (!fs.existsSync(os.tmpdir() + separator + 'chrome-data-capture-video')) {
|
|
|
fs.mkdirSync(os.tmpdir() + separator + 'chrome-data-capture-video');
|
|
|
}
|
|
|
|
|
|
-
|
|
|
let taskArr = [];
|
|
|
let task = "";
|
|
|
let userDataDir = os.tmpdir() + separator + 'chrome-data-capture-video';
|
|
|
// 运行不同平台的浏览器
|
|
|
puppeteer.use(StealthPlugin());
|
|
|
this.videoBrowser = await puppeteer.launch({
|
|
|
- headless: false,
|
|
|
+ headless: true,
|
|
|
executablePath: this.initPath(),
|
|
|
userDataDir: userDataDir,
|
|
|
args: [
|
|
@@ -604,6 +621,18 @@
|
|
|
for(let i = 0; i < fileList.length; i++){
|
|
|
let item = fileList[i];
|
|
|
|
|
|
+ if(Number(this.usageTimes) >= 1){
|
|
|
+ let data = Number(this.usageTimes) - 1;
|
|
|
+ this.usageTimes -= 1;
|
|
|
+ let name = pjson.softInfo.softMid + pjson.name;
|
|
|
+ fs.writeFile(os.tmpdir() + separator + name, data, (err) => {
|
|
|
+ if (err) throw err;
|
|
|
+ });
|
|
|
+ }else{
|
|
|
+ videoBrowser
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
task = this.videoDownload(item, this.videoBrowser);
|
|
|
|
|
|
if(task){
|
|
@@ -642,7 +671,7 @@
|
|
|
}
|
|
|
},
|
|
|
|
|
|
- // 1 - 抖音视频下载
|
|
|
+ // 视频下载
|
|
|
async videoDownload(urlInfo, browser){
|
|
|
let task = await new Promise((resolve,reject) =>{
|
|
|
(async () => {
|
|
@@ -663,31 +692,92 @@
|
|
|
});
|
|
|
await page.goto(urlInfo.url, {waitUntil : 'networkidle2'});
|
|
|
|
|
|
- if(urlInfo.title){
|
|
|
- if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
|
|
|
- urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
|
|
|
- } else {
|
|
|
- fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
|
|
|
- urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
|
|
|
- }
|
|
|
- }else{
|
|
|
- await this.getTitle(page, urlInfo); // 生成页面标题对应的文件夹
|
|
|
- }
|
|
|
-
|
|
|
- urlInfo.status = '3';
|
|
|
- console.log(responseVideo);
|
|
|
- //视频下载
|
|
|
- for(let j = 0; j < responseVideo.length; j++){
|
|
|
- let num = Number(j) + 1;
|
|
|
- let suffix = '.mp4';
|
|
|
- let outputPath = urlInfo.newPath + '\\视频' + num + suffix;
|
|
|
- await this.downloadImage(responseVideo[j], outputPath, urlInfo);
|
|
|
- }
|
|
|
-
|
|
|
- this.loading = false;
|
|
|
- urlInfo.status = '4';
|
|
|
- resolve(true);
|
|
|
+ let pageInfo = await page.evaluate(() => {
|
|
|
+ let cHeight = document.documentElement.clientHeight;
|
|
|
+ let scrollHeight = document.body.scrollHeight;
|
|
|
+ return {'scrollHeight': scrollHeight, 'cHeight': cHeight}
|
|
|
+ });
|
|
|
+ let scrollHeight = pageInfo.scrollHeight;
|
|
|
+ let cHeight = pageInfo.cHeight;
|
|
|
|
|
|
+ let num = Math.ceil(scrollHeight / cHeight);
|
|
|
+ let start = -1;
|
|
|
+ let scrollInt = setInterval(async() => {
|
|
|
+ start ++;
|
|
|
+
|
|
|
+ let startTime = 30;
|
|
|
+ if(this.menuIndex == '10'){
|
|
|
+ startTime = 100;
|
|
|
+
|
|
|
+ let scrollHeight2 = await page.evaluate((start) => {
|
|
|
+ let scrollHeight = document.body.scrollHeight;
|
|
|
+ let cHeight = document.documentElement.clientHeight;
|
|
|
+ window.scrollTo({
|
|
|
+ top: cHeight * start,
|
|
|
+ behavior: "smooth"
|
|
|
+ });
|
|
|
+ return scrollHeight;
|
|
|
+ }, start);
|
|
|
+ num = Math.ceil(scrollHeight2 / cHeight);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(start > num || start > startTime){ // 防止页面过长,滚动30次自动停止
|
|
|
+ urlInfo.status = '3';
|
|
|
+ clearInterval(scrollInt);
|
|
|
+
|
|
|
+ if(urlInfo.title){
|
|
|
+ if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
|
|
|
+ urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
|
|
|
+ } else {
|
|
|
+ fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
|
|
|
+ urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ await this.getTitle(page, urlInfo); // 生成页面标题对应的文件夹
|
|
|
+ }
|
|
|
+
|
|
|
+ //detailImg:详情图;skuImg:sku图片;commentImg: 评论图;video: 视频
|
|
|
+ const imgInfo = await page.evaluate((authority) => {
|
|
|
+ let outObj = {
|
|
|
+ video: []
|
|
|
+ };
|
|
|
+ // 视频
|
|
|
+ let arr5 = document.querySelectorAll('video source');
|
|
|
+ for(let i=0; i< arr5.length; i++){
|
|
|
+ if(outObj.video.indexOf(arr5[i].src) < 0 && !arr5[i].src.startsWith('blob:https://')){
|
|
|
+ if(arr5[i].src){
|
|
|
+ outObj.video.push(arr5[i].src);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return outObj;
|
|
|
+ }, authority);
|
|
|
+
|
|
|
+ if(responseVideo.length > 0){
|
|
|
+ for(let l=0; l<responseVideo.length; l++){
|
|
|
+ if(imgInfo.video.indexOf(responseVideo[l]) < 0){
|
|
|
+ imgInfo.video.push(responseVideo[l]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ urlInfo.status = '3';
|
|
|
+ console.log(imgInfo.video);
|
|
|
+
|
|
|
+ //视频下载
|
|
|
+ for(let j = 0; j < imgInfo.video.length; j++){
|
|
|
+ let num = Number(j) + 1;
|
|
|
+ let suffix = '.mp4';
|
|
|
+ let outputPath = urlInfo.newPath + '\\视频' + num + suffix;
|
|
|
+ console.log(imgInfo.video[j]);
|
|
|
+ await this.downloadImage(imgInfo.video[j], outputPath, urlInfo);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.loading = false;
|
|
|
+ urlInfo.status = '4';
|
|
|
+ resolve(true);
|
|
|
+ }
|
|
|
+ }, 600);
|
|
|
}catch(e){
|
|
|
urlInfo.status = '5';
|
|
|
reject(e);
|
|
@@ -723,21 +813,27 @@
|
|
|
req.on('response', (data) => {
|
|
|
total_bytes = parseInt(data.headers['content-length']);
|
|
|
const status = data.statusCode;
|
|
|
- if (status < 200 || status >= 300) {
|
|
|
- //reject(false);
|
|
|
- this.$notify.error({
|
|
|
- title: '网络资源访问异常!- 1',
|
|
|
- message: imageUrl.slice(0,50)
|
|
|
- });
|
|
|
- }else if(isNaN(total_bytes)){
|
|
|
- //reject(false);
|
|
|
- this.$notify.error({
|
|
|
- title: '网络资源访问异常!- 2',
|
|
|
- message: imageUrl.slice(0,50)
|
|
|
- });
|
|
|
- }else{
|
|
|
- // console.log('下载中...')
|
|
|
+ if(this.menuIndex != '1'){
|
|
|
+ if (status < 200 || status >= 300) {
|
|
|
+ this.$notify.error({
|
|
|
+ title: '网络资源访问异常!- 1',
|
|
|
+ message: imageUrl.slice(0,50)
|
|
|
+ });
|
|
|
+ }else if(isNaN(total_bytes)){
|
|
|
+ this.$notify.error({
|
|
|
+ title: '网络资源访问异常!- 2',
|
|
|
+ message: imageUrl.slice(0,50)
|
|
|
+ });
|
|
|
+ }else{
|
|
|
+ // console.log('下载中...')
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ if(this.menuIndex == '1' && (status == 403 || isNaN(total_bytes))){
|
|
|
+ fs.unlinkSync(outputPath);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
});
|
|
|
|
|
|
req.on('data', (chunk) => {
|