npmrun 2 weeks ago
commit
b873cc2430
  1. 175
      .gitignore
  2. 15
      README.md
  3. 53
      backup-file/index copy.ts
  4. 111
      backup-file/index.ts
  5. BIN
      bun.lockb
  6. 15
      package.json
  7. 27
      tsconfig.json
  8. 64
      wallhaven/index.ts
  9. 54
      zzzmh/index.ts

175
.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

15
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.

53
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)
})
})

111
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());
// });

BIN
bun.lockb

Binary file not shown.

15
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"
}
}

27
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
}
}

64
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)

54
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)
Loading…
Cancel
Save