stack-analyze 1.3.5 → 1.3.7
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.
- package/CHANGELOG.md +335 -311
- package/LICENSE +21 -21
- package/about.js +98 -121
- package/api/pokerApi.js +5 -5
- package/api/wallpapersURL.js +7 -5
- package/api/webApis.js +21 -21
- package/cli.js +204 -213
- package/eslint.config.js +44 -44
- package/functions/animeInfo.js +45 -45
- package/functions/bitly.js +41 -41
- package/functions/bundlephobia.js +36 -36
- package/functions/cryptoList.js +48 -48
- package/functions/cssValidator.js +25 -25
- package/functions/deezer.js +37 -37
- package/functions/download.js +25 -24
- package/functions/gitUser.js +37 -37
- package/functions/hardware.js +109 -109
- package/functions/moviesInfo.js +55 -55
- package/functions/multipleStack.js +53 -53
- package/functions/pageSpeed.js +82 -82
- package/functions/password.js +24 -24
- package/functions/pokemon.js +106 -106
- package/functions/poker.js +40 -42
- package/functions/potterSearch.js +32 -32
- package/functions/quotes.js +33 -0
- package/functions/scraping.js +132 -132
- package/functions/singleStack.js +48 -48
- package/functions/twitch.js +72 -72
- package/hash/infoTools.js +61 -61
- package/hash/queryTools.js +113 -116
- package/hash/quotesSelect.js +16 -0
- package/hash/utilityTools.js +33 -32
- package/hash/wallpaperSelect.js +90 -59
- package/hash/webTools.js +93 -92
- package/logo-module.webp +0 -0
- package/menu.js +13 -13
- package/package.json +67 -67
- package/prompts/webPrompts.js +31 -31
- package/readme.md +44 -44
- package/types.js +51 -0
- package/utils.js +96 -101
- package/validations/infoValidations.js +37 -37
- package/validations/webValidations.js +33 -33
package/functions/pokemon.js
CHANGED
|
@@ -1,106 +1,106 @@
|
|
|
1
|
-
// colors
|
|
2
|
-
import colors from "colors";
|
|
3
|
-
import boxen from "boxen";
|
|
4
|
-
import CliProgress from "cli-progress";
|
|
5
|
-
|
|
6
|
-
// utils
|
|
7
|
-
import { listFormat, stackSave } from "../utils.js";
|
|
8
|
-
|
|
9
|
-
const pokeStats = {
|
|
10
|
-
hp: 255,
|
|
11
|
-
attack: 194,
|
|
12
|
-
defense: 230,
|
|
13
|
-
"special-attack": 180,
|
|
14
|
-
"special-defense": 230,
|
|
15
|
-
speed: 200,
|
|
16
|
-
xp: 635
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @param {string}
|
|
21
|
-
* @returns {string}
|
|
22
|
-
*/
|
|
23
|
-
const barColor = stat => {
|
|
24
|
-
switch(stat) {
|
|
25
|
-
case "hp":
|
|
26
|
-
return "{bar}".red;
|
|
27
|
-
case "attack":
|
|
28
|
-
return "{bar}".yellow;
|
|
29
|
-
case "defense":
|
|
30
|
-
return "{bar}".brightYellow;
|
|
31
|
-
case "special-attack":
|
|
32
|
-
return "{bar}".blue;
|
|
33
|
-
case "special-defense":
|
|
34
|
-
return "{bar}".green;
|
|
35
|
-
case "speed":
|
|
36
|
-
return "{bar}".magenta;
|
|
37
|
-
default:
|
|
38
|
-
return "{bar}".cyan;
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @async
|
|
44
|
-
* @param {number | string} pokemon
|
|
45
|
-
* @returns {Promise<void>}
|
|
46
|
-
*/
|
|
47
|
-
export default async function pokemonInfo(pokemon) {
|
|
48
|
-
console.clear();
|
|
49
|
-
|
|
50
|
-
const multibar = new CliProgress.MultiBar({
|
|
51
|
-
format: "{stats} | {bar} | {value}/{total}",
|
|
52
|
-
clearOnComplete: false,
|
|
53
|
-
stopOnComplete: true,
|
|
54
|
-
hideCursor: true,
|
|
55
|
-
forceRedraw: true,
|
|
56
|
-
}, CliProgress.Presets.shades_grey);
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
const data = await (
|
|
60
|
-
await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemon}`)
|
|
61
|
-
).json();
|
|
62
|
-
|
|
63
|
-
const {
|
|
64
|
-
id,
|
|
65
|
-
name,
|
|
66
|
-
height,
|
|
67
|
-
base_experience,
|
|
68
|
-
weight,
|
|
69
|
-
stats,
|
|
70
|
-
types
|
|
71
|
-
} = data;
|
|
72
|
-
|
|
73
|
-
const info = {
|
|
74
|
-
id,
|
|
75
|
-
name,
|
|
76
|
-
height,
|
|
77
|
-
base_experience,
|
|
78
|
-
weight,
|
|
79
|
-
types: listFormat.format(types.map(({ type }) => type.name)),
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const PokeInfo = boxen(info.types, {title: `${id} - ${name}`});
|
|
83
|
-
|
|
84
|
-
multibar.create(pokeStats.xp, 0, { stats: "xp" }, {
|
|
85
|
-
format: `{stats} | ${barColor("xp")} | {value}/{total}`,
|
|
86
|
-
}).update(base_experience);
|
|
87
|
-
|
|
88
|
-
stats.forEach(({base_stat, stat}) => {
|
|
89
|
-
multibar.create(pokeStats[stat.name], 0, { stats: stat.name }, {
|
|
90
|
-
format: `{stats} | ${barColor(stat.name)} | {value}/{total}`,
|
|
91
|
-
}).update(base_stat);
|
|
92
|
-
|
|
93
|
-
info[stat.name] = base_stat;
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
multibar.log(`${PokeInfo}\n`);
|
|
97
|
-
|
|
98
|
-
setTimeout(() => {
|
|
99
|
-
multibar.stop();
|
|
100
|
-
}, 3000);
|
|
101
|
-
|
|
102
|
-
stackSave("poke-info.json", JSON.stringify(info, null, 2));
|
|
103
|
-
} catch(err) {
|
|
104
|
-
console.info(colors.red(err.message));
|
|
105
|
-
}
|
|
106
|
-
}
|
|
1
|
+
// colors
|
|
2
|
+
import colors from "colors";
|
|
3
|
+
import boxen from "boxen";
|
|
4
|
+
import CliProgress from "cli-progress";
|
|
5
|
+
|
|
6
|
+
// utils
|
|
7
|
+
import { listFormat, stackSave } from "../utils.js";
|
|
8
|
+
|
|
9
|
+
const pokeStats = {
|
|
10
|
+
hp: 255,
|
|
11
|
+
attack: 194,
|
|
12
|
+
defense: 230,
|
|
13
|
+
"special-attack": 180,
|
|
14
|
+
"special-defense": 230,
|
|
15
|
+
speed: 200,
|
|
16
|
+
xp: 635
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string}
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
const barColor = stat => {
|
|
24
|
+
switch(stat) {
|
|
25
|
+
case "hp":
|
|
26
|
+
return "{bar}".red;
|
|
27
|
+
case "attack":
|
|
28
|
+
return "{bar}".yellow;
|
|
29
|
+
case "defense":
|
|
30
|
+
return "{bar}".brightYellow;
|
|
31
|
+
case "special-attack":
|
|
32
|
+
return "{bar}".blue;
|
|
33
|
+
case "special-defense":
|
|
34
|
+
return "{bar}".green;
|
|
35
|
+
case "speed":
|
|
36
|
+
return "{bar}".magenta;
|
|
37
|
+
default:
|
|
38
|
+
return "{bar}".cyan;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @async
|
|
44
|
+
* @param {number | string} pokemon
|
|
45
|
+
* @returns {Promise<void>}
|
|
46
|
+
*/
|
|
47
|
+
export default async function pokemonInfo(pokemon) {
|
|
48
|
+
console.clear();
|
|
49
|
+
|
|
50
|
+
const multibar = new CliProgress.MultiBar({
|
|
51
|
+
format: "{stats} | {bar} | {value}/{total}",
|
|
52
|
+
clearOnComplete: false,
|
|
53
|
+
stopOnComplete: true,
|
|
54
|
+
hideCursor: true,
|
|
55
|
+
forceRedraw: true,
|
|
56
|
+
}, CliProgress.Presets.shades_grey);
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const data = await (
|
|
60
|
+
await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemon}`)
|
|
61
|
+
).json();
|
|
62
|
+
|
|
63
|
+
const {
|
|
64
|
+
id,
|
|
65
|
+
name,
|
|
66
|
+
height,
|
|
67
|
+
base_experience,
|
|
68
|
+
weight,
|
|
69
|
+
stats,
|
|
70
|
+
types
|
|
71
|
+
} = data;
|
|
72
|
+
|
|
73
|
+
const info = {
|
|
74
|
+
id,
|
|
75
|
+
name,
|
|
76
|
+
height,
|
|
77
|
+
base_experience,
|
|
78
|
+
weight,
|
|
79
|
+
types: listFormat.format(types.map(({ type }) => type.name)),
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const PokeInfo = boxen(info.types, {title: `${id} - ${name}`});
|
|
83
|
+
|
|
84
|
+
multibar.create(pokeStats.xp, 0, { stats: "xp" }, {
|
|
85
|
+
format: `{stats} | ${barColor("xp")} | {value}/{total}`,
|
|
86
|
+
}).update(base_experience);
|
|
87
|
+
|
|
88
|
+
stats.forEach(({base_stat, stat}) => {
|
|
89
|
+
multibar.create(pokeStats[stat.name], 0, { stats: stat.name }, {
|
|
90
|
+
format: `{stats} | ${barColor(stat.name)} | {value}/{total}`,
|
|
91
|
+
}).update(base_stat);
|
|
92
|
+
|
|
93
|
+
info[stat.name] = base_stat;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
multibar.log(`${PokeInfo}\n`);
|
|
97
|
+
|
|
98
|
+
setTimeout(() => {
|
|
99
|
+
multibar.stop();
|
|
100
|
+
}, 3000);
|
|
101
|
+
|
|
102
|
+
stackSave("poke-info.json", JSON.stringify(info, null, 2));
|
|
103
|
+
} catch(err) {
|
|
104
|
+
console.info(colors.red(err.message));
|
|
105
|
+
}
|
|
106
|
+
}
|
package/functions/poker.js
CHANGED
|
@@ -1,42 +1,40 @@
|
|
|
1
|
-
import { load } from "cheerio";
|
|
2
|
-
import colors from "colors";
|
|
3
|
-
|
|
4
|
-
import { pokerApi } from "../api/pokerApi.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* @
|
|
9
|
-
* @
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
console.
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
}
|
|
42
|
-
}
|
|
1
|
+
import { load } from "cheerio";
|
|
2
|
+
import colors from "colors";
|
|
3
|
+
|
|
4
|
+
import { pokerApi } from "../api/pokerApi.js";
|
|
5
|
+
import { stackSave } from "../utils.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {"go-fish"|"gin-rummy"|"blackjack"|"slapjack"|"basics-of-poker"|"texas-holdem-poker"} Options
|
|
9
|
+
* @params {Options} game
|
|
10
|
+
* @returns {Promise<void>}
|
|
11
|
+
*/
|
|
12
|
+
export default async function pokerGame(game) {
|
|
13
|
+
try {
|
|
14
|
+
const { data } = await pokerApi.get(game);
|
|
15
|
+
|
|
16
|
+
// extract rules
|
|
17
|
+
const $ = load(data);
|
|
18
|
+
|
|
19
|
+
const title = $("title").text();
|
|
20
|
+
|
|
21
|
+
const [age, players] = $(".border-brand-blue-pale div:not(.text-brand-blue)").map(
|
|
22
|
+
(i, el) => $(el).text()
|
|
23
|
+
).get().slice(1);
|
|
24
|
+
|
|
25
|
+
const howPLay = $("h3.text-2xl+p.mb-5").map(
|
|
26
|
+
(i, el) => $(el).text()
|
|
27
|
+
).get().slice(0, 5);
|
|
28
|
+
|
|
29
|
+
// poker game
|
|
30
|
+
const pokerGame = { title, age, players, howPLay };
|
|
31
|
+
const pokerTable = { ...pokerGame };
|
|
32
|
+
delete pokerTable.howPLay;
|
|
33
|
+
console.table(pokerTable);
|
|
34
|
+
|
|
35
|
+
stackSave(`${title}.json`, JSON.stringify(pokerGame, null, 2));
|
|
36
|
+
console.info("poker rule file is created".green);
|
|
37
|
+
} catch(err) {
|
|
38
|
+
console.info(colors.red(err.message));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import colors from "colors";
|
|
3
|
-
import { printTable } from "console-table-printer";
|
|
4
|
-
|
|
5
|
-
// save search
|
|
6
|
-
import { stackSave } from "../utils.js";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @description search harry potter characters using keyword or name
|
|
10
|
-
* @async
|
|
11
|
-
* @param { string } search - get results of harry potter characters
|
|
12
|
-
* @returns { Promise<void>}
|
|
13
|
-
*/
|
|
14
|
-
export default async function potterSearch(search) {
|
|
15
|
-
try {
|
|
16
|
-
const { data } = await axios.get("https://potterapi-fedeperin.vercel.app/en/characters", {
|
|
17
|
-
params: { search }
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
const characterList = data.map(({
|
|
21
|
-
nickname, fullName, hogwartsHouse, birthdate
|
|
22
|
-
}) => ({
|
|
23
|
-
nickname, fullName, birthdate,
|
|
24
|
-
house: hogwartsHouse,
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
printTable(characterList);
|
|
28
|
-
stackSave("potter-results.json", JSON.stringify(characterList, null, 2));
|
|
29
|
-
} catch(err) {
|
|
30
|
-
console.error(colors.red(err.message));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import colors from "colors";
|
|
3
|
+
import { printTable } from "console-table-printer";
|
|
4
|
+
|
|
5
|
+
// save search
|
|
6
|
+
import { stackSave } from "../utils.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @description search harry potter characters using keyword or name
|
|
10
|
+
* @async
|
|
11
|
+
* @param { string } search - get results of harry potter characters
|
|
12
|
+
* @returns { Promise<void>}
|
|
13
|
+
*/
|
|
14
|
+
export default async function potterSearch(search) {
|
|
15
|
+
try {
|
|
16
|
+
const { data } = await axios.get("https://potterapi-fedeperin.vercel.app/en/characters", {
|
|
17
|
+
params: { search }
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const characterList = data.map(({
|
|
21
|
+
nickname, fullName, hogwartsHouse, birthdate
|
|
22
|
+
}) => ({
|
|
23
|
+
nickname, fullName, birthdate,
|
|
24
|
+
house: hogwartsHouse,
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
printTable(characterList);
|
|
28
|
+
stackSave("potter-results.json", JSON.stringify(characterList, null, 2));
|
|
29
|
+
} catch(err) {
|
|
30
|
+
console.error(colors.red(err.message));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import axios from "axios";
|
|
2
|
+
import colors from "colors";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @description get random quote from anime characters.
|
|
6
|
+
* @async
|
|
7
|
+
* @param {string} anime
|
|
8
|
+
* @returns {Promise<void>}
|
|
9
|
+
*/
|
|
10
|
+
async function getAnimeQuote(anime) {
|
|
11
|
+
try {
|
|
12
|
+
/** @type {import('axios').AxiosResponse<import('../types.js').AnimeQuoute>} */
|
|
13
|
+
const { data } = await axios.get("https://api.animechan.io/v1/quotes/random", {
|
|
14
|
+
params: { anime }
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
content,
|
|
19
|
+
anime: { altName: animeAltName, name: animeName },
|
|
20
|
+
character: { name: characterName }
|
|
21
|
+
} = data.data;
|
|
22
|
+
|
|
23
|
+
console.info({
|
|
24
|
+
content, animeAltName, animeName, characterName
|
|
25
|
+
});
|
|
26
|
+
} catch (err) {
|
|
27
|
+
console.error(colors.red(/** @type {import('axios').AxiosError} */(err).message));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export {
|
|
32
|
+
getAnimeQuote
|
|
33
|
+
};
|
package/functions/scraping.js
CHANGED
|
@@ -1,132 +1,132 @@
|
|
|
1
|
-
import { load } from "cheerio";
|
|
2
|
-
import colors from "colors";
|
|
3
|
-
import { printTable } from "console-table-printer";
|
|
4
|
-
|
|
5
|
-
// stack save
|
|
6
|
-
import { stackSave } from "../utils.js";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {"title"|"images"|"metadata"|"headings"|"table_heading"|"table_data"|"links"|"cites"} Options
|
|
10
|
-
*
|
|
11
|
-
* It takes a URL and an option as arguments, and then it scrapes the page at the URL for the option
|
|
12
|
-
* @param {string} url
|
|
13
|
-
* @param {Options} options
|
|
14
|
-
* @returns {Promise<void>}
|
|
15
|
-
*/
|
|
16
|
-
export default async function scrape(url, options) {
|
|
17
|
-
try {
|
|
18
|
-
const data = await (await fetch(url)).text();
|
|
19
|
-
const $ = load(data);
|
|
20
|
-
|
|
21
|
-
let result;
|
|
22
|
-
|
|
23
|
-
const scraping = {
|
|
24
|
-
title() {
|
|
25
|
-
result = `url title: ${$("title").text()}`;
|
|
26
|
-
console.info($("title").text());
|
|
27
|
-
},
|
|
28
|
-
images() {
|
|
29
|
-
const imageList = $("img").map((i, el) => ({
|
|
30
|
-
imagePath: $(el).attr("src"),
|
|
31
|
-
imageTitle: $(el).attr("alt")
|
|
32
|
-
})).toArray();
|
|
33
|
-
|
|
34
|
-
result = imageList.length === 0
|
|
35
|
-
? "no found images"
|
|
36
|
-
: imageList;
|
|
37
|
-
|
|
38
|
-
typeof result === "string"
|
|
39
|
-
? console.info(result)
|
|
40
|
-
: printTable(result);
|
|
41
|
-
},
|
|
42
|
-
metadata() {
|
|
43
|
-
const metadataList = $("meta").map((i, el) => ({
|
|
44
|
-
metaInfo: $(el).attr("name"),
|
|
45
|
-
metaContent: $(el).attr("content")
|
|
46
|
-
})).toArray()
|
|
47
|
-
.filter((data) => data?.metaInfo);
|
|
48
|
-
|
|
49
|
-
result = metadataList;
|
|
50
|
-
|
|
51
|
-
printTable(metadataList);
|
|
52
|
-
},
|
|
53
|
-
headings() {
|
|
54
|
-
const headingList = $("h1, h2, h3, h4, h5, h6").map((i, el) => ({
|
|
55
|
-
headingTag: $(el).prop("tagName"),
|
|
56
|
-
headingText: $(el).text()
|
|
57
|
-
})).toArray();
|
|
58
|
-
|
|
59
|
-
result = headingList.length === 0
|
|
60
|
-
? "no found heading tags"
|
|
61
|
-
: headingList;
|
|
62
|
-
|
|
63
|
-
typeof result === "string"
|
|
64
|
-
? console.info("no found heading tags")
|
|
65
|
-
:printTable(headingList);
|
|
66
|
-
},
|
|
67
|
-
tableHead() {
|
|
68
|
-
const tableHeadList = $("th").map((i, el) => ({
|
|
69
|
-
thCol: $(el).index(),
|
|
70
|
-
thData: $(el).text()
|
|
71
|
-
})).toArray();
|
|
72
|
-
|
|
73
|
-
result = tableHeadList.length === 0
|
|
74
|
-
? "no found th tags"
|
|
75
|
-
: tableHeadList;
|
|
76
|
-
|
|
77
|
-
typeof result === "string"
|
|
78
|
-
? console.info("no found th tags")
|
|
79
|
-
: printTable(tableHeadList);
|
|
80
|
-
},
|
|
81
|
-
tableData() {
|
|
82
|
-
const tableColumnList = $("td").map((i, el) => ({
|
|
83
|
-
rowID: $(el).parent().index(),
|
|
84
|
-
colID: $(el).index(),
|
|
85
|
-
colData: $(el).text(),
|
|
86
|
-
})).toArray();
|
|
87
|
-
|
|
88
|
-
result = tableColumnList.length === 0
|
|
89
|
-
? "no found td tags"
|
|
90
|
-
: tableColumnList;
|
|
91
|
-
|
|
92
|
-
typeof result === "string"
|
|
93
|
-
? console.info(result)
|
|
94
|
-
: console.table(result.slice(0, 10));
|
|
95
|
-
},
|
|
96
|
-
links() {
|
|
97
|
-
const linkList = $("a").map((i, el) => ({
|
|
98
|
-
url: $(el).attr("href"),
|
|
99
|
-
text: $(el).text()
|
|
100
|
-
})).toArray()
|
|
101
|
-
.filter(({ url }) => url.indexOf("#") !== 0);
|
|
102
|
-
|
|
103
|
-
result = linkList;
|
|
104
|
-
|
|
105
|
-
printTable(linkList);
|
|
106
|
-
},
|
|
107
|
-
cites() {
|
|
108
|
-
const citeList = $("q, blockquote").map((i, el) => ({
|
|
109
|
-
citeTag: $(el).prop("tagName"),
|
|
110
|
-
citeLink: $(el).attr("cite"),
|
|
111
|
-
citeText: $(el).text()
|
|
112
|
-
})).toArray();
|
|
113
|
-
|
|
114
|
-
result = citeList.length === 0
|
|
115
|
-
? "no found q and/or blockquote tags"
|
|
116
|
-
: citeList;
|
|
117
|
-
|
|
118
|
-
typeof result === "string"
|
|
119
|
-
? console.info("no found q and/or blockquote tags")
|
|
120
|
-
: printTable(citeList);
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
scraping[options]();
|
|
125
|
-
|
|
126
|
-
typeof result === "string"
|
|
127
|
-
? stackSave("scraping.txt", result)
|
|
128
|
-
: stackSave("scraping.json", JSON.stringify(result, null, 2));
|
|
129
|
-
} catch (err) {
|
|
130
|
-
console.error(colors.red(err.message));
|
|
131
|
-
}
|
|
132
|
-
}
|
|
1
|
+
import { load } from "cheerio";
|
|
2
|
+
import colors from "colors";
|
|
3
|
+
import { printTable } from "console-table-printer";
|
|
4
|
+
|
|
5
|
+
// stack save
|
|
6
|
+
import { stackSave } from "../utils.js";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {"title"|"images"|"metadata"|"headings"|"table_heading"|"table_data"|"links"|"cites"} Options
|
|
10
|
+
*
|
|
11
|
+
* It takes a URL and an option as arguments, and then it scrapes the page at the URL for the option
|
|
12
|
+
* @param {string} url
|
|
13
|
+
* @param {Options} options
|
|
14
|
+
* @returns {Promise<void>}
|
|
15
|
+
*/
|
|
16
|
+
export default async function scrape(url, options) {
|
|
17
|
+
try {
|
|
18
|
+
const data = await (await fetch(url)).text();
|
|
19
|
+
const $ = load(data);
|
|
20
|
+
|
|
21
|
+
let result;
|
|
22
|
+
|
|
23
|
+
const scraping = {
|
|
24
|
+
title() {
|
|
25
|
+
result = `url title: ${$("title").text()}`;
|
|
26
|
+
console.info($("title").text());
|
|
27
|
+
},
|
|
28
|
+
images() {
|
|
29
|
+
const imageList = $("img").map((i, el) => ({
|
|
30
|
+
imagePath: $(el).attr("src"),
|
|
31
|
+
imageTitle: $(el).attr("alt")
|
|
32
|
+
})).toArray();
|
|
33
|
+
|
|
34
|
+
result = imageList.length === 0
|
|
35
|
+
? "no found images"
|
|
36
|
+
: imageList;
|
|
37
|
+
|
|
38
|
+
typeof result === "string"
|
|
39
|
+
? console.info(result)
|
|
40
|
+
: printTable(result);
|
|
41
|
+
},
|
|
42
|
+
metadata() {
|
|
43
|
+
const metadataList = $("meta").map((i, el) => ({
|
|
44
|
+
metaInfo: $(el).attr("name"),
|
|
45
|
+
metaContent: $(el).attr("content")
|
|
46
|
+
})).toArray()
|
|
47
|
+
.filter((data) => data?.metaInfo);
|
|
48
|
+
|
|
49
|
+
result = metadataList;
|
|
50
|
+
|
|
51
|
+
printTable(metadataList);
|
|
52
|
+
},
|
|
53
|
+
headings() {
|
|
54
|
+
const headingList = $("h1, h2, h3, h4, h5, h6").map((i, el) => ({
|
|
55
|
+
headingTag: $(el).prop("tagName"),
|
|
56
|
+
headingText: $(el).text()
|
|
57
|
+
})).toArray();
|
|
58
|
+
|
|
59
|
+
result = headingList.length === 0
|
|
60
|
+
? "no found heading tags"
|
|
61
|
+
: headingList;
|
|
62
|
+
|
|
63
|
+
typeof result === "string"
|
|
64
|
+
? console.info("no found heading tags")
|
|
65
|
+
:printTable(headingList);
|
|
66
|
+
},
|
|
67
|
+
tableHead() {
|
|
68
|
+
const tableHeadList = $("th").map((i, el) => ({
|
|
69
|
+
thCol: $(el).index(),
|
|
70
|
+
thData: $(el).text()
|
|
71
|
+
})).toArray();
|
|
72
|
+
|
|
73
|
+
result = tableHeadList.length === 0
|
|
74
|
+
? "no found th tags"
|
|
75
|
+
: tableHeadList;
|
|
76
|
+
|
|
77
|
+
typeof result === "string"
|
|
78
|
+
? console.info("no found th tags")
|
|
79
|
+
: printTable(tableHeadList);
|
|
80
|
+
},
|
|
81
|
+
tableData() {
|
|
82
|
+
const tableColumnList = $("td").map((i, el) => ({
|
|
83
|
+
rowID: $(el).parent().index(),
|
|
84
|
+
colID: $(el).index(),
|
|
85
|
+
colData: $(el).text(),
|
|
86
|
+
})).toArray();
|
|
87
|
+
|
|
88
|
+
result = tableColumnList.length === 0
|
|
89
|
+
? "no found td tags"
|
|
90
|
+
: tableColumnList;
|
|
91
|
+
|
|
92
|
+
typeof result === "string"
|
|
93
|
+
? console.info(result)
|
|
94
|
+
: console.table(result.slice(0, 10));
|
|
95
|
+
},
|
|
96
|
+
links() {
|
|
97
|
+
const linkList = $("a").map((i, el) => ({
|
|
98
|
+
url: $(el).attr("href"),
|
|
99
|
+
text: $(el).text()
|
|
100
|
+
})).toArray()
|
|
101
|
+
.filter(({ url }) => url.indexOf("#") !== 0);
|
|
102
|
+
|
|
103
|
+
result = linkList;
|
|
104
|
+
|
|
105
|
+
printTable(linkList);
|
|
106
|
+
},
|
|
107
|
+
cites() {
|
|
108
|
+
const citeList = $("q, blockquote").map((i, el) => ({
|
|
109
|
+
citeTag: $(el).prop("tagName"),
|
|
110
|
+
citeLink: $(el).attr("cite"),
|
|
111
|
+
citeText: $(el).text()
|
|
112
|
+
})).toArray();
|
|
113
|
+
|
|
114
|
+
result = citeList.length === 0
|
|
115
|
+
? "no found q and/or blockquote tags"
|
|
116
|
+
: citeList;
|
|
117
|
+
|
|
118
|
+
typeof result === "string"
|
|
119
|
+
? console.info("no found q and/or blockquote tags")
|
|
120
|
+
: printTable(citeList);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
scraping[options]();
|
|
125
|
+
|
|
126
|
+
typeof result === "string"
|
|
127
|
+
? stackSave("scraping.txt", result)
|
|
128
|
+
: stackSave("scraping.json", JSON.stringify(result, null, 2));
|
|
129
|
+
} catch (err) {
|
|
130
|
+
console.error(colors.red(err.message));
|
|
131
|
+
}
|
|
132
|
+
}
|