better-ani-scraped 1.1.1 → 1.2.1

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 { AnimeScraper, getVideoUrlFromEmbed } from "../index.js"; // REPLACE BY
3
3
  const main = async () => {
4
4
  const scraper = new AnimeScraper('animesama');
5
5
 
6
- const search = await scraper.searchAnime("frieren");
6
+ const search = await scraper.searchAnime("86");
7
7
  console.log("Search Results:", search);
8
8
 
9
9
  const animeUrl = Object.values(search)[0].url;
@@ -16,7 +16,7 @@ const main = async () => {
16
16
  ]);
17
17
  console.log("Embed Links:", embeds);
18
18
 
19
- const videoUrl = await getVideoUrlFromEmbed("sibnet", embeds[11].url)
19
+ const videoUrl = await getVideoUrlFromEmbed("sibnet", embeds[0].url)
20
20
  console.log("Video URL:", videoUrl);
21
21
  };
22
22
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-ani-scraped",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "description": "Scrape anime data from different sources (only anime-sama.fr for the moment)",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -125,37 +125,56 @@ export async function getSeasons(animeUrl, language = "vostfr") {
125
125
  }
126
126
 
127
127
  export async function getEpisodeTitles(animeUrl) {
128
- let browser;
128
+ const puppeteer = await import('puppeteer');
129
+ let browser;
130
+
131
+ try {
132
+ browser = await puppeteer.launch({
133
+ headless: true,
134
+ args: ['--no-sandbox', '--disable-setuid-sandbox']
135
+ });
136
+
137
+ const page = await browser.newPage();
138
+
139
+ await page.setUserAgent(
140
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
141
+ );
142
+
143
+ await page.setRequestInterception(true);
144
+ page.on('request', (req) => {
145
+ const blocked = ['image', 'stylesheet', 'font', 'media'];
146
+ if (blocked.includes(req.resourceType())) req.abort();
147
+ else req.continue();
148
+ });
149
+
150
+ console.log("▶️ Navigation vers", animeUrl);
151
+ await page.goto(animeUrl, { waitUntil: 'domcontentloaded', timeout: 20000 });
152
+
129
153
  try {
130
- browser = await puppeteer.launch({
131
- headless: true,
132
- args: ['--no-sandbox', '--disable-setuid-sandbox']
133
- });
134
- const page = await browser.newPage();
135
- await page.setRequestInterception(true);
136
- page.on('request', (req) => {
137
- const blocked = ['image', 'stylesheet', 'font', 'media'];
138
- if (blocked.includes(req.resourceType())) {
139
- req.abort();
140
- } else {
141
- req.continue();
142
- }
143
- });
144
- await page.goto(animeUrl, { waitUntil: 'domcontentloaded' });
145
- await page.waitForSelector('#selectEpisodes');
146
- // Récupération des titres d'épisodes
147
- const titres = await page.$$eval('#selectEpisodes option', options =>
148
- options.map(o => o.textContent.trim())
149
- );
150
- return titres;
151
- } catch (error) {
152
- console.error('Erreur dans la récupération des titres:', error);
153
- return [];
154
- } finally {
155
- if (browser) await browser.close();
154
+ await page.waitForSelector('#selectEpisodes', { timeout: 7000 });
155
+ } catch (waitError) {
156
+ console.warn("⚠️ Sélecteur #selectEpisodes introuvable :", waitError.message);
157
+
158
+ const htmlDump = await page.content();
159
+ require("fs").writeFileSync("debug_selectEpisodes.html", htmlDump);
160
+ return [];
156
161
  }
162
+
163
+ const titres = await page.$$eval('#selectEpisodes option', options =>
164
+ options.map(o => o.textContent.trim())
165
+ );
166
+
167
+ console.log(`✅ ${titres.length} titres récupérés`);
168
+ return titres;
169
+ } catch (error) {
170
+ console.error('❌ Erreur dans getEpisodeTitles:', error.message);
171
+ return [];
172
+ } finally {
173
+ if (browser) await browser.close();
174
+ }
157
175
  }
158
176
 
177
+
159
178
  export async function getEmbed(animeUrl, hostPriority = ["vidmoly"]) {
160
179
  const res = await axios.get(animeUrl, {
161
180
  headers: getHeaders(animeUrl.split("/").slice(0, 5).join("/")),
@@ -178,34 +197,45 @@ export async function getEmbed(animeUrl, hostPriority = ["vidmoly"]) {
178
197
  ];
179
198
  if (!matches.length) throw new Error("No episode arrays found");
180
199
 
181
- let allEmbeds = [];
182
-
200
+ // Parse les arrays et crée une matrice [epsX][index]
201
+ let episodeMatrix = [];
183
202
  for (const [, , arrayString] of matches) {
184
203
  try {
185
- const links = eval(arrayString);
186
- allEmbeds.push(...links);
204
+ const links = eval(arrayString);
205
+ episodeMatrix.push(links);
187
206
  } catch (e) {
188
207
  console.warn("Could not parse embed array:", e);
189
208
  }
190
209
  }
191
- for (const host of hostPriority) {
192
- const filtered = allEmbeds.filter((url) => url.includes(host));
193
- if (filtered.length) {
194
- const titles = await getEpisodeTitles(animeUrl);
195
- return titles.slice(0, filtered.length).map((title, i) => ({
196
- title,
197
- url: filtered[i]
198
- }));
210
+
211
+ // Déterminer le nombre total d'épisodes max (plus long des arrays)
212
+ const maxEpisodes = Math.max(...episodeMatrix.map(arr => arr.length));
213
+ const finalEmbeds = [];
214
+
215
+ // Parcours vertical
216
+ for (let i = 0; i < maxEpisodes; i++) {
217
+ let selectedUrl = null;
218
+
219
+ for (const host of hostPriority) {
220
+ for (const arr of episodeMatrix) {
221
+ if (i < arr.length && arr[i].includes(host)) {
222
+ selectedUrl = arr[i];
223
+ break;
224
+ }
225
+ }
226
+ if (selectedUrl) break;
199
227
  }
228
+
229
+ finalEmbeds.push(selectedUrl || null);
200
230
  }
231
+
201
232
  const titles = await getEpisodeTitles(animeUrl);
202
- return titles.slice(0, allEmbeds.length).map((title, i) => ({
233
+ return titles.slice(0, finalEmbeds.length).map((title, i) => ({
203
234
  title,
204
- url: allEmbeds[i]
235
+ url: finalEmbeds[i]
205
236
  }));
206
237
  }
207
238
 
208
-
209
239
  export async function getAnimeInfo(animeUrl) {
210
240
  const res = await axios.get(animeUrl, { headers: getHeaders(CATALOGUE_URL) });
211
241
  const $ = cheerio.load(res.data);