1 | const cheerio = require('cheerio');
|
2 | const got = require('got');
|
3 | const debug = require('debug')('anime-scraper-html');
|
4 |
|
5 | const BASE_URL = 'https://gogoanime.io';
|
6 |
|
7 |
|
8 | function parseSearchResults($) {
|
9 | const results = $('.items li .name a');
|
10 |
|
11 | return results.map((i, value) => ({
|
12 | name: $(value).text(),
|
13 | url: `${BASE_URL}${$(value).attr('href')}`,
|
14 | })).get();
|
15 | }
|
16 |
|
17 |
|
18 | function parseEpisodeListing($) {
|
19 | const episodes = $('li a');
|
20 |
|
21 | return episodes.map((i, value) => ({
|
22 | name: $(value).find('.name').text().trim(),
|
23 | url: `${BASE_URL}${$(value).attr('href').trim()}`,
|
24 | })).get().reverse();
|
25 | }
|
26 |
|
27 |
|
28 | function parseAnimePage($) {
|
29 | return {
|
30 | id: $('#movie_id').val(),
|
31 | url: `${BASE_URL}${$('[rel="canonical"]').attr('href')}`,
|
32 | name: $('.anime_info_body h1').text(),
|
33 | summary: $('span:contains("Plot Summary")').get(0).nextSibling.data,
|
34 | genres: $("span:contains('Genre')").parent().find('a').map((i, val) => $(val).attr('title'))
|
35 | .get(),
|
36 | released: $("span:contains('Released')").get(0).nextSibling.data
|
37 | };
|
38 | }
|
39 |
|
40 |
|
41 | const VideoProviders = {
|
42 | Vidstreaming(url) {
|
43 | return got(url).then(resp => cheerio.load(resp.body))
|
44 | .then($ =>
|
45 | $('.linkserver').map((i, val) => {
|
46 | val = $(val);
|
47 | var source = val.attr('data-video');
|
48 | var out = {
|
49 | name: val.text(),
|
50 | url: source,
|
51 | type: "iframe"
|
52 | }
|
53 | if (!source && val.hasClass("active")) {
|
54 | $('script').each((i, el) => {
|
55 | var html = $(el).html();
|
56 | var ind = html.indexOf("window.urlVideo = '");
|
57 |
|
58 | if (ind != -1) {
|
59 | ind += "window.urlVideo = '".length;
|
60 | var results = [""];
|
61 | for (; ind < html.length; ind++) {
|
62 | var char = html.charAt(ind);
|
63 | if (char == "'") {
|
64 | break;
|
65 | } else {
|
66 | results.push(char);
|
67 |
|
68 | }
|
69 | }
|
70 | out.url = results.join("");
|
71 | out.type = "source";
|
72 |
|
73 | } else {
|
74 | ind = html.indexOf("playerInstance.setup({");
|
75 | if (ind != -1) {
|
76 |
|
77 | ind += "playerInstance.setup({".length;
|
78 | var curly = 1;
|
79 | var text = false;
|
80 | var results = ["{"];
|
81 | var str = "";
|
82 | for (; ind < html.length; ind++) {
|
83 | var char = html.charAt(ind);
|
84 | results.push(char)
|
85 | if (char == "'") {
|
86 | text = !text
|
87 |
|
88 | } else if (!text && char == "{") {
|
89 | curly++;
|
90 | } else if (!text && char == "}") {
|
91 | curly--;
|
92 | if (curly == 0) break;
|
93 | }
|
94 |
|
95 | }
|
96 | var parsed = results.join("")
|
97 |
|
98 |
|
99 | .replace(/:\s*"([^"]*)"/g, function (match, p1) {
|
100 | return ': "' + p1.replace(/:/g, '@colon@') + '"';
|
101 | })
|
102 |
|
103 |
|
104 | .replace(/:\s*'([^']*)'/g, function (match, p1) {
|
105 | return ': "' + p1.replace(/:/g, '@colon@') + '"';
|
106 | })
|
107 |
|
108 |
|
109 | .replace(/(['"])?([a-z0-9A-Z_]+)(['"])?\s*:/g, '"$2": ')
|
110 |
|
111 |
|
112 | .replace(/@colon@/g, ':')
|
113 | .replace(/(.*?),\s*(\}|])/g, "$1$2");
|
114 |
|
115 | try {
|
116 |
|
117 | parsed = JSON.parse(parsed);
|
118 | } catch (e) {
|
119 |
|
120 | return;
|
121 | }
|
122 | var max = null;
|
123 | parsed.sources.forEach((item) => {
|
124 | if (item.file) {
|
125 | if (!max) max = item;
|
126 | if ((parseInt(item.label) || 0) > (parseInt(max.label) || 0)) {
|
127 | max = item;
|
128 | }
|
129 | }
|
130 | })
|
131 | out.url = max.file;
|
132 | out.type = "source"
|
133 | out.quality = max.label;
|
134 | out.sources = parsed.sources;
|
135 | }
|
136 | }
|
137 | })
|
138 | }
|
139 | return out
|
140 | }).get());
|
141 | },
|
142 | };
|
143 |
|
144 | function parseVideo($) {
|
145 |
|
146 | const vidStreaming = $('[data-video*="//gogo-stream.com/"]').attr('data-video');
|
147 | debug(`Found Vidstreaming link: ${vidStreaming}`);
|
148 |
|
149 | if (vidStreaming != null) {
|
150 | return VideoProviders.Vidstreaming("http:" + vidStreaming);
|
151 | }
|
152 |
|
153 | return null;
|
154 | }
|
155 |
|
156 |
|
157 | module.exports = {
|
158 | parseSearchResults,
|
159 | parseEpisodeListing,
|
160 | parseAnimePage,
|
161 | parseVideo,
|
162 | };
|