| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- /**
- * 每天运行一次,生成站点地图
- */
- const fs = require('fs');
- const datefns = require('date-fns');
- const models = require('../../models');
- const categories = require('../../config/category');
- const { tags } = require('../../config/tag');
- const date = datefns.format(Date.now(), 'yyyy-MM-dd');
- const sitemapPath = __dirname + '/../../dist/sitemap.xml';
- const sitemapTempPath = __dirname + '/../../dist/sitemap.xml.temp';
- // 生成站点地图
- async function generateSitemap() {
- let commonXml = [
- '<?xml version="1.0" encoding="UTF-8"?>',
- // '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
- '<urlset',
- ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',
- ' xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.w3.org/1999/xhtml http://www.w3.org/2002/08/xhtml/xhtml1-strict.xsd"',
- ' xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"',
- ' xmlns:xhtml="http://www.w3.org/1999/xhtml"',
- '>',
- ' <url>',
- ' <loc>https://art.pcoloring.com/en</loc>',
- ` <lastmod>${date}</lastmod>`,
- ' <changefreq>daily</changefreq>',
- ' <priority>1.0</priority>',
- ' </url>',
- ' <url>',
- ' <loc>https://art.pcoloring.com/en/videos</loc>',
- ` <lastmod>${date}</lastmod>`,
- ' <changefreq>weekly</changefreq>',
- ' <priority>0.8</priority>',
- ' </url>',
- ' <url>',
- ' <loc>https://art.pcoloring.com/en/category</loc>',
- ` <lastmod>${date}</lastmod>`,
- ' <changefreq>daily</changefreq>',
- ' <priority>0.8</priority>',
- ' </url>',
- ' <url>',
- ' <loc>https://art.pcoloring.com/en/tag</loc>',
- ` <lastmod>${date}</lastmod>`,
- ' <changefreq>daily</changefreq>',
- ' <priority>0.8</priority>',
- ' </url>',
- ' <url>',
- ' <loc>https://art.pcoloring.com/en/albums</loc>',
- ` <lastmod>${date}</lastmod>`,
- ' <changefreq>weekly</changefreq>',
- ' <priority>0.8</priority>',
- ' </url>',
- ' <url>',
- ' <loc>https://art.pcoloring.com/en/special</loc>',
- ` <lastmod>${date}</lastmod>`,
- ' <changefreq>daily</changefreq>',
- ' <priority>0.8</priority>',
- ' </url>',
- ' <url>',
- ' <loc>https://art.pcoloring.com/en/artists</loc>',
- ` <lastmod>${date}</lastmod>`,
- ' <changefreq>monthly</changefreq>',
- ' <priority>0.8</priority>',
- ' </url>',
- ' <url>',
- ' <loc>https://art.pcoloring.com/en/info</loc>',
- ` <lastmod>${date}</lastmod>`,
- ' </url>',
- ];
- // categories
- let categoriesXml = [];
- categories.forEach(e => {
- categoriesXml = categoriesXml.concat([
- ' <url>',
- ` <loc>https://art.pcoloring.com/en/category/${e.id}</loc>`,
- ` <lastmod>${date}</lastmod>`,
- ' </url>',
- ]
- );
- });
- console.log(categoriesXml);
- // tags
- let tagsXml = [];
- tags.forEach(e => {
- tagsXml = tagsXml.concat([
- ' <url>',
- ` <loc>https://art.pcoloring.com/en/tag/${e.tag}</loc>`,
- ` <lastmod>${date}</lastmod>`,
- ' </url>',
- ]);
- });
- console.log(tagsXml);
- // albums
- let albums = await models.ArtAlbum
- .find({ pid: 'art', enabled: true })
- .sort({ order: 'asc' })
- .select('_id')
- .lean()
- .exec();
- let albumsXml = [];
- albums.forEach(e => {
- albumsXml = albumsXml.concat([
- ' <url>',
- ` <loc>https://art.pcoloring.com/en/coloring-page-album/${e._id}</loc>`,
- ` <lastmod>${date}</lastmod>`,
- ' </url>',
- ])
- });
- console.log(albumsXml);
- // designers
- let designers = await models.Art.aggregate([
- // 首先,过滤出 status = 9000 的文档
- { $match: { open: true, status: 9000 } },
- // 首先,根据 user 字段进行分组,并计算每个 user 出现的次数
- { $group: { _id: '$user', count: { $sum: 1 } } },
- // 然后,按照 count 字段进行降序排列
- { $sort: { count: -1 } },
- // 接着,与 users 集合进行连接,以获取用户的详细信息
- {
- $lookup: {
- from: 'users', // 要连接的集合名称
- localField: '_id', // 本地字段(即上一步分组后的 _id 字段)
- foreignField: '_id', // 要连接的集合中的字段
- as: 'userDetails' // 连接后结果存储在新字段 userDetails 中
- }
- },
- // 展开 userDetails 数组,以便将用户信息提升到顶层
- { $unwind: '$userDetails' },
- // 调整输出格式,只保留需要的字段
- { $project: { _id: 1, user: '$_id', count: 1, username: '$userDetails.username', name: '$userDetails.name' } },
- // 限制返回的记录数量
- { $limit: 40 }
- ]);
- let designersXml = [];
- designers.forEach(e => {
- designersXml = designersXml.concat([
- ' <url>',
- ` <loc>https://art.pcoloring.com/en/artist/${e._id}</loc>`,
- ` <lastmod>${date}</lastmod>`,
- ' </url>',
- ])
- });
- console.log(designersXml);
- // details
- let detailsXml = [];
- const cursor = await models.Art
- .find({ open: true, status: 9000 })
- .select('name title')
- .sort({ publishTime: -1 }).cursor(); // 使用cursor,避免一次查询太多记录内存受不了
- // 遍历游标中的每个文档
- for await (const doc of cursor) {
- let uriTitle = doc.name;
- if (doc.title) {
- try {
- let titleJson = JSON.parse(doc.title);
- if (titleJson.en) uriTitle = titleJson.en; // URL 里还是尽量用英文title
- } catch (e) {
- console.error(e.message);
- }
- }
- let utf8name = encodeURIComponent(uriTitle.replace(/[\s_]+/g, '-')).toLowerCase();
- detailsXml = detailsXml.concat([
- ' <url>',
- ` <loc>https://art.pcoloring.com/en/coloring-page/${utf8name}-${doc._id}</loc>`,
- ` <lastmod>${date}</lastmod>`,
- ' </url>',
- ]);
- console.log(`process detail ${doc._id} url done`);
- }
- let endXml = ['</urlset>'];
- let sitemapXml = [...commonXml, ...categoriesXml, ...tagsXml, ...albumsXml, ...designersXml, ...detailsXml, ...endXml];
- let sitemapXmlStr = sitemapXml.join('\n');
- fs.writeFileSync(sitemapTempPath, sitemapXmlStr); // 先写入临时文件
- fs.renameSync(sitemapTempPath, sitemapPath); // 再重命名
- console.log('生成sitemap成功');
- }
- function run() {
- generateSitemap();
- }
- module.exports = { run }
- if (require.main == module) {
- run();
- }
|