better-ani-scraped 1.6.7 → 1.6.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -3,7 +3,7 @@ import { getVideoUrlFromEmbed } from "../../index.js"; // REPLACE BY "from 'bett
|
|
|
3
3
|
const main = async () => {
|
|
4
4
|
const embedUrlSibnet = "https://video.sibnet.ru/shell.php?videoid=4291083";
|
|
5
5
|
const embedUrlSendvid = "https://sendvid.com/embed/4vzpcb0q";
|
|
6
|
-
const embedUrlVidmoly = "https://vidmoly.to/embed-
|
|
6
|
+
const embedUrlVidmoly = "https://vidmoly.to/embed-rvqrwg5zk37w.html";
|
|
7
7
|
const embedUrlOneupload = "https://oneupload.net/embed-axdrxh1y3p37.html";
|
|
8
8
|
|
|
9
9
|
const videoUrlSibnet = await getVideoUrlFromEmbed("sibnet", embedUrlSibnet)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "better-ani-scraped",
|
|
3
|
-
"version": "1.6.
|
|
4
|
-
"description": "Scrape anime data from different sources (only anime-sama.fr for the moment)",
|
|
3
|
+
"version": "1.6.81",
|
|
4
|
+
"description": "Scrape anime data from different sources (only anime-sama.fr, animepahe and crunchyroll for the moment)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1"
|
package/scrapers/animesama.js
CHANGED
|
@@ -36,13 +36,19 @@ async function ensureChromiumInstalled(customPath) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function getHeaders(referer = BASE_URL) {
|
|
39
|
+
const userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' + '(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36';
|
|
39
40
|
return {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
headers: {
|
|
42
|
+
"User-Agent": userAgent,
|
|
43
|
+
"Accept-Language": "fr-FR,fr;q=0.9,en;q=0.8",
|
|
44
|
+
"Referer": referer,
|
|
45
|
+
},
|
|
46
|
+
userAgent
|
|
43
47
|
};
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
|
|
51
|
+
|
|
46
52
|
export async function searchAnime(
|
|
47
53
|
query,
|
|
48
54
|
limit = 10,
|
|
@@ -53,6 +59,7 @@ export async function searchAnime(
|
|
|
53
59
|
const languages = Array.isArray(wantedLanguages) ? wantedLanguages : ["vostfr", "vf", "vastfr"];
|
|
54
60
|
const types = Array.isArray(wantedTypes) ? wantedTypes : ["Anime", "Film"];
|
|
55
61
|
|
|
62
|
+
const { headers } = getHeaders(CATALOGUE_URL);
|
|
56
63
|
const isWanted = (text, list) =>
|
|
57
64
|
list.length === 0 || list.some(item => text.toLowerCase().includes(item.toLowerCase()));
|
|
58
65
|
|
|
@@ -64,7 +71,7 @@ export async function searchAnime(
|
|
|
64
71
|
? `${CATALOGUE_URL}/?search=${encodeURIComponent(query)}`
|
|
65
72
|
: `${CATALOGUE_URL}/?search=${encodeURIComponent(query)}&page=${pageNum}`;
|
|
66
73
|
|
|
67
|
-
const res = await axios.get(url, { headers:
|
|
74
|
+
const res = await axios.get(url, { headers: headers });
|
|
68
75
|
const $ = cheerio.load(res.data);
|
|
69
76
|
|
|
70
77
|
const containers = $("a.flex.divide-x");
|
|
@@ -125,7 +132,9 @@ export async function searchAnime(
|
|
|
125
132
|
}
|
|
126
133
|
|
|
127
134
|
export async function getSeasons(animeUrl, languagePriority = ["vostfr", "vf", "va", "vkr", "vcn", "vqc", "vf1", "vf2"]) {
|
|
128
|
-
const
|
|
135
|
+
const { headersCatalog } = getHeaders(CATALOGUE_URL);
|
|
136
|
+
const { headersAnime } = getHeaders(animeUrl);
|
|
137
|
+
const res = await axios.get(animeUrl, { headers: headersCatalog });
|
|
129
138
|
const html = res.data;
|
|
130
139
|
|
|
131
140
|
const mainAnimeOnly = html.split("Anime Version Kai")[0];
|
|
@@ -155,19 +164,19 @@ export async function getSeasons(animeUrl, languagePriority = ["vostfr", "vf", "
|
|
|
155
164
|
const href = match[2].split("/")[0];
|
|
156
165
|
const fullUrl = `${CATALOGUE_URL}/${animeName}/${href}/${language}`;
|
|
157
166
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
} catch (err) {
|
|
167
|
-
// Ignore invalid URLs
|
|
167
|
+
try {
|
|
168
|
+
const check = await axios.head(fullUrl, {
|
|
169
|
+
headers: headersAnime,
|
|
170
|
+
});
|
|
171
|
+
if (check.status === 200) {
|
|
172
|
+
languageAvailable = true;
|
|
173
|
+
seasons.push({ title, url: fullUrl });
|
|
168
174
|
}
|
|
175
|
+
} catch (err) {
|
|
176
|
+
// Ignore missing URLs
|
|
169
177
|
}
|
|
170
178
|
}
|
|
179
|
+
}
|
|
171
180
|
|
|
172
181
|
if (languageAvailable) {
|
|
173
182
|
return { language, seasons };
|
|
@@ -179,6 +188,7 @@ export async function getSeasons(animeUrl, languagePriority = ["vostfr", "vf", "
|
|
|
179
188
|
|
|
180
189
|
|
|
181
190
|
export async function getEpisodeTitles(seasonUrl, customChromiumPath) {
|
|
191
|
+
const { headers, userAgent } = getHeaders(seasonUrl);
|
|
182
192
|
let browser;
|
|
183
193
|
try {
|
|
184
194
|
const puppeteer = await import('puppeteer');
|
|
@@ -187,11 +197,15 @@ export async function getEpisodeTitles(seasonUrl, customChromiumPath) {
|
|
|
187
197
|
browser = await puppeteer.launch({
|
|
188
198
|
headless: true,
|
|
189
199
|
executablePath,
|
|
190
|
-
args: [
|
|
200
|
+
args: [
|
|
201
|
+
'--no-sandbox',
|
|
202
|
+
'--disable-setuid-sandbox',
|
|
203
|
+
]
|
|
204
|
+
|
|
191
205
|
});
|
|
192
206
|
|
|
193
207
|
const page = await browser.newPage();
|
|
194
|
-
|
|
208
|
+
await page.setExtraHTTPHeaders(headers);
|
|
195
209
|
await page.setRequestInterception(true);
|
|
196
210
|
page.on('request', (req) => {
|
|
197
211
|
const blocked = ['image', 'stylesheet', 'font', 'media'];
|
|
@@ -201,9 +215,13 @@ export async function getEpisodeTitles(seasonUrl, customChromiumPath) {
|
|
|
201
215
|
req.continue();
|
|
202
216
|
}
|
|
203
217
|
});
|
|
204
|
-
|
|
218
|
+
await page.setUserAgent(userAgent);
|
|
219
|
+
await page.evaluateOnNewDocument(() => {
|
|
220
|
+
Object.defineProperty(navigator, 'webdriver', { get: () => false });
|
|
221
|
+
});
|
|
205
222
|
await page.goto(seasonUrl, { waitUntil: 'domcontentloaded' });
|
|
206
223
|
await page.waitForSelector('#selectEpisodes');
|
|
224
|
+
|
|
207
225
|
|
|
208
226
|
const titres = await page.$$eval('#selectEpisodes option', options =>
|
|
209
227
|
options.map(o => o.textContent.trim())
|
|
@@ -226,8 +244,10 @@ export async function getEmbed(
|
|
|
226
244
|
includeInfo = false,
|
|
227
245
|
customChromiumPath
|
|
228
246
|
) {
|
|
247
|
+
const { headersSplit } = getHeaders(seasonUrl.split("/").slice(0, 5).join("/"));
|
|
248
|
+
const { headers } = getHeaders(seasonUrl);
|
|
229
249
|
const res = await axios.get(seasonUrl, {
|
|
230
|
-
headers:
|
|
250
|
+
headers: headersSplit,
|
|
231
251
|
});
|
|
232
252
|
|
|
233
253
|
const $ = cheerio.load(res.data);
|
|
@@ -245,7 +265,7 @@ export async function getEmbed(
|
|
|
245
265
|
: seasonUrl + "/" + scriptTag;
|
|
246
266
|
|
|
247
267
|
const episodesJs = await axios
|
|
248
|
-
.get(scriptUrl, { headers:
|
|
268
|
+
.get(scriptUrl, { headers: headers })
|
|
249
269
|
.then((r) => r.data);
|
|
250
270
|
|
|
251
271
|
const matches = [...episodesJs.matchAll(/var\s+(eps\d+)\s*=\s*(\[[^\]]+\])/g)];
|
|
@@ -302,13 +322,13 @@ export async function getEmbed(
|
|
|
302
322
|
if (selectedUrl) break;
|
|
303
323
|
}
|
|
304
324
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
325
|
+
finalEmbeds.push({
|
|
326
|
+
title: null,
|
|
327
|
+
url: selectedUrl || null,
|
|
328
|
+
host: selectedHost || null
|
|
329
|
+
});
|
|
311
330
|
}
|
|
331
|
+
}
|
|
312
332
|
|
|
313
333
|
const titles = await getEpisodeTitles(seasonUrl, customChromiumPath);
|
|
314
334
|
finalEmbeds.forEach((embed, i) => {
|
|
@@ -331,7 +351,8 @@ export async function getEmbed(
|
|
|
331
351
|
|
|
332
352
|
|
|
333
353
|
export async function getAnimeInfo(animeUrl) {
|
|
334
|
-
const
|
|
354
|
+
const { headers } = getHeaders(CATALOGUE_URL);
|
|
355
|
+
const res = await axios.get(animeUrl, { headers: headers });
|
|
335
356
|
const $ = cheerio.load(res.data);
|
|
336
357
|
|
|
337
358
|
const cover = $("#coverOeuvre").attr("src");
|
|
@@ -367,6 +388,7 @@ export async function getAvailableLanguages(
|
|
|
367
388
|
wantedLanguages = ["vostfr", "vf", "va", "vkr", "vcn", "vqc", "vf1", "vf2"],
|
|
368
389
|
numberEpisodes = false
|
|
369
390
|
) {
|
|
391
|
+
const { headers } = getHeaders(CATALOGUE_URL);
|
|
370
392
|
const languageLinks = [];
|
|
371
393
|
|
|
372
394
|
// Iterate over each possible language and check if the page exists
|
|
@@ -374,7 +396,7 @@ export async function getAvailableLanguages(
|
|
|
374
396
|
const languageUrl = seasonUrl.split('/').map((s, i) => i === 6 ? language : s).join('/');
|
|
375
397
|
try {
|
|
376
398
|
const res = await axios.get(languageUrl, {
|
|
377
|
-
headers:
|
|
399
|
+
headers: headers,
|
|
378
400
|
});
|
|
379
401
|
if (res.status === 200) {
|
|
380
402
|
if (numberEpisodes){
|
|
@@ -400,6 +422,7 @@ export async function getAllAnime(
|
|
|
400
422
|
output = "anime_list.json",
|
|
401
423
|
get_seasons = false
|
|
402
424
|
) {
|
|
425
|
+
const { headers } = getHeaders(CATALOGUE_URL);
|
|
403
426
|
let animeLinks = [];
|
|
404
427
|
|
|
405
428
|
const isWanted = (text, list) =>
|
|
@@ -407,7 +430,7 @@ export async function getAllAnime(
|
|
|
407
430
|
|
|
408
431
|
const fetchPage = async (pageNum) => {
|
|
409
432
|
const url = pageNum === 1 ? CATALOGUE_URL : `${CATALOGUE_URL}?page=${pageNum}`;
|
|
410
|
-
const res = await axios.get(url, { headers:
|
|
433
|
+
const res = await axios.get(url, { headers: headers });
|
|
411
434
|
const $ = cheerio.load(res.data);
|
|
412
435
|
|
|
413
436
|
const containers = $("div.shrink-0.m-3.rounded.border-2");
|
|
@@ -486,7 +509,8 @@ export async function getAllAnime(
|
|
|
486
509
|
|
|
487
510
|
export async function getLatestEpisodes(languageFilter = null) {
|
|
488
511
|
try {
|
|
489
|
-
const
|
|
512
|
+
const { headers } = getHeaders(BASE_URL);
|
|
513
|
+
const res = await axios.get(BASE_URL, { headers: headers });
|
|
490
514
|
const $ = cheerio.load(res.data);
|
|
491
515
|
|
|
492
516
|
const container = $("#containerAjoutsAnimes");
|
|
@@ -498,7 +522,7 @@ export async function getLatestEpisodes(languageFilter = null) {
|
|
|
498
522
|
const cover = $(el).find("img").attr("src");
|
|
499
523
|
|
|
500
524
|
const buttons = $(el).find("button");
|
|
501
|
-
const language = $(buttons[0]).text().trim().toLowerCase();
|
|
525
|
+
const language = $(buttons[0]).text().trim().toLowerCase();
|
|
502
526
|
const episode = $(buttons[1]).text().trim();
|
|
503
527
|
|
|
504
528
|
if (
|
|
@@ -532,10 +556,11 @@ export async function getRandomAnime(
|
|
|
532
556
|
maxAttempts = null,
|
|
533
557
|
attempt = 0
|
|
534
558
|
) {
|
|
559
|
+
const { headers } = getHeaders(CATALOGUE_URL);
|
|
535
560
|
try {
|
|
536
561
|
const res = await axios.get(
|
|
537
562
|
`${CATALOGUE_URL}/?search=&random=1`,
|
|
538
|
-
{ headers:
|
|
563
|
+
{ headers:headers }
|
|
539
564
|
);
|
|
540
565
|
|
|
541
566
|
const $ = cheerio.load(res.data);
|
package/utils/extractVideoUrl.js
CHANGED
|
@@ -53,6 +53,9 @@ export async function getSendvidVideo(embedUrl) {
|
|
|
53
53
|
|
|
54
54
|
export async function getVidmolyOrOneuploadVideo(embedUrl) {
|
|
55
55
|
try {
|
|
56
|
+
if (embedUrl.includes("vidmoly.to/")) {
|
|
57
|
+
embedUrl = embedUrl.replace("vidmoly.to/", "vidmoly.net/");
|
|
58
|
+
}
|
|
56
59
|
console.log(embedUrl)
|
|
57
60
|
const { data } = await axios.get(embedUrl, {
|
|
58
61
|
headers: getHeaders(embedUrl),
|