feat: add an router for getting all collections of a user in zhihu.com. (#18028)
* 添加知乎路由,用于获取指定用户所有公开的收藏内容 * 修改example地址 * 修改代码以符合路由规范 * Update lib/routes/zhihu/all-collections.ts Co-authored-by: Tony <TonyRL@users.noreply.github.com> * 修改代码以符合路由规范和代码审阅者要求的got请求代码格式统一和re-cast的问题 --------- Co-authored-by: yuerongkang <yuerongkang@drivedream.com>
This commit is contained in:
parent
1e246f25a4
commit
c405ee80ee
|
|
@ -0,0 +1,109 @@
|
|||
import { Route, ViewType, Collection, CollectionItem } from '@/types';
|
||||
import got from '@/utils/got';
|
||||
import { header } from './utils';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
import cache from '@/utils/cache';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/people/allCollections/:id',
|
||||
categories: ['social-media'],
|
||||
view: ViewType.Articles,
|
||||
example: '/zhihu/people/allCollections/87-44-49-67',
|
||||
parameters: { id: '作者 id,可在用户主页 URL 中找到' },
|
||||
features: {
|
||||
requireConfig: false,
|
||||
requirePuppeteer: false,
|
||||
antiCrawler: true,
|
||||
supportBT: false,
|
||||
supportPodcast: false,
|
||||
supportScihub: false,
|
||||
},
|
||||
radar: [
|
||||
{
|
||||
source: ['www.zhihu.com/people/:id'],
|
||||
// target: 'people/allCollections/:id',
|
||||
},
|
||||
],
|
||||
name: '用户全部收藏内容',
|
||||
maintainers: ['Healthyyue'],
|
||||
handler,
|
||||
};
|
||||
|
||||
async function handler(ctx) {
|
||||
const id = ctx.req.param('id');
|
||||
const apiPath = `https://api.zhihu.com/people/${id}/collections`;
|
||||
|
||||
const response = await got(apiPath, {
|
||||
headers: {
|
||||
Referer: `https://www.zhihu.com/people/${id}/collections`,
|
||||
},
|
||||
});
|
||||
|
||||
const collections = response.data.data as Collection[];
|
||||
|
||||
const allCollectionItems = await Promise.all(
|
||||
collections.map(async (collection) => {
|
||||
const firstPageResponse = await got(`https://www.zhihu.com/api/v4/collections/${collection.id}/items?offset=0&limit=20`, {
|
||||
headers: {
|
||||
...header,
|
||||
Referer: `https://www.zhihu.com/collection/${collection.id}`,
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
data: items,
|
||||
paging: { totals },
|
||||
} = firstPageResponse.data;
|
||||
|
||||
if (totals > 20) {
|
||||
const offsetList = Array.from({ length: Math.ceil(totals / 20) - 1 }, (_, index) => (index + 1) * 20);
|
||||
|
||||
const otherPages = await Promise.all(
|
||||
offsetList.map((offset) =>
|
||||
cache.tryGet(`https://www.zhihu.com/api/v4/collections/${collection.id}/items?offset=${offset}&limit=20`, async () => {
|
||||
const response = await got(`https://www.zhihu.com/api/v4/collections/${collection.id}/items?offset=${offset}&limit=20`, {
|
||||
headers: {
|
||||
...header,
|
||||
Referer: `https://www.zhihu.com/collection/${collection.id}`,
|
||||
},
|
||||
});
|
||||
return response.data.data;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
items.push(...otherPages.flat());
|
||||
}
|
||||
|
||||
return {
|
||||
collectionId: collection.id,
|
||||
collectionTitle: collection.title,
|
||||
items,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
const items = allCollectionItems.flatMap(
|
||||
(collection) =>
|
||||
collection.items.map((item) => ({
|
||||
...item,
|
||||
collectionTitle: collection.collectionTitle,
|
||||
})) as CollectionItem[]
|
||||
);
|
||||
|
||||
return {
|
||||
title: `${collections[0].creator.name}的知乎收藏`,
|
||||
link: `https://www.zhihu.com/people/${id}/collections`,
|
||||
item: items.map((item) => {
|
||||
const content = item.content;
|
||||
|
||||
return {
|
||||
title: content.type === 'article' || content.type === 'zvideo' ? content.title : content.question.title,
|
||||
link: content.url,
|
||||
description: content.type === 'zvideo' ? `<img src=${content.video.url}/>` : content.content,
|
||||
pubDate: parseDate((content.type === 'article' ? content.updated : content.updated_time) * 1000),
|
||||
category: [item.collectionTitle],
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
|
@ -102,3 +102,29 @@ export interface Articles {
|
|||
};
|
||||
data: Article[];
|
||||
}
|
||||
|
||||
export interface CollectionItem {
|
||||
content: {
|
||||
type: string;
|
||||
title?: string;
|
||||
question?: {
|
||||
title: string;
|
||||
};
|
||||
url: string;
|
||||
content: string;
|
||||
video?: {
|
||||
url: string;
|
||||
};
|
||||
updated?: number;
|
||||
updated_time?: number;
|
||||
};
|
||||
collectionTitle?: string;
|
||||
}
|
||||
|
||||
export interface Collection {
|
||||
id: string;
|
||||
title: string;
|
||||
creator: {
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue