feat(route)(weibo): display article (#9195)
Signed-off-by: Rongrong <15956627+Rongronggg9@users.noreply.github.com>
This commit is contained in:
parent
5324eefdad
commit
9610d66d1b
|
|
@ -1131,7 +1131,7 @@ rule
|
|||
对于微博内容,在 `routeParams` 参数中以 query string 格式指定选项,可以控制输出的样式
|
||||
|
||||
| 键 | 含义 | 接受的值 | 默认值 |
|
||||
| -------------------------- | --------------------------------- | -------------- | ------------------------------- |
|
||||
|----------------------------|-----------------------------------|----------------|---------------------------------|
|
||||
| readable | 是否开启细节排版可读性优化 | 0/1/true/false | false |
|
||||
| authorNameBold | 是否加粗作者名字 | 0/1/true/false | false |
|
||||
| showAuthorInTitle | 是否在标题处显示作者 | 0/1/true/false | false(`/weibo/keyword/`中为 true) |
|
||||
|
|
@ -1144,7 +1144,8 @@ rule
|
|||
| widthOfPics | 微博配图宽(生效取决于阅读器) | 不指定 / 数字 | 不指定 |
|
||||
| heightOfPics | 微博配图高(生效取决于阅读器) | 不指定 / 数字 | 不指定 |
|
||||
| sizeOfAuthorAvatar | 作者头像大小 | 数字 | 48 |
|
||||
| displayVideo | 是否直接显示微博视频,只在博主 RSS 中有效 | 0/1/true/false | true |
|
||||
| displayVideo | 是否直接显示微博视频,只在博主或个人时间线 RSS 中有效 | 0/1/true/false | true |
|
||||
| displayArticle | 是否直接显示微博文章,只在博主或个人时间线 RSS 中有效 | 0/1/true/false | false |
|
||||
| showEmojiInDescription | 是否展示正文中的 emoji 表情 | 0/1/true/false | true |
|
||||
|
||||
指定更多与默认值不同的参数选项可以改善 RSS 的可读性,如
|
||||
|
|
|
|||
|
|
@ -11,12 +11,14 @@ module.exports = async (ctx) => {
|
|||
const routeParams = ctx.params.routeParams || undefined;
|
||||
const token = await ctx.cache.get('weibotimelineuid' + uid, false);
|
||||
let displayVideo = '1';
|
||||
let displayArticle = '0';
|
||||
if (routeParams) {
|
||||
if (routeParams === '1' || routeParams === '0') {
|
||||
displayVideo = routeParams;
|
||||
} else {
|
||||
const routeParams = querystring.parse(ctx.params.routeParams);
|
||||
displayVideo = fallback(undefined, queryToBoolean(routeParams.displayVideo), true) ? '1' : '0';
|
||||
displayArticle = fallback(undefined, queryToBoolean(routeParams.displayArticle), false) ? '1' : '0';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -79,6 +81,11 @@ module.exports = async (ctx) => {
|
|||
description = weiboUtils.formatVideo(description, item);
|
||||
}
|
||||
|
||||
// 文章的处理
|
||||
if (displayArticle === '1') {
|
||||
description = await weiboUtils.formatArticle(ctx, description, item);
|
||||
}
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
|
|
|
|||
|
|
@ -8,12 +8,14 @@ const { fallback, queryToBoolean } = require('@/utils/readable-social');
|
|||
module.exports = async (ctx) => {
|
||||
const uid = ctx.params.uid;
|
||||
let displayVideo = '1';
|
||||
let displayArticle = '0';
|
||||
if (ctx.params.routeParams) {
|
||||
if (ctx.params.routeParams === '1' || ctx.params.routeParams === '0') {
|
||||
displayVideo = ctx.params.routeParams;
|
||||
} else {
|
||||
const routeParams = querystring.parse(ctx.params.routeParams);
|
||||
displayVideo = fallback(undefined, queryToBoolean(routeParams.displayVideo), true) ? '1' : '0';
|
||||
displayArticle = fallback(undefined, queryToBoolean(routeParams.displayArticle), false) ? '1' : '0';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,6 +103,11 @@ module.exports = async (ctx) => {
|
|||
description = weiboUtils.formatVideo(description, item.mblog);
|
||||
}
|
||||
|
||||
// 文章的处理
|
||||
if (displayArticle === '1') {
|
||||
description = await weiboUtils.formatArticle(ctx, description, item.mblog);
|
||||
}
|
||||
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const querystring = require('querystring');
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { fallback, queryToBoolean, queryToInteger } = require('@/utils/readable-social');
|
||||
|
||||
const weiboUtils = {
|
||||
|
|
@ -260,6 +261,92 @@ const weiboUtils = {
|
|||
}
|
||||
return itemDesc;
|
||||
},
|
||||
formatArticle: async (ctx, itemDesc, status) => {
|
||||
const pageInfo = status.page_info;
|
||||
if (pageInfo && pageInfo.type === 'article' && pageInfo.page_url) {
|
||||
const pageUrl = pageInfo.page_url;
|
||||
const articleIdMatch = pageUrl.match(/id=(\d+)/);
|
||||
if (!articleIdMatch) {
|
||||
return itemDesc;
|
||||
}
|
||||
const articleId = articleIdMatch[1];
|
||||
const link = `https://card.weibo.com/article/m/aj/detail?id=${articleId}`;
|
||||
const response = await ctx.cache.tryGet(link, async () => {
|
||||
const _response = await got.get(link, {
|
||||
headers: {
|
||||
Referer: `https://card.weibo.com/article/m/show/id/${articleId}`,
|
||||
'MWeibo-Pwa': 1,
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
|
||||
},
|
||||
});
|
||||
return _response.data;
|
||||
}); // cache it!
|
||||
const article = response.data;
|
||||
if (article && article.title && article.content) {
|
||||
const title = article.title;
|
||||
const content = article.content;
|
||||
const summary = article.summary;
|
||||
const createAt = article.create_at;
|
||||
const readCount = article.read_count;
|
||||
const isOriginal = article.is_original;
|
||||
const isArticleNonFree = article.is_article_free; // 微博起错了字段名,它为 1 时才是收费文章
|
||||
|
||||
let html = '<br clear="both" /><br clear="both" />';
|
||||
html += '<div style="clear: both"></div><div style="background: #60606010;border:1px solid #80808030;margin:0;padding:3% 7%;overflow-wrap: break-word">';
|
||||
|
||||
html += `<h1 style="font-size: 1.5rem;line-height: 1.25;color: #333;">${title}</h1>`; // 加入标题
|
||||
|
||||
// 加入文章信息
|
||||
const iconStyle =
|
||||
'display: inline-block;margin-inline: 0.25rem;width: 2.25rem; height: 1.125rem; background: #e7e7e7; border-radius: 2px; box-sizing: border-box; text-align: center; line-height: 1.0625rem; font-size: 0.75rem; color: #aaa;';
|
||||
let articleMeta = '<p style="line-height: 1.66; color: #999;margin: 0 0 0.75rem;font-size: 0.75rem;padding: 0">';
|
||||
if (isArticleNonFree) {
|
||||
articleMeta += `<span style="${iconStyle}">试读</span> `;
|
||||
}
|
||||
if (isOriginal) {
|
||||
articleMeta += `<span style="${iconStyle}">原创</span> `;
|
||||
}
|
||||
articleMeta += `<span style="margin-inline: 0.25rem;">发布时间: ${createAt}</span> `; // 发布时间
|
||||
articleMeta += `<span style="margin-inline: 0.25rem;">阅读量: ${readCount}</span> `; // 阅读量
|
||||
articleMeta += '</p>';
|
||||
html += articleMeta;
|
||||
|
||||
if (summary) {
|
||||
html += `<p style="color: #999;line-height: 1.5rem;padding: 0.0625rem 0 0.875rem;margin: 0">${summary}</p>`; // 摘要
|
||||
}
|
||||
|
||||
html += '<div style="height: 0;border-bottom: 1px dashed #999;margin-bottom: 0.75rem;"></div>'; // 分割线
|
||||
|
||||
// 正文处理,加入一些在微博文章页的 CSS 中定义的不可或缺的样式
|
||||
const $ = cheerio.load(content);
|
||||
$('p').each((_, elem) => {
|
||||
elem = $(elem);
|
||||
let style = elem.attr('style') || '';
|
||||
style = 'margin: 0;padding: 0;border: 0;' + style;
|
||||
elem.attr('style', style);
|
||||
});
|
||||
$('.image').each((_, elem) => {
|
||||
elem = $(elem);
|
||||
let style = elem.attr('style') || '';
|
||||
style = 'display: table;text-align: center;margin-left: auto;margin-right: auto;clear: both;min-width: 50px;' + style;
|
||||
elem.attr('style', style);
|
||||
});
|
||||
$('img').each((_, elem) => {
|
||||
elem = $(elem);
|
||||
let style = elem.attr('style') || '';
|
||||
style = 'display: block;max-width: 100%;margin-left: auto;margin-right: auto;min-width: 50px;' + style;
|
||||
elem.attr('style', style);
|
||||
});
|
||||
const contentHtml = $.html();
|
||||
html += `<div style="line-height: 1.59;text-align: justify;font-size: 1.0625rem;color: #333;">${contentHtml}</div>`; // 正文
|
||||
|
||||
html += '</div>';
|
||||
itemDesc += html;
|
||||
}
|
||||
}
|
||||
return itemDesc;
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = weiboUtils;
|
||||
|
|
|
|||
Loading…
Reference in New Issue