Skip to content

Commit

Permalink
feat(route): 微博自定义分组(使用Cookie) (DIYgod#12514)
Browse files Browse the repository at this point in the history
* change route 'weibo/user' to fit api could be opened with Share(third-party android weibo clent)

* update weibo group route using cookies approach

* fix typo

* code optimization for /weibo/group; docs for /weibo/group

* try fix ESLint error

* fix typo and code optimization

* fix missing ','

* '/weibo/group' throw error when the cookie is not set
  • Loading branch information
monologconnor authored May 15, 2023
1 parent 9bdba06 commit 2bd8e48
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
.vercel
.vscode
.yarn
.yarnrc.yml
.pnp*

*.swp
*.iml
Expand Down
8 changes: 8 additions & 0 deletions docs/install/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,14 @@ RSSHub 支持使用访问密钥 / 码,白名单和黑名单三种方式进行
- `WEIBO_APP_SECRET`: 微博 App Secret
- `WEIBO_REDIRECT_URL`: 微博登录授权回调地址,默认为 `RSSHub 地址/weibo/timeline/0`,自定义回调地址请确保最后可以转跳到 `RSSHub 地址/weibo/timeline/0?code=xxx`
- 微博 自定义分组
- `WEIBO_COOKIES`: 用户访问网页微博时所使用的cookie, 获取方式:
1. 打开并登录 <https://m.weibo.cn> (确保打开页面为手机版, 如果强制跳转电脑端可尝试使用可更改UserAgent的浏览器插件)
2. 按下`F12`打开控制台,切换至`Network(网络)`面板
3. 在该网页切换至任意关注分组, 并在面板打开最先捕获到的请求(该情形下捕获到的请求路径应包含`/feed/group`)
4. 查看该请求的`Headers(请求头)`, 找到`Cookie`字段并复制内容
- 小宇宙:需要 App 登陆后抓包获取相应数据。
- `XIAOYUZHOU_ID`: 即数据包中的 `x-jike-device-id`。
Expand Down
16 changes: 16 additions & 0 deletions docs/social-media.md
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,22 @@ rule

</Route>

### 自定义分组

<Route author="monologconnor" example="/weibo/group/4541216424989965/微博分组/:routeParams?" path="/weibo/group/:gid/:gname?/:routeParams?" :paramsDesc="['分组id, 在网页版分组地址栏末尾`?gid=`处获取', '分组显示名称; 默认为: `微博分组`', '额外参数;请参阅上面的说明和表格']" anticrawler="1" selfhost="1">

::: warning 注意

由于微博官方未提供自定义分组相关api, 此方案必须使用用户`Cookie`进行抓取

因微博cookies的过期与更新方案未经验证, 部署一次Cookie的有效时长未知

微博用户Cookie的配置可参照部署文档

:::

</Route>

## 微博绿洲

### 用户
Expand Down
1 change: 1 addition & 0 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ const calculateValue = () => {
weibo: {
app_key: envs.WEIBO_APP_KEY,
app_secret: envs.WEIBO_APP_SECRET,
cookies: envs.WEIBO_COOKIES,
redirect_url: envs.WEIBO_REDIRECT_URL,
},
wenku8: {
Expand Down
99 changes: 99 additions & 0 deletions lib/v2/weibo/group.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
const querystring = require('querystring');
const got = require('@/utils/got');
const config = require('@/config').value;
const weiboUtils = require('./utils');
const { fallback, queryToBoolean } = require('@/utils/readable-social');

module.exports = async (ctx) => {
if (!config.weibo_cookies) {
throw 'Weibo Group Timeline is not available due to the absense of [Weibo Cookies]. Check <a href="https://docs.rsshub.app/install/#pei-zhi-bu-fen-rss-mo-kuai-pei-zhi">relevant config tutorial</a>';
}

const gid = ctx.params.gid;
const groupName = ctx.params.gname || '微博分组';
let displayVideo = '1';
let displayArticle = '0';
let displayComments = '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';
displayComments = fallback(undefined, queryToBoolean(routeParams.displayComments), false) ? '1' : '0';
}
}

const responseData = await ctx.cache.tryGet(
`weibo:group:index:${gid}`,
async() => {
const _r = await got({
method: 'get',
url: `https://m.weibo.cn/feed/group?gid=${gid}`,
headers: {
Referer: `https://m.weibo.cn/`,
'MWeibo-Pwa': 1,
'X-Requested-With': 'XMLHttpRequest',
'Cookie': config.weibo.cookies,
}
});
return _r.data.data;
},
config.cache.routeExpire,
false
);

const resultItems = await Promise.all(
responseData.statuses.map(async (item) => {
const retweet = item.retweeted_status;
if (retweet && retweet.isLongText) {
const retweetData = await ctx.cache.tryGet(`weibo:retweeted:${retweet.user.id}:${retweet.bid}`, () => weiboUtils.getShowData(retweet.user.id, retweet.bid));
if (retweetData !== undefined && retweetData.text) {
item.retweeted_status.text = retweetData.text;
}
}

const link = `https://m.weibo.cn/status/${item.bid}`;
const formatExtended = weiboUtils.formatExtended(ctx, item);
let description = formatExtended.description;
const title = formatExtended.title;
const pubDate = item.created_at;

if (displayVideo === '1') {
if (item.retweeted_status) {
description = weiboUtils.formatVideo(description, item.retweeted_status);
} else {
description = weiboUtils.formatVideo(description, item);
}
}

if (displayComments === '1') {
description = await weiboUtils.formatComments(ctx, description, item);
}

if (displayArticle === '1') {
if (item.retweeted_status) {
description = await weiboUtils.formatArticle(ctx, description, item.retweeted_status);
} else {
description = await weiboUtils.formatArticle(ctx, description, item);
}
}

return {
title,
description,
link,
pubDate,
author: item.user.screen_name
};
})
);

ctx.state.data = weiboUtils.sinaimgTvax({
title: groupName,
link: `https://weibo.com/mygroups?gid=${gid}`,
description: '微博自定义分组',
item: resultItems,
});
};
1 change: 1 addition & 0 deletions lib/v2/weibo/maintainer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = {
'/group/:gid/:gname?/:routeParams?': ['monologconnor'],
'/keyword/:keyword/:routeParams?': ['DIYgod'],
'/oasis/user/:userid': ['kt286'],
'/search/hot': ['xyqfer'],
Expand Down
1 change: 1 addition & 0 deletions lib/v2/weibo/router.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = (router) => {
router.get('/group/:gid/:gname?/:routeParams?', require('./group'));
router.get('/keyword/:keyword/:routeParams?', require('./keyword'));
router.get('/oasis/user/:userid', require('./oasis/user'));
router.get('/search/hot', require('./search/hot'));
Expand Down
2 changes: 1 addition & 1 deletion lib/v2/weibo/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ module.exports = async (ctx) => {
}
}

const link = `https://weibo.com/${uid}/${item.mblog.bid}`;
const link = `https://m.weibo.cn/status/${item.mblog.bid}`;
const formatExtended = weiboUtils.formatExtended(ctx, item.mblog);
let description = formatExtended.description;
const title = formatExtended.title;
Expand Down

0 comments on commit 2bd8e48

Please sign in to comment.