Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
node_modules/
build/
yarn.lock
package-lock.json
cookie.ts
cookies.ts

dist/
logs
22 changes: 6 additions & 16 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
{
"typescript.tsdk": "node_modules\\typescript\\lib",
"cSpell.words": [
"KHTML",
"laruence",
"sina"
],
"cSpell.ignorePaths": [
"**/package-lock.json",
"**/node_modules/**",
"**/vscode-extension/**",
"**/.git/objects/**",
".vscode",
"**/cookie.ts",
"src/config/app.ts"
]
}
"typescript.tsdk": "node_modules/typescript/lib",
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit",
"source.fixAll.biome": "explicit"
}
}
30 changes: 30 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "typescript",
"tsconfig": "tsconfig.json",
"option": "watch",
"problemMatcher": [
"$tsc-watch"
],
"group": "build",
"label": "tsc: 监视 - tsconfig.json"
},
{
"label": "esbuild: watch",
"type": "shell",
"command": "node",
"args": [
"esbuild.js",
],
"group": {
"kind": "build",
"isDefault": true // 设为默认构建任务(Ctrl+Shift+B 直接运行)
},

"problemMatcher": [], // 不匹配问题(esbuild 错误会直接显示)
"detail": "使用 esbuild watch 打包项目"
}
]
}
17 changes: 17 additions & 0 deletions 1.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

# 定义起始值和执行次数
START_UID=1001
DELAY=7200.0
COUNT=10 # 执行的次数,可以根据需要修改

# 循环执行命令
for ((i=0; i<COUNT; i++)); do
S_UID=$((START_UID + i))
DELAY=$(echo "scale=1; $DELAY + 0.01" | bc)
echo "启动实例: UID=$S_UID, DELAY_TS=$DELAY"
HL=1 DELAY_TS=$DELAY XMMX_UID=$S_UID nohup yarn start > "./logs/$S_UID.log" 2>&1 &
# sleep 1
done

echo "所有实例已启动"
58 changes: 58 additions & 0 deletions biome.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"$schema": "https://biomejs.dev/schemas/2.2.2/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"includes": [
"./src/**"
]
},
"formatter": {
"enabled": true,
"indentWidth": 2,
"indentStyle": "space",
"lineEnding": "lf",
"lineWidth": 120,
"attributePosition": "auto"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noExplicitAny": "off"
},
"correctness": {
"useExhaustiveDependencies": "off"
}
}
},
"javascript": {
"globals": [
"$",
"_"
],
"formatter": {
"arrowParentheses": "asNeeded",
"bracketSameLine": false,
"bracketSpacing": true,
"jsxQuoteStyle": "double",
"quoteProperties": "asNeeded",
"semicolons": "asNeeded",
"trailingCommas": "all",
"quoteStyle": "single"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
21 changes: 21 additions & 0 deletions esbuild.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as esbuild from 'esbuild'

let ctx = await esbuild.context({
entryPoints: ['src/index.ts'],
tsconfig: 'tsconfig.json',
bundle: true,
minify: true,
sourcemap: false,
format: "esm",
charset: "utf8",
target: ['node22'],
platform: "node",
legalComments: "none",
outfile: 'dist/bundle.js',
banner: {
js: "import { createRequire as topLevelCreateRequire } from 'module'; const require = topLevelCreateRequire(import.meta.url);"
},
})

await ctx.watch()
console.log('watching...')
31 changes: 12 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,24 @@
{
"name": "spider",
"version": "1.0.0",
"main": "index.js",
"repository": "https://github.com/buffge/spider",
"author": "buffge <1515888956@qq.com>",
"author": "buffge <admin@buffge.com>",
"license": "MIT",
"private": false,
"private": true,
"type": "module",
"dependencies": {
"delay": "^4.3.0",
"jquery": "^3.4.1",
"module-alias": "^2.2.2",
"moment": "^2.24.0",
"puppeteer-core": "^1.20.0"
"puppeteer-core": "^24.17.0"
},
"devDependencies": {
"@types/jquery": "^3.3.31",
"@types/node": "^12.7.12",
"@types/puppeteer-core": "^1.9.0",
"typescript": "^3.6.4"
"@biomejs/biome": "^2.2.2",
"@types/node": "^22.18.0",
"esbuild": "^0.25.9",
"typescript": "^5.9.2"
},
"scripts": {
"start": "node ./build/index"
},
"_moduleAliases": {
"@": "./build",
"@interface": "./build/interface",
"@sites": "./build/sites",
"@conf": "./build/config"
"esbuild":"node esbuild.js",
"start": "node ./dist/bundle.js",
"fix": "biome check --fix .",
"lint": "biome check ."
}
}
2 changes: 0 additions & 2 deletions runtime/screenshot/.gitignore

This file was deleted.

89 changes: 48 additions & 41 deletions src/Spider.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import ISpider, { ScreenShotConf, Mode } from "@/interface/Spider"
import { existsSync, mkdirSync } from "fs"
import * as os from "os"
import { existsSync, mkdirSync } from 'node:fs'
import { pseudoChrome, scriptNameMapPath } from '@conf/app'
import puppeteer, {
Browser,
DirectNavigationOptions,
LaunchOptions,
Page,
SetCookie,
} from "puppeteer-core"
import { pseudoChrome, scriptNameMapPath } from "./config/app"
type Browser,
type CookieData,
type GoToOptions,
type LaunchOptions,
type Page,
} from 'puppeteer-core'
export interface ScreenShotConf {
// 存储路径
path: string
// 截屏文件名
fileName: string
// 全屏
fullPage?: boolean
}
export type Mode = 'debug' | 'prod'
declare let window: Window & { chrome: any }
export default class Spider implements ISpider {
export default class Spider {
startTime?: Date
pages: Page[] = []
browser?: Browser
constructor(mode: Mode = "prod") {
mode = mode
mode: Mode
constructor(mode: Mode = 'prod') {
this.mode = mode
}
start() {}
async launch(opts: LaunchOptions) {
Expand All @@ -31,37 +39,37 @@ export default class Spider implements ISpider {
window.chrome = pseudoChrome
const originalQuery = window.navigator.permissions.query
window.navigator.permissions.query = parameters =>
parameters.name === "notifications"
parameters.name === 'notifications'
? Promise.resolve({ state: Notification.permission } as PermissionStatus)
: originalQuery(parameters)
//插件这个不要写
// Object.defineProperty(navigator, 'plugins', {
// get: () => [1, 2, 3, 4, 5],
// });
Object.defineProperty(navigator, "languages", {
get: () => ["en", "zh-CN", "zh"],
Object.defineProperty(navigator, 'languages', {
get: () => ['en', 'zh-CN', 'zh'],
})
Object.defineProperty(navigator, "language", {
get: () => ["en"],
Object.defineProperty(navigator, 'language', {
get: () => ['en'],
})
Object.defineProperty(navigator, "webdriver", {
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined,
})
})
}
async setRequestInterception(page: Page) {
await page.setRequestInterception(true)
page.on("request", interceptedRequest => {
let reqUrl = interceptedRequest.url()
let suffix = ""
let urlSplitArr = reqUrl.split(".")
page.on('request', interceptedRequest => {
const reqUrl = interceptedRequest.url()
let suffix = ''
const urlSplitArr = reqUrl.split('.')
if (urlSplitArr.length > 1) {
suffix = urlSplitArr.pop() as string
}
const disableSuffixArr = ["png", "jpg", "jpeg", "webp", "gif", "bmp", "woff", "woff2", "ttf"]
const disableSuffixArr = ['png', 'jpg', 'jpeg', 'webp', 'gif', 'bmp', 'woff', 'woff2', 'ttf']
if (
interceptedRequest.resourceType() === "image" ||
interceptedRequest.resourceType() === "font" ||
interceptedRequest.resourceType() === 'image' ||
interceptedRequest.resourceType() === 'font' ||
disableSuffixArr.includes(suffix)
) {
interceptedRequest.abort()
Expand All @@ -71,25 +79,24 @@ export default class Spider implements ISpider {
})
}
async setMaxViewport(page: Page, headless: boolean) {
let availWidth =
os.platform() === "win32" && !headless
? await page.evaluate(() => {
console.log(screen.availWidth)
return screen.availWidth
})
: 1920
const [width, height] = !headless
? await page.evaluate(() => {
console.log(screen)
return [screen.width, screen.height]
})
: [2560, 1440]
return await page.setViewport({
width: availWidth,
height: 1080,
width: width,
height: height,
})
}
async screenShot(page: Page, conf: ScreenShotConf) {
const { fileName, fullPage, path } = conf
const { fullPage, path } = conf
if (!existsSync(path)) {
mkdirSync(path, { recursive: true })
}
await page.screenshot({
path: path + "/" + fileName + ".png",
// path: path + "/" + fileName + ".png",
fullPage: !!fullPage,
})
}
Expand All @@ -98,16 +105,16 @@ export default class Spider implements ISpider {
path: scriptNameMapPath[scriptName],
})
}
async go(page: Page, url: string, opts: DirectNavigationOptions = {}) {
async go(page: Page, url: string, opts: GoToOptions = {}) {
await page.goto(url, opts)
}
async shutdown() {
if (!this.browser) {
throw new Error("browser not init!")
throw new Error('browser not init!')
}
await this.browser.close()
}
async setCookie(page: Page, cookie: SetCookie[]) {
await page.setCookie(...cookie)
async setCookie(_: Page, cookie: CookieData[]) {
await this.browser?.setCookie(...cookie)
}
}
Loading