From b873cc2430b5c007434cf046cfef4d3af45ecd19 Mon Sep 17 00:00:00 2001 From: npmrun <154946975@qq.com> Date: Thu, 4 Jun 2026 00:19:31 +0800 Subject: [PATCH] init --- .gitignore | 175 ++++++++++++++++++++++++++++++++++++++++++++++ README.md | 15 ++++ backup-file/index copy.ts | 53 ++++++++++++++ backup-file/index.ts | 111 +++++++++++++++++++++++++++++ bun.lockb | Bin 0 -> 12104 bytes package.json | 15 ++++ tsconfig.json | 27 +++++++ wallhaven/index.ts | 64 +++++++++++++++++ zzzmh/index.ts | 54 ++++++++++++++ 9 files changed, 514 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 backup-file/index copy.ts create mode 100644 backup-file/index.ts create mode 100755 bun.lockb create mode 100644 package.json create mode 100644 tsconfig.json create mode 100644 wallhaven/index.ts create mode 100644 zzzmh/index.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b1ee42 --- /dev/null +++ b/.gitignore @@ -0,0 +1,175 @@ +# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore + +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Caches + +.cache + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# IntelliJ based IDEs +.idea + +# Finder (MacOS) folder config +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..64886e3 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# pic + +To install dependencies: + +```bash +bun install +``` + +To run: + +```bash +bun run index.ts +``` + +This project was created using `bun init` in bun v1.1.18. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/backup-file/index copy.ts b/backup-file/index copy.ts new file mode 100644 index 0000000..01e5aa5 --- /dev/null +++ b/backup-file/index copy.ts @@ -0,0 +1,53 @@ +import { IncomingMessage } from "http" +import { fetch } from "bun" +import https from "https" +import fs from "fs" + +const maxNum = 3 +function request(opts: any, cb: any, num = 0) { + https.get(opts, function (res: IncomingMessage) { + if (res.statusCode === 302) { + if (num > maxNum) { + console.error("重定向次数超过三次,已强制终止"); + return + } + let url = new URL(res.headers['location']!) + if (url) { + console.log(`重定向:`, url.href); + num++ + // 重定向 + request({ + ...opts, + hostname: url.hostname, + path: url.pathname + url.search, + }, cb, num) + } + } else if (res.statusCode === 200) { + cb && cb(res) + } else { + console.log(`当前${opts.hostname}请求${opts.path}未成功`, res.statusCode); + // res.on('data', (d) => { + // process.stdout.write(d); + // }); + } + }) +} + +// 会重定向,需要想重定向请求 +request({ + hostname: "api.zzzmh.cn", + path: "/v2/bz/v3/getUrl/1b87e2c5880511ebb6edd017c2d2eca211", + headers: { + 'Accept': '*/*', + 'Accept-Encoding': 'gzip, deflate', + // "User-Agent": getRandomUserAgent(), + // 'Connection': 'keep-alive', + 'Referer': 'https://bz.zzzmh.cn/' + } +}, function (res: IncomingMessage) { + const write = fs.createWriteStream("./a.jpg") + res.pipe(write) + write.on("error", function (err) { + console.log(err) + }) +}) diff --git a/backup-file/index.ts b/backup-file/index.ts new file mode 100644 index 0000000..70c8248 --- /dev/null +++ b/backup-file/index.ts @@ -0,0 +1,111 @@ +import { fetch } from "bun" +import fs from "node:fs" +import * as cheerio from "cheerio" + +// https://bz.zzzmh.cn/index + +// const stream = await (await fetch("https://api.zzzmh.cn/v2/bz/v3/getUrl/1b87e2c5880511ebb6edd017c2d2eca211")).arrayBuffer() +// const stream = await (await fetch("https://api.zzzmh.cn/v2/bz/v3/getUrl/393204c88fff4715a4b4aa88aabdb2ed21")).arrayBuffer() +// fs.writeFileSync("./a.png", Buffer.from(stream!)) + +let totalPage = 1 +async function downImageByPage(current: number) { + const res = await (await fetch("https://api.zzzmh.cn/v2/bz/v3/getData", { + method: "POST", + headers: { + 'Content-Type': 'application/json;charset=utf-8', + referer: "https://bz.zzzmh.cn/" + }, + body: `{ "size": 24, "current": ${current}, "sort": 0, "category": 0, "resolution": 0, "color": 0, "categoryId": 0, "ratio": 0 }` + })).json() + totalPage = res.data.totalPage + for (let i = 0; i < res.data.list.length; i++) { + const item = res.data.list[i]; + console.log(`正在下载第${i + 1}张图片`); + await (() => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(1) + }, Math.random() * 2000 + 500); + }) + })(); + const stream = await (await fetch("https://api.zzzmh.cn/v2/bz/v3/getUrl/" + item.i + (item.t == 2 ? "21" : "11"))).arrayBuffer() + const p = "./dist/" + "page-" + current + "/" + item.i + ".png" + if (!await checkExist("./dist/" + "page-" + current)) { + fs.mkdirSync("./dist/" + "page-" + current, { recursive: true }) + } + const isExist = await checkExist(p) + if (!isExist) { + fs.writeFileSync(p, Buffer.from(stream!), { flag: "w" }) + } else { + console.log("文件已存在,跳过下载", item.i + ".png"); + } + } +} + +downImageByPage(2) + +function checkExist(path: string) { + return new Promise((resolve, reject) => { + fs.access(path, fs.constants.F_OK, (err) => { + if (err) { + resolve(false) + } else { + resolve(true) + } + }) + }) +} + +// async function readAllChunks(readableStream: any) { +// const reader = readableStream.getReader(); +// const chunks = []; + +// let done, value; +// while (!done) { +// ({ value, done } = await reader.read()); +// if (done) { +// return chunks; +// } +// chunks.push(value); +// } +// } +// const rr = await readAllChunks(stream) +// fs.writeFileSync("./a.png", Buffer.from(rr!)) + +// const maxNum = 3 +// function request(opts: any, cb: any, num = 0) { +// https.get(opts, function (res: IncomingMessage) { +// if (res.statusCode === 302) { +// if (num > maxNum) { +// console.error("重定向次数超过三次,已强制终止"); +// return +// } +// let url = new URL(res.headers['location']!) +// if (url) { +// console.log(`重定向:`, url.href); +// num++ +// // 重定向 +// request({ +// ...opts, +// hostname: url.hostname, +// path: url.pathname + url.search, +// }, cb, num) +// } +// } else if (res.statusCode === 200) { +// cb && cb(res) +// } else { +// console.log(`当前${opts.hostname}请求${opts.path}未成功`, res.statusCode); +// // res.on('data', (d) => { +// // process.stdout.write(d); +// // }); +// } +// }) +// } + +// fetch("https://bz.zzzmh.cn/index") +// .then((res) => res.text()) +// .then((html) => { +// const $ = cheerio.load(html) +// console.log($("title").text()); +// }); \ No newline at end of file diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..5280b3e4c64d08211cc0fa7f1fba55001c75817d GIT binary patch literal 12104 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 F{s-J@t$+Xk literal 0 HcmV?d00001 diff --git a/package.json b/package.json new file mode 100644 index 0000000..d5d6f61 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "pic", + "module": "index.ts", + "type": "module", + "devDependencies": { + "@types/bun": "latest" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "dependencies": { + "@types/node": "^22.7.9", + "cheerio": "^1.0.0" + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..238655f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} diff --git a/wallhaven/index.ts b/wallhaven/index.ts new file mode 100644 index 0000000..ff9b59d --- /dev/null +++ b/wallhaven/index.ts @@ -0,0 +1,64 @@ +import { fetch } from "bun"; +import * as cheerio from "cheerio" +import fs from "node:fs"; +import path from "node:path"; + +const output = path.resolve(__dirname, "../dist/wallhaven") + +async function downImageByPage(page: number) { + const html = await (await fetch("https://wallhaven.cc/search?categories=110&purity=100&topRange=1M&sorting=toplist&order=desc&ai_art_filter=1&page=" + page, { + method: "GET" + })).text() + + const $ = cheerio.load(html); + + const previewList: string[] = [] + + $("#thumbs > section > ul > li > figure > a").each((index, el) => { + previewList[index] = $(el).attr("href") as string + }); + + for (let i = 0; i < previewList.length; i++) { + const previewURL = previewList[i]; + console.log(`正在下载第${i + 1}张图片`); + await (() => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(1) + }, Math.random() * 2000 + 500); + }) + })(); + const html = await (await fetch(previewURL, { + method: "GET" + })).text() + const $ = cheerio.load(html); + const imageURL = $("#wallpaper").attr("src") as string + const p = path.resolve(output, "page-" + page + "/" + imageURL.split('/').slice(-1).join('')) + console.log("图片地址:", imageURL); + console.log("图片保存地址:", p); + if (!await checkExist(path.resolve(output, "page-" + page))) { + fs.mkdirSync(path.resolve(output, "page-" + page), { recursive: true }) + } + const isExist = await checkExist(p) + if (!isExist) { + const stream = await (await fetch(imageURL)).arrayBuffer() + fs.writeFileSync(p, Buffer.from(stream!), { flag: "w" }) + } else { + console.log("文件已存在,跳过下载", imageURL); + } + } +} + +function checkExist(path: string) { + return new Promise((resolve, reject) => { + fs.access(path, fs.constants.F_OK, (err) => { + if (err) { + resolve(false) + } else { + resolve(true) + } + }) + }) +} + +downImageByPage(1) diff --git a/zzzmh/index.ts b/zzzmh/index.ts new file mode 100644 index 0000000..6405437 --- /dev/null +++ b/zzzmh/index.ts @@ -0,0 +1,54 @@ +import { fetch } from "bun" +import fs from "node:fs" +import path from "node:path" + +const output = path.resolve(__dirname, "../dist/zzzmh") + +let totalPage = 1 +async function downImageByPage(current: number) { + const res = await (await fetch("https://api.zzzmh.cn/v2/bz/v3/getData", { + method: "POST", + headers: { + 'Content-Type': 'application/json;charset=utf-8', + referer: "https://bz.zzzmh.cn/" + }, + body: `{ "size": 24, "current": ${current}, "sort": 0, "category": 0, "resolution": 0, "color": 0, "categoryId": 0, "ratio": 0 }` + })).json() + totalPage = res.data.totalPage + for (let i = 0; i < res.data.list.length; i++) { + const item = res.data.list[i]; + console.log(`正在下载第${i + 1}张图片`); + await (() => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(1) + }, Math.random() * 2000 + 500); + }) + })(); + const stream = await (await fetch("https://api.zzzmh.cn/v2/bz/v3/getUrl/" + item.i + (item.t == 2 ? "21" : "11"))).arrayBuffer() + const p = path.resolve(output, "page-" + current + "/" + item.i + ".png") + if (!await checkExist(path.resolve(output, "page-" + current))) { + fs.mkdirSync(path.resolve(output, "page-" + current), { recursive: true }) + } + const isExist = await checkExist(p) + if (!isExist) { + fs.writeFileSync(p, Buffer.from(stream!), { flag: "w" }) + } else { + console.log("文件已存在,跳过下载", item.i + ".png"); + } + } +} + +function checkExist(path: string) { + return new Promise((resolve, reject) => { + fs.access(path, fs.constants.F_OK, (err) => { + if (err) { + resolve(false) + } else { + resolve(true) + } + }) + }) +} + +downImageByPage(2) \ No newline at end of file