UNPKG

@kelvdra/scraper

Version:

A simple scraper by kelvdra.

162 lines (138 loc) 3.89 kB
import axios from "axios" import * as cheerio from "cheerio" import qs from "qs" import { URLSearchParams } from "url" const formatNumber = (n = 0) => Intl.NumberFormat("en", { notation: "compact" }).format(n) const formatDate = (unix) => unix ? new Date(unix * 1000).toLocaleString("id-ID", { day: "2-digit", month: "long", year: "numeric", hour: "2-digit", minute: "2-digit" }) : "-" export async function ttdl(url) { const payload = qs.stringify({ url, count: 12, cursor: 0, web: 1, hd: 1 }) const { data } = await axios.post( "https://www.tikwm.com/api/", payload, { headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", "Accept": "application/json, text/javascript, */*; q=0.01", "X-Requested-With": "XMLHttpRequest" } } ) if (data.code !== 0) { return { status: false, message: "Failed fetch TikTok" } } const v = data.data const id = v.id const isSlide = Array.isArray(v.images) && v.images.length > 0 return { status: true, creator: "@kelvdra/scraper", result: { title: v.title, taken_at: formatDate(v.create_time), region: v.region, id, durations: v.duration || 0, duration: v.duration ? `${v.duration} Seconds` : "Photo Slide", cover: `https://www.tikwm.com/video/cover/${id}.webp`, size: { nowm: v.size || 0, nowm_hd: v.hd_size || 0 }, video: isSlide ? null : { nowm: `https://www.tikwm.com/video/media/play/${id}.mp4`, nowm_hd: `https://www.tikwm.com/video/media/hdplay/${id}.mp4` }, slides: isSlide ? v.images : null, music: { id: v.music_info?.id || "", title: v.music_info?.title || "-", author: v.music_info?.author || "-", album: v.music_info?.album || "Unknown", url: `https://www.tikwm.com/video/music/${id}.mp3` }, stats: { views: formatNumber(v.play_count), likes: formatNumber(v.digg_count), comment: formatNumber(v.comment_count), share: formatNumber(v.share_count), download: formatNumber(v.download_count) }, author: { id: v.author?.id || "", fullname: v.author?.nickname || "", nickname: v.author?.unique_id || "", avatar: `https://www.tikwm.com/video/avatar/${id}.jpeg` } } } } export const ttdl2 = async (tiktokUrl) => { try { const hydra = await Tiktok(tiktokUrl) const payload = new URLSearchParams(); payload.append('q', tiktokUrl); payload.append('lang', 'en'); payload.append('cftoken', ''); const res = await axios.post( 'https://savetik.co/api/ajaxSearch', payload.toString(), { headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'X-Requested-With': 'XMLHttpRequest', }, } ); const data = res.data.data; const $ = cheerio.load(data); const title = $('.content h3').text().trim(); const thumbnail = $('.thumbnail img').attr('src') || null; const videoDownloads = []; $('.dl-action a').each((i, el) => { const type = $(el).text().trim().toLowerCase(); const url = $(el).attr('href'); if (url && url.startsWith('http')) { videoDownloads.push({ type, url }); } }); const photos = []; $('.photo-list .download-box li').each((i, el) => { const img = $(el).find('img').attr('src'); const url = $(el).find('a').attr('href'); if (img && url) { photos.push({ preview: img, url }); } }); return { status: true, creator: "@kelvdra/scraper", title, thumbnail, video: videoDownloads, photos } } catch (err) { return { status: false, message: err.message }; } }