@kelvdra/scraper
Version:
A simple scraper by kelvdra.
162 lines (138 loc) • 3.89 kB
JavaScript
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
};
}
}