Compare commits
30 Commits
c97825b54f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c88d106a55 | |||
| 42485cc97e | |||
| bb1c7ec16d | |||
| 7280705baf | |||
| 39e1f58665 | |||
| b2c8345798 | |||
| 6d56fe8638 | |||
| afd0b1125d | |||
| b8e35a9760 | |||
| f4beb32725 | |||
| cdf683bd62 | |||
| 80b3219244 | |||
| 09f402377e | |||
| 5f127098cf | |||
| a9b6a2c7fd | |||
| e62c113c93 | |||
| eb2e0e5d2a | |||
| 5d22686cf8 | |||
| 31cf0d0daa | |||
| 76924ac0a5 | |||
| 7042f3d11e | |||
| 368d23399a | |||
| 05dc0aac1b | |||
| c4feb57867 | |||
| a51818759c | |||
| 497b3ab9ed | |||
| 409ff2f44a | |||
| ac8d89454b | |||
| 586fb257bd | |||
| 8372b221ee |
118
main.js
118
main.js
@@ -8,6 +8,7 @@ class 计数 {
|
||||
周 = new Map()
|
||||
月 = new Map()
|
||||
年 = new Map()
|
||||
总 = new Map()
|
||||
}
|
||||
|
||||
class 类型 {
|
||||
@@ -25,6 +26,27 @@ const 截图 = new 类型()
|
||||
const 收藏 = new 类型()
|
||||
const 综合 = new 类型()
|
||||
|
||||
// 获取浏览数
|
||||
export function get_views(name, ids = []) {
|
||||
const all = { 文章, 作品, 游戏, 截图, 收藏, 综合 }
|
||||
const counts = all[name].浏览数.总
|
||||
return ids.map(id => ({ id: parseInt(id, 10), count: counts.get(id) || 0 }))
|
||||
}
|
||||
|
||||
// 获取当日热门搜索词
|
||||
export function get_search(n = 10) {
|
||||
const 全部 = new Map()
|
||||
const all = { 文章, 作品, 游戏, 截图, 收藏, 综合 }
|
||||
for (const key in all) {
|
||||
all[key].搜索词.日.forEach((value, key) => {
|
||||
console.log(key, value)
|
||||
全部.set(key, (全部.get(key) || 0) + value)
|
||||
})
|
||||
}
|
||||
return [...全部.entries()].sort((a, b) => b[1] - a[1]).slice(0, n).map(([text, count]) => {
|
||||
return { text, count }
|
||||
})
|
||||
}
|
||||
|
||||
const 日期格式 = new Intl.DateTimeFormat('zh-CN', {
|
||||
year: 'numeric',
|
||||
@@ -36,7 +58,8 @@ const 日期格式 = new Intl.DateTimeFormat('zh-CN', {
|
||||
// 匹配文章和截图的正则表达式
|
||||
const imagesRegex = /\/web\/v1\/images\/detail\/v2\?imagesId=(\d+)¤tUserId=(\d+)/
|
||||
const articleRegex = /\/web\/v1\/article\/get\?id=(\d+)&userId=(\d+)/
|
||||
const collectionRegex = /\/web\/v1\/member\/explorer\/article\/get\?id=(\d+)/
|
||||
const collectionArticleRegex = /\/web\/v1\/member\/explorer\/article\/get\?id=(\d+)/
|
||||
const collectionImagesRegex = /\/web\/v1\/member\/explorer\/get\?id=(\d+)/
|
||||
|
||||
|
||||
var 当前日期 = 日期格式.format(new Date()).replace(/\//g, '-')
|
||||
@@ -60,7 +83,19 @@ const 存档 = async (message = '正在存档...') => {
|
||||
}
|
||||
|
||||
|
||||
export default function () {
|
||||
export function main() {
|
||||
console.log(当前日期, '启动时加载全部数据...')
|
||||
fs.readdirSync('./data').filter(file => file.endsWith('.json')).map(name => {
|
||||
console.log('filename:', name)
|
||||
const file = fs.readFileSync(`./data/${name}`, 'utf8')
|
||||
if (file) {
|
||||
const data = JSON.parse(file)
|
||||
Object.entries(data.文章).forEach(([key, value]) => 文章.浏览数.总.set(key, value))
|
||||
Object.entries(data.截图).forEach(([key, value]) => 截图.浏览数.总.set(key, value))
|
||||
Object.entries(data.收藏).forEach(([key, value]) => 收藏.浏览数.总.set(key, value))
|
||||
}
|
||||
})
|
||||
|
||||
console.log(当前日期, '启动时加载当日数据...')
|
||||
if (fs.existsSync(`./data/${当前日期}.json`)) {
|
||||
const file = fs.readFileSync(`./data/${当前日期}.json`, 'utf8')
|
||||
@@ -76,21 +111,23 @@ export default function () {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setInterval(async () => {
|
||||
|
||||
try {
|
||||
存档('每10分钟自动存档...')
|
||||
await update('web_images', 'day_rank', Object.entries(Object.fromEntries(截图.浏览数.日)))
|
||||
await update('web_article', 'day_rank', Object.entries(Object.fromEntries(文章.浏览数.日)))
|
||||
await update_explorer('web_member_explorer', 'day_rank', Object.entries(Object.fromEntries(收藏.浏览数.日)))
|
||||
} catch(err) {
|
||||
console.error(err)
|
||||
// 定时执行任务,确保上一次执行完毕后才开始下一轮
|
||||
async function startScheduledTask() {
|
||||
while (true) {
|
||||
try {
|
||||
存档('每10分钟自动存档...')
|
||||
await update('web_images', 'day_rank', Object.entries(Object.fromEntries(截图.浏览数.日)))
|
||||
await update('web_article', 'day_rank', Object.entries(Object.fromEntries(文章.浏览数.日)))
|
||||
await update_explorer('web_member_explorer', 'day_rank', Object.entries(Object.fromEntries(收藏.浏览数.日)))
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 10 * 60 * 1000))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}, 10000)
|
||||
|
||||
// 启动定时任务
|
||||
startScheduledTask()
|
||||
|
||||
console.log(当前日期, '开始收集日志...')
|
||||
const tail = new Tail('/opt/log/caddy/access.log')
|
||||
@@ -118,7 +155,11 @@ export default function () {
|
||||
if (item.request.uri.startsWith('/web/v1/article/get')) {
|
||||
const [uri, id] = item.request.uri.match(articleRegex) ?? []
|
||||
if (uri && id) {
|
||||
文章.浏览数.日.set(id, 文章.浏览数.日.has(id) ? 文章.浏览数.日.get(id) + 1 : 1)
|
||||
文章.浏览数.日.set(id, (文章.浏览数.日.get(id) || 0) + 1)
|
||||
文章.浏览数.周.set(id, (文章.浏览数.周.get(id) || 0) + 1)
|
||||
文章.浏览数.月.set(id, (文章.浏览数.月.get(id) || 0) + 1)
|
||||
文章.浏览数.年.set(id, (文章.浏览数.年.get(id) || 0) + 1)
|
||||
文章.浏览数.总.set(id, (文章.浏览数.总.get(id) || 0) + 1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,16 +167,53 @@ export default function () {
|
||||
if (item.request.uri.startsWith('/web/v1/images/detail/v2')) {
|
||||
const [uri, id] = item.request.uri.match(imagesRegex) ?? []
|
||||
if (uri && id) {
|
||||
截图.浏览数.日.set(id, 截图.浏览数.日.has(id) ? 截图.浏览数.日.get(id) + 1 : 1)
|
||||
截图.浏览数.日.set(id, (截图.浏览数.日.get(id) || 0) + 1)
|
||||
截图.浏览数.周.set(id, (截图.浏览数.周.get(id) || 0) + 1)
|
||||
截图.浏览数.月.set(id, (截图.浏览数.月.get(id) || 0) + 1)
|
||||
截图.浏览数.年.set(id, (截图.浏览数.年.get(id) || 0) + 1)
|
||||
截图.浏览数.总.set(id, (截图.浏览数.总.get(id) || 0) + 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 处理收藏日志
|
||||
// 处理收藏图集日志
|
||||
if (item.request.uri.startsWith('/web/v1/member/explorer/article/get')) {
|
||||
const [uri, id] = item.request.uri.match(collectionRegex) ?? []
|
||||
const [uri, id] = item.request.uri.match(collectionArticleRegex) ?? []
|
||||
if (uri && id) {
|
||||
收藏.浏览数.日.set(id, 收藏.浏览数.日.has(id) ? 收藏.浏览数.日.get(id) + 1 : 1)
|
||||
收藏.浏览数.日.set(id, (收藏.浏览数.日.get(id) || 0) + 1)
|
||||
收藏.浏览数.周.set(id, (收藏.浏览数.周.get(id) || 0) + 1)
|
||||
收藏.浏览数.月.set(id, (收藏.浏览数.月.get(id) || 0) + 1)
|
||||
收藏.浏览数.年.set(id, (收藏.浏览数.年.get(id) || 0) + 1)
|
||||
收藏.浏览数.总.set(id, (收藏.浏览数.总.get(id) || 0) + 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 处理收藏图片日志
|
||||
if (item.request.uri.startsWith('/web/v1/member/explorer/get')) {
|
||||
const [uri, id] = item.request.uri.match(collectionImagesRegex) ?? []
|
||||
if (uri && id) {
|
||||
收藏.浏览数.日.set(id, (收藏.浏览数.日.get(id) || 0) + 1)
|
||||
收藏.浏览数.周.set(id, (收藏.浏览数.周.get(id) || 0) + 1)
|
||||
收藏.浏览数.月.set(id, (收藏.浏览数.月.get(id) || 0) + 1)
|
||||
收藏.浏览数.年.set(id, (收藏.浏览数.年.get(id) || 0) + 1)
|
||||
收藏.浏览数.总.set(id, (收藏.浏览数.总.get(id) || 0) + 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 处理搜索日志
|
||||
if (item.request.uri.startsWith('/api?query=')) {
|
||||
const url = decodeURI(item.request.uri)
|
||||
const regex = /text:"([^"]*)"/g
|
||||
const match = regex.exec(url)
|
||||
if (match) {
|
||||
let key = match[1]
|
||||
截图.搜索词.日.set(key, (截图.搜索词.日.get(key) || 0) + 1)
|
||||
截图.搜索词.周.set(key, (截图.搜索词.周.get(key) || 0) + 1)
|
||||
截图.搜索词.月.set(key, (截图.搜索词.月.get(key) || 0) + 1)
|
||||
截图.搜索词.年.set(key, (截图.搜索词.年.get(key) || 0) + 1)
|
||||
截图.搜索词.总.set(key, (截图.搜索词.总.get(key) || 0) + 1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
11
server.js
11
server.js
@@ -1,10 +1,19 @@
|
||||
import fs from 'fs'
|
||||
import express from 'express'
|
||||
import main from './main.js'
|
||||
import { main, get_search, get_views } from './main.js'
|
||||
|
||||
const app = express()
|
||||
|
||||
app.use(express.json())
|
||||
|
||||
app.get('/api/get_views/:name', (req, res) => {
|
||||
res.json(get_views(req.params.name, req.query.ids.split(",")))
|
||||
})
|
||||
|
||||
app.get('/api/get_search/hot', (req, res) => {
|
||||
res.json(get_search(req.query.pagesize || 10))
|
||||
})
|
||||
|
||||
app.get('/api', (req, res) => {
|
||||
const { start, end } = req.query
|
||||
console.log(req.query)
|
||||
|
||||
31
update.js
31
update.js
@@ -82,35 +82,44 @@ export async function update(table, rank, views) {
|
||||
|
||||
// 0=文章/游戏/作品 1=短视频 2=图片
|
||||
const TYPE = {
|
||||
'web_images': 'type=2',
|
||||
'web_images': 'type=2',
|
||||
'web_article': 'type=0',
|
||||
}
|
||||
|
||||
// 定义查询时间范围
|
||||
const WHERE = {
|
||||
'day_rank': `create_time >= CURDATE() AND ${TYPE[table]}`,
|
||||
'week_rank': `create_time >= CURDATE() - INTERVAL 7 DAY AND ${TYPE[table]}`,
|
||||
'day_rank': `create_time >= CURDATE() AND ${TYPE[table]}`,
|
||||
'week_rank': `create_time >= CURDATE() - INTERVAL 7 DAY AND ${TYPE[table]}`,
|
||||
'month_rank': `create_time >= CURDATE() - INTERVAL 1 MONTH AND ${TYPE[table]}`,
|
||||
'year_rank': `create_time >= CURDATE() - INTERVAL 1 YEAR AND ${TYPE[table]}`,
|
||||
'aeon_rank': `${TYPE[table]}`
|
||||
'year_rank': `create_time >= CURDATE() - INTERVAL 1 YEAR AND ${TYPE[table]}`,
|
||||
'aeon_rank': `${TYPE[table]}`
|
||||
}
|
||||
|
||||
const JOIN = {
|
||||
'comment': `SELECT comment_id AS id, COUNT(*) AS comment_count FROM web_comment WHERE ${WHERE[rank]} GROUP BY id`,
|
||||
'praise': `SELECT praise_id AS id, COUNT(*) AS praise_count FROM web_praise WHERE ${WHERE[rank]} GROUP BY id`,
|
||||
'collect': `SELECT collect_id AS id, COUNT(*) AS collect_count FROM web_collect WHERE ${WHERE[rank]} GROUP BY id`
|
||||
'comment': `SELECT comment_id AS id, IFNULL(COUNT(*), 0) AS comment_count FROM web_comment WHERE ${WHERE[rank]} GROUP BY comment_id`,
|
||||
'praise': `SELECT praise_id AS id, IFNULL(COUNT(*), 0) AS praise_count FROM web_praise WHERE ${WHERE[rank]} GROUP BY praise_id`,
|
||||
'collect': `SELECT collect_id AS id, IFNULL(COUNT(*), 0) AS collect_count FROM web_collect WHERE ${WHERE[rank]} GROUP BY collect_id`
|
||||
}
|
||||
|
||||
for (let name of ['comment', 'praise', 'collect']) {
|
||||
console.log(`统计 ${rank} 时间段内 ${name} 数到临时表`)
|
||||
await conn.query(`UPDATE temp_updates t JOIN(${JOIN[name]}) stats ON t.id = stats.id SET t.${name}_count = stats.${name}_count`)
|
||||
const updateResult = await conn.query(`UPDATE temp_updates t JOIN(${JOIN[name]}) stats ON t.id = stats.id SET t.${name}_count = stats.${name}_count`)
|
||||
console.log(`${name} 更新结果:`, updateResult)
|
||||
}
|
||||
|
||||
console.log('统计当天时间段内排行榜到临时表')
|
||||
await conn.query("UPDATE temp_updates SET rank = collect_count * 35 + praise_count * 20 + comment_count * 20 + views_count * 25")
|
||||
const rankUpdateResult = await conn.query("UPDATE temp_updates SET rank = IFNULL(collect_count, 0) * 35 + IFNULL(praise_count, 0) * 20 + IFNULL(comment_count, 0) * 20 + IFNULL(views_count, 0) * 25")
|
||||
console.log('排行榜更新结果:', rankUpdateResult)
|
||||
|
||||
// 打印临时表前 10 条数据
|
||||
console.log('打印临时表前 10 条数据')
|
||||
const [tempData] = await conn.query("SELECT * FROM temp_updates LIMIT 10")
|
||||
console.log('临时表数据:', tempData)
|
||||
|
||||
console.log('更新数据从临时表转入生产库', table)
|
||||
await conn.query(`UPDATE ${table} t LEFT JOIN temp_updates tu ON t.id = tu.id SET t.${rank} = IFNULL(tu.rank, 0)`)
|
||||
const finalUpdateResult = await conn.query(`UPDATE ${table} t LEFT JOIN temp_updates tu ON t.id = tu.id SET t.${rank} = IFNULL(tu.rank, 0)`)
|
||||
console.log('生产库更新结果:', finalUpdateResult)
|
||||
|
||||
await conn.end()
|
||||
console.log('更新完成')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user