@saipulanuar/tiktok-scraper-ts
Version:
A scraper for tiktok videos, users and more
2 lines • 10.7 kB
JavaScript
var S=Object.defineProperty;var u=(s,i)=>S(s,"name",{value:i,configurable:!0});import{fileURLToPath as R}from"url";import N from"path";var O=u(()=>R(import.meta.url),"getFilename"),D=u(()=>N.dirname(O()),"getDirname"),c=D();import*as U from"cheerio";import x from"miniget";import A from"node-fetch";import{createWriteStream as y,existsSync as T,mkdirSync as j,unlinkSync as F}from"node:fs";import*as V from"puppeteer";import P from"node:http";import W from"node:https";import{exit as $}from"node:process";var f=class{constructor(i,e,t,o,r,a,d,n,h,p,b,v,I,k,M){this.id=i,this.uniqueId=e,this.nickname=t,this.avatar=o,this.signature=r,this.createdAt=a,this.verified=d,this.secretUID=n,this.bioLink=h,this.privateAccount=p,this.isUnderAge18=b,this.followers=v,this.following=I,this.hearts=k,this.videos=M}};u(f,"User");var C=class{constructor(i,e,t,o,r,a,d,n,h,p){this.author=i,this.video=e,this.audio=t,this.shareCount=o,this.likesCount=r,this.commentCount=a,this.playCount=d,this.createdAt=n,this.tiktokLink=h,this.thumbnail=p}};u(C,"TikTokResult");var g=class{constructor(i,e,t,o,r,a,d,n,h,p,b,v,I,k,M,E,L){this.id=i,this.description=e,this.createdAt=t,this.height=o,this.width=r,this.duration=a,this.resolution=d,this.shareCount=n,this.likesCount=h,this.commentCount=p,this.playCount=b,this.downloadURL=v,this.cover=I,this.dynamicCover=k,this.playURL=M,this.format=E,this.author=L}};u(g,"Video");var w=class{constructor(i,e,t,o,r,a,d,n,h){this.id=i,this.title=e,this.playURL=t,this.coverLarge=o,this.coverThumb=r,this.author=a,this.duration=d,this.original=n,this.album=h}};u(w,"Music");var l=class{constructor(i){this._cookies="";this._cookies=i}async requestWebsite(i,e){let t=new P.Agent({keepAlive:!0,maxSockets:20}),o=new W.Agent({keepAlive:!0,maxSockets:20}),r={agent:h=>h.protocol=="http:"?t:o,headers:{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36",Accept:"application/json, text/plain, */*","Accept-Encoding":"gzip, deflate, br","Cache-Control":"no-cache",Connection:"keep-alive",Cookie:`${this._cookies}`}},d=await(await A(`${i}`,e||r)).text();return U.load(d,{xmlMode:!0})}extractJSONObject(i){let e=i.split('<script id="SIGI_STATE" type="application/json">')[1].indexOf("<\/script>");return i.split('<script id="SIGI_STATE" type="application/json">')[1].slice(0,e)}checkJSONExisting(i){try{return!!JSON.parse(i)}catch{}}async requestWithPuppeteer(i){let e=await V.launch({headless:!0,args:["--no-sandbox","--disable-setuid-sandbox"]}),o=await(await e.newPage()).goto(i);if(o==null)throw new Error("Could not load the desired Page!");let r=await o.text();return await e.close(),this.extractJSONObject(r)}handleHTMLContent(i){let e=i,t=e.split("window['SIGI_STATE']=")[1].indexOf(";window['SIGI_RETRY']=");return JSON.parse(e.split("window['SIGI_STATE']=")[1].slice(0,t))}async TryFetch(i){let e=await this.requestWebsite(i);if(this.checkJSONExisting(e("#SIGI_STATE").text()))return JSON.parse(e("#SIGI_STATE").text());{let t=await this.requestWithPuppeteer(i);return JSON.parse(t)}}async video(i,e){if(!i)throw new Error("A video URL must be provided");let t=await this.TryFetch(i),o=t.ItemList?.video?.list[0]??0;if(o==0)return console.log("Could not find the Video on Tiktok!");let r=e?await this.noWaterMark(t.ItemModule[o].video.id):t.ItemModule[o].video.downloadAddr.trim();return new g(t.ItemModule[o].video.id,t.ItemModule[o].desc,new Date(Number(t.ItemModule[o].createTime)*1e3).toLocaleDateString(),Number(t.ItemModule[o].video.height),Number(t.ItemModule[o].video.width),Number(t.ItemModule[o].video.duration),t.ItemModule[o].video.ratio,t.ItemModule[o].stats.shareCount,t.ItemModule[o].stats.diggCount,t.ItemModule[o].stats.commentCount,t.ItemModule[o].stats.playCount,r,t.ItemModule[o].video.cover,t.ItemModule[o].video.dynamicCover,r,t.ItemModule[o].video.format,t.ItemModule[o].nickname)}async user(i){if(!i)throw new Error("Please enter a username");let e=await this.TryFetch(`https://www.tiktok.com/@${i}`),t=e.UserModule.users[i];return new f(t.id,t.uniqueId,t.nickname,t.avatarLarger,t.signature.trim(),new Date(t.createTime*1e3).toLocaleDateString(),t.verified,t.secUid,t?.bioLink?.link,t.privateAccount,t.isUnderAge18,e.UserModule.stats[i].followerCount,e.UserModule.stats[i].followingCount,e.UserModule.stats[i].heart,e.UserModule.stats[i].videoCount)}async getAllVideosFromUser(i){if(!i)throw new Error("You must provide a username!");let{secretUID:e}=await this.user(`${i}`);if(!e)throw new Error("Couuld not find user UID!");let t="",o=[],r=[],a=await this.fetchUserVideos(e,t);if(a?.itemList&&(r.push(a.itemList),t=a.cursor),a?.hasMore===!0)for(;;){let d=await this.fetchUserVideos(e,t);if(r.push(d.itemList),t=d.cursor,d.hasMore==!1)break}for(let d of r)for(let n of d)o.push(new g(n.id,n.desc,new Date(Number(n.createTime)*1e3).toLocaleDateString(),Number(n.video?.height),Number(n.video?.width),Number(n.video?.duration),n.video?.ratio,n?.stats?.shareCount,n?.stats?.diggCount,n?.stats?.commentCount,n?.stats?.playCount,n.video?.downloadAddr.trim(),n?.video?.cover,n?.video?.dynamicCover,n.video?.downloadAddr.trim(),n?.video?.format,n.author));return o}async fetchUserVideos(i,e){return await(await A(`https://m.tiktok.com/api/post/item_list/?aid=1988&count=35&secUid=${i}&cursor=${e}`,{headers:{"Accept-Encoding":"gzip, deflate, br",Connection:"keep-alive",Cookie:"_ttp=20giOKHgEqBuTmVEAZtfn1d2hY7; ttwid=1%7CTQIxz0XiWfp7pukZEMXLVKPHz-8yYy-hFtsuP9QH6qQ%7C1666445148%7Cb9a0888038642e8181e42a5fdaac6f198842f5be356d87316064ad3bf1f53e33; _abck=2C43FEAB6D7433C06BC6BA58A7ABDFFC~-1~YAAQPeUVAveE++WDAQAAMPXe/wjYc6xTVTh4Ke+kHGxxgJfxDRcT0ee3UkTu3sYlI0/69c8OLY/v+ofiwRwfxveidVDxaESN7yjCkBHSBV2dseB7rOBVUGyOtm1hGsf/hGHEVHVopulk0NAeiJoOWsARcJDql0k07Qhcv2pmP5lYQ17fhi75Lm6tFGCSwl+O9+idv5u8yCSf675M33/mdm5vuhXjPHCASZIjZVftaPqSdJdEDy6Z772SQ3VwQhMMOMpF51aj29e99OCtMRPM3bmbda16q4UAo2m8guw0c3HxhdCTYd/R7MmqDbr51KPRFFYiGmSJj49PstRweWQY4WjaAO+0Bx9ejfYha7dp1Cp/54sYHlI2oYIpTh9c9x2NbNRlFBEghhWK+d4=~-1~-1~-1; cookie-consent={%22ga%22:true%2C%22af%22:true%2C%22fbp%22:true%2C%22lip%22:true%2C%22bing%22:true%2C%22ttads%22:true%2C%22reddit%22:true%2C%22version%22:%22v8%22}; msToken=2ly4AKsEPS3tqqICLrucL3vfxEGgfhV8yzbp4ntCJRwbL0qBr1HGS-39CmfhhfoJgh9AjO-ZZw8yPTeh7VLiaRHPjEFNe-C4p0itrLBHjbjrrnc2vk19rUJNgefqanCQvlY5zg==; bm_sz=F7CD2096F100E2BBF898F75FB340B07E~YAAQPeUVAviE++WDAQAAMPXe/xGNyQyHT0csQ+5X+XBNhPNWpfB37e3Cc+Cy6ca1L3bb3+xVQCSUzwOAZt3AfYCmfis2wGK9oUPRr+6Osp3ZBR2QFOyQX7e3HU8optmJ0xHZV0D6MZc4YzD0xlxoFSkjOxb754ZanGbuFyLJgPCXD926sCOgNBQuGx6Zgk29NwARbeoupgQrRptG/t6eFoJcDA3vL+nHqMpm6XtIXV7i4O5kXn7+E+eCybbMVhkTt+qTnMfot7ULa1NNQSDaQgwZa1UIw8eKs71dyE0cikQFjc4=~4473158~3354937; tt_csrf_token=cBoP4X6a-FRM6sy440ir5_77ij4DfchzNfWQ","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:106.0) Gecko/20100101 Firefox/106.0",Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"}})).json()}async getMusic(i){if(!i)throw new Error("You must provide a link!");let e=await this.TryFetch(i),t=e.ItemList.video.list[0];return new w(e.ItemModule[t].music.id,e.ItemModule[t].music.title,e.ItemModule[t].music.playUrl,e.ItemModule[t].music.coverLarge,e.ItemModule[t].music.coverThumb,e.ItemModule[t].music.authorName,Number(e.ItemModule[t].music.duration),e.ItemModule[t].music.original,e.ItemModule[t].music.album)}async downloadAllVideosFromUser(i,e){if(!i)throw new Error("Please enter a username!");let t=await this.getAllVideosFromUser(i);if(!t)throw new Error("No Videos were found for this username. Either the videos are private or the user has not videos");if(!e.path){if(e.path=`${c}/../${i}`,T(e.path)){console.log("A folder with this username exists, that is unusual!");try{F(e.path)}catch(o){console.log(`[ERROR] Could not remove ${e.path}
Error Message: ${o.message}`),$(1)}}T(e.path)||j(e.path)}if(e.watermark){for(let[o,r]of t.entries()){console.log(`Downloading Video: ${r.description?r.description:r.id}, [${o+1}/${t.length}]`);let a=await this.noWaterMark(r.id);if(!a){console.log(`Could not fetch ${r.description?r.description:r.id} with no watermark`);continue}x(a).pipe(y(`${e.path}/${r.id}_${r.resolution}.${r.format}`))}return}for(let[o,r]of t.entries())console.log(`Downloading Video: ${r.description?r.description:r.id}, [${o+1}/${t.length}]`),x(r.downloadURL).pipe(y(`${e.path}/${r.id}_${r.resolution}.${r.format}`))}async noWaterMark(i){let e="";if(i.startsWith("https")){let a=await this.video(i);if(!a?.id)return console.log("Could not extract the Video ID from Tiktok!");e=a.id}else e=i;let o=await(await A("https://api2.musical.ly/aweme/v1/aweme/detail/?aweme_id="+e)).json();if(!o)throw new Error("There was an Error retrieveing this video without watermark!");let r=o.aweme_detail.video.play_addr;if(!r)throw new Error("There was an Error retrieveing this video without watermark!");return r.url_list[0]}async hashTag(i){if(!i)throw new Error("You must provide a tag name to complete the search!");let e=await this.TryFetch(`https://www.tiktok.com/tag/${i}`),{ItemList:t}=e,o=[];for(let r of t.challenge.list)o.push(new g(e.ItemModule[r].video.id,e.ItemModule[r].desc,new Date(Number(e.ItemModule[r].createTime)*1e3).toLocaleDateString(),Number(e.ItemModule[r].video.height),Number(e.ItemModule[r].video.width),Number(e.ItemModule[r].video.duration),e.ItemModule[r].video.ratio,e.ItemModule[r].stats.shareCount,e.ItemModule[r].stats.diggCount,e.ItemModule[r].stats.commentCount,e.ItemModule[r].stats.playCount,e.ItemModule[r].video.downloadAddr.trim(),e.ItemModule[r].video.cover,e.ItemModule[r].video.dynamicCover,e.ItemModule[r].video.playAddr.trim(),e.ItemModule[r].video.format,e.ItemModule[r].author));return o}};u(l,"TTScraper");async function Ae(s,i){if(!s)throw new Error("You must provide a Tiktok video url!");return await new l().video(s,i)}u(Ae,"fetchVideo");async function xe(s){if(!s)throw new Error("You must provide a username!");return await new l().user(s)}u(xe,"fetchUser");async function ye(s){if(!s)throw new Error("You must provide a username!");return await new l().getAllVideosFromUser(s)}u(ye,"fetchAllVideosFromUser");async function Te(s){if(!s)throw new Error("You must provide a Tiktok video url!");return await new l().getMusic(s)}u(Te,"fetchMusic");async function Ue(s){if(!s)throw new Error("You must provide a Tiktok video url!");return await new l().noWaterMark(s)}u(Ue,"fetchVideoNoWaterMark");async function Ve(s){if(!s)throw new Error("You must provide a tiktok hashtag");return await new l().hashTag(s)}u(Ve,"hashtag");export{w as Music,l as TTScraper,C as TikTokResult,f as User,g as Video,ye as fetchAllVideosFromUser,Te as fetchMusic,xe as fetchUser,Ae as fetchVideo,Ue as fetchVideoNoWaterMark,Ve as hashtag};