Compare commits
	
		
			32 Commits
		
	
	
		
			49bd703039
			...
			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 | |||
| c97825b54f | |||
| f8c408878e | 
							
								
								
									
										113
									
								
								main.js
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								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,14 +111,23 @@ export default function () {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 定时执行任务,确保上一次执行完毕后才开始下一轮
 | 
			
		||||
    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))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setInterval(async () => {
 | 
			
		||||
        存档('每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(收藏.浏览数.日)))
 | 
			
		||||
    }, 10000)
 | 
			
		||||
 | 
			
		||||
    // 启动定时任务
 | 
			
		||||
    startScheduledTask()
 | 
			
		||||
 | 
			
		||||
    console.log(当前日期, '开始收集日志...')
 | 
			
		||||
    const tail = new Tail('/opt/log/caddy/access.log')
 | 
			
		||||
@@ -111,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)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -119,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)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								update.js
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								update.js
									
									
									
									
									
								
							@@ -48,7 +48,7 @@ export async function update_explorer(table, rank, views) {
 | 
			
		||||
  console.log('统计当天时间段内排行榜到临时表')
 | 
			
		||||
  await conn.query("UPDATE temp_updates SET rank = fans_count * 35 + views_count * 25")
 | 
			
		||||
 | 
			
		||||
  console.log('更新数据从临时表转入生产库')
 | 
			
		||||
  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)`)
 | 
			
		||||
  await conn.end()
 | 
			
		||||
  console.log('更新完成')
 | 
			
		||||
@@ -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)
 | 
			
		||||
  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)
 | 
			
		||||
 | 
			
		||||
  console.log('更新数据从临时表转入生产库')
 | 
			
		||||
  await conn.query(`UPDATE ${table} t LEFT JOIN temp_updates tu ON t.id = tu.id SET t.${rank} = IFNULL(tu.rank, 0)`)
 | 
			
		||||
  await conn.end()
 | 
			
		||||
  console.log('更新完成')
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user