Skip to content

Commit d59c3ee

Browse files
authored
feat(route): add claude blog route (#21348)
* feat(route/claude): Add claude.ai blog rss Made-with: Cursor * fix maintainer
1 parent 09a2886 commit d59c3ee

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

lib/routes/claude/blog.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { load } from 'cheerio';
2+
import pMap from 'p-map';
3+
4+
import type { DataItem, Route } from '@/types';
5+
import cache from '@/utils/cache';
6+
import ofetch from '@/utils/ofetch';
7+
import { parseDate } from '@/utils/parse-date';
8+
9+
const baseUrl = 'https://claude.com';
10+
11+
export const route: Route = {
12+
path: '/blog',
13+
categories: ['programming'],
14+
example: '/claude/blog',
15+
parameters: {},
16+
features: {
17+
requireConfig: false,
18+
requirePuppeteer: false,
19+
antiCrawler: false,
20+
supportBT: false,
21+
supportPodcast: false,
22+
supportScihub: false,
23+
},
24+
radar: [
25+
{
26+
source: ['claude.com/blog'],
27+
target: '/blog',
28+
},
29+
],
30+
name: 'Blog',
31+
maintainers: ['zhenlohuang'],
32+
handler,
33+
url: 'claude.com/blog',
34+
};
35+
36+
async function handler(ctx) {
37+
const link = `${baseUrl}/blog`;
38+
const response = await ofetch(link);
39+
const $ = load(response);
40+
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 15;
41+
42+
const list: DataItem[] = $('.blog_cms_list article.card_blog_list_wrap')
43+
.toArray()
44+
.slice(0, limit)
45+
.map((el) => {
46+
const $el = $(el);
47+
const title = $el.find('.card_blog_list_title').text().trim();
48+
const href = $el.find('a.clickable_link').attr('href') ?? '';
49+
const pubDateText = $el.find('[fs-list-fieldtype="date"][fs-list-field="date"]').text().trim();
50+
const category = $el
51+
.find('[fs-list-field="category"]')
52+
.toArray()
53+
.map((c) => $(c).text().trim())
54+
.filter(Boolean);
55+
56+
return {
57+
title,
58+
link: href.startsWith('http') ? href : `${baseUrl}${href}`,
59+
pubDate: pubDateText ? parseDate(pubDateText) : undefined,
60+
category,
61+
};
62+
});
63+
64+
const items = await pMap(
65+
list,
66+
(item) =>
67+
cache.tryGet(item.link!, async () => {
68+
const response = await ofetch(item.link!);
69+
const $ = load(response);
70+
71+
const content = $('.blog_post_content_wrap');
72+
73+
content.find('style, script').remove();
74+
75+
item.description = content.html() ?? undefined;
76+
77+
return item;
78+
}),
79+
{ concurrency: 3 }
80+
);
81+
82+
return {
83+
title: 'Claude Blog',
84+
link,
85+
description: 'Product news and best practices for teams building with Claude.',
86+
language: 'en',
87+
item: items,
88+
};
89+
}

0 commit comments

Comments
 (0)