mirror of
https://github.com/DIYgod/RSSHub.git
synced 2025-12-02 10:08:02 +08:00
fix(route): Hacker News (#8420)
This commit is contained in:
@@ -137,26 +137,21 @@ For instance, the `/github/topics/framework/l=php&o=desc&s=stars` route will gen
|
||||
|
||||
### Section
|
||||
|
||||
<RouteEn author="cf020031308" example="/hackernews/best/comments" path="/hackernews/:section/:type?" :paramsDesc="['Section', 'Link type']">
|
||||
<RouteEn author="cf020031308 nczitzk" example="/hackernews" path="/hackernews/:section?/:type?" :paramsDesc="['Section, see below, index by default', 'Link, see below, sources by default']">
|
||||
|
||||
Website: https://news.ycombinator.com/
|
||||
Section
|
||||
|
||||
| Section | section |
|
||||
| ------- | ----------------------------------- |
|
||||
| index | https://news.ycombinator.com/ |
|
||||
| new | https://news.ycombinator.com/newest |
|
||||
| past | https://news.ycombinator.com/front |
|
||||
| ask | https://news.ycombinator.com/ask |
|
||||
| show | https://news.ycombinator.com/show |
|
||||
| jobs | https://news.ycombinator.com/jobs |
|
||||
| best | https://news.ycombinator.com/best |
|
||||
| homepage | new | past | comments | ask | show | jobs | best |
|
||||
| ------------------------------------- | --------------------------------------------- | ------------------------------------------- | ------------------------------------------------------- | --------------------------------------- | ----------------------------------------- | ----------------------------------------- | ----------------------------------------- |
|
||||
| [index](https://news.ycombinator.com) | [newest](https://news.ycombinator.com/newest) | [front](https://news.ycombinator.com/front) | [newcomments](https://news.ycombinator.com/newcomments) | [ask](https://news.ycombinator.com/ask) | [show](https://news.ycombinator.com/show) | [jobs](https://news.ycombinator.com/jobs) | [best](https://news.ycombinator.com/best) |
|
||||
|
||||
> Official RSS:https://news.ycombinator.com/rss is same as `index` section
|
||||
Items link to
|
||||
|
||||
| Link type | type |
|
||||
| --------- | ------------------------------ |
|
||||
| story | Deault, link to shared address |
|
||||
| comments | Link to Hacker News address |
|
||||
| Source addresses shared by users | Comments on Hacker News |
|
||||
| -------------------------------- | ----------------------- |
|
||||
| sources | comments |
|
||||
|
||||
> Default RSS by the website: <https://news.ycombinator.com/rss>, same as `index` section, should be the first choice.
|
||||
|
||||
</RouteEn>
|
||||
|
||||
|
||||
@@ -219,28 +219,23 @@ GitHub 官方也提供了一些 RSS:
|
||||
|
||||
## Hacker News
|
||||
|
||||
### 分类
|
||||
### 分区
|
||||
|
||||
<Route author="cf020031308" example="/hackernews/best/comments" path="/hackernews/:section/:type?" :paramsDesc="['内容分区', '链接类型(可不填)']">
|
||||
<Route author="cf020031308 nczitzk" example="/hackernews" path="/hackernews/:section?/:type?" :paramsDesc="['内容分区,见下表,默认为 index', '链接类型,见下表,默认为 sources']">
|
||||
|
||||
网站地址:<https://news.ycombinator.com/>
|
||||
内容分区
|
||||
|
||||
| 内容分区 | section |
|
||||
| -------- | ------------------------------------- |
|
||||
| index | <https://news.ycombinator.com/> |
|
||||
| new | <https://news.ycombinator.com/newest> |
|
||||
| past | <https://news.ycombinator.com/front> |
|
||||
| ask | <https://news.ycombinator.com/ask> |
|
||||
| show | <https://news.ycombinator.com/show> |
|
||||
| jobs | <https://news.ycombinator.com/jobs> |
|
||||
| best | <https://news.ycombinator.com/best> |
|
||||
| homepage | new | past | comments | ask | show | jobs | best |
|
||||
| ------------------------------------- | --------------------------------------------- | ------------------------------------------- | ------------------------------------------------------- | --------------------------------------- | ----------------------------------------- | ----------------------------------------- | ----------------------------------------- |
|
||||
| [index](https://news.ycombinator.com) | [newest](https://news.ycombinator.com/newest) | [front](https://news.ycombinator.com/front) | [newcomments](https://news.ycombinator.com/newcomments) | [ask](https://news.ycombinator.com/ask) | [show](https://news.ycombinator.com/show) | [jobs](https://news.ycombinator.com/jobs) | [best](https://news.ycombinator.com/best) |
|
||||
|
||||
> 网站有默认的 RSS:<https://news.ycombinator.com/rss> 内容同 index,应优先考虑
|
||||
条目指向链接类型
|
||||
|
||||
| 链接类型 | type |
|
||||
| -------- | ----------------------------- |
|
||||
| story | 默认值,链向用户分享的地址 |
|
||||
| comments | 链向 Hacker News 上的讨论页面 |
|
||||
| 用户分享的来源地址 | Hacker News 上的讨论页面 |
|
||||
| ------------------ | ------------------------ |
|
||||
| sources | comments |
|
||||
|
||||
> 网站有默认的 RSS:<https://news.ycombinator.com/rss> 内容同 homepage,应优先考虑。
|
||||
|
||||
</Route>
|
||||
|
||||
|
||||
@@ -1434,7 +1434,7 @@ router.get('/aisixiang/ranking/:type?/:range?', lazyloadRouteHandler('./routes/a
|
||||
router.get('/aisixiang/thinktank/:name/:type?', lazyloadRouteHandler('./routes/aisixiang/thinktank'));
|
||||
|
||||
// Hacker News
|
||||
router.get('/hackernews/:section/:type?', lazyloadRouteHandler('./routes/hackernews/story'));
|
||||
// router.get('/hackernews/:section/:type?', lazyloadRouteHandler('./routes/hackernews/story'));
|
||||
|
||||
// LeetCode
|
||||
router.get('/leetcode/articles', lazyloadRouteHandler('./routes/leetcode/articles'));
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
|
||||
const host = 'https://news.ycombinator.com';
|
||||
const paths = {
|
||||
index: '/',
|
||||
new: '/newest',
|
||||
past: '/front',
|
||||
ask: '/ask',
|
||||
show: '/show',
|
||||
jobs: '/jobs',
|
||||
best: '/best',
|
||||
};
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const section = ctx.params.section;
|
||||
const showStory = ctx.params.type !== 'comments';
|
||||
const path = paths[section];
|
||||
const url = `${host}${path}`;
|
||||
const response = await got.get(url);
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const items = $('a.storylink')
|
||||
.map(function () {
|
||||
return {
|
||||
title: $(this).text(),
|
||||
link: $(this).attr('href'),
|
||||
author: 'Hacker News',
|
||||
description: '',
|
||||
};
|
||||
})
|
||||
.get();
|
||||
|
||||
$('a.hnuser').each(function (i) {
|
||||
items[i].author = $(this).text();
|
||||
});
|
||||
|
||||
$('tr.athing').each(function (i) {
|
||||
const commURL = `${host}/item?id=` + $(this).attr('id');
|
||||
const item = items[i];
|
||||
|
||||
if (showStory) {
|
||||
item.description = `Comments: <a href="${commURL}"> ${commURL} </a>`;
|
||||
} else {
|
||||
item.description = `Link: <a href="${item.link}"> ${item.title} </a>`;
|
||||
item.link = commURL;
|
||||
}
|
||||
});
|
||||
|
||||
let title = `Hacker News: ${section}`;
|
||||
if (!showStory) {
|
||||
title += '/comments';
|
||||
}
|
||||
|
||||
ctx.state.data = {
|
||||
title,
|
||||
link: url,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
97
lib/v2/hackernews/index.js
Normal file
97
lib/v2/hackernews/index.js
Normal file
@@ -0,0 +1,97 @@
|
||||
const got = require('@/utils/got');
|
||||
const cheerio = require('cheerio');
|
||||
const { parseDate } = require('@/utils/parse-date');
|
||||
|
||||
module.exports = async (ctx) => {
|
||||
const section = ctx.params.section ?? 'index';
|
||||
const type = ctx.params.type ?? 'sources';
|
||||
|
||||
const rootUrl = 'https://news.ycombinator.com';
|
||||
const currentUrl = `${rootUrl}${section === 'index' ? '' : `/${section}`}`;
|
||||
|
||||
const response = await got({
|
||||
method: 'get',
|
||||
url: currentUrl,
|
||||
});
|
||||
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
const list = $('.athing')
|
||||
.slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 30)
|
||||
.map((_, thing) => {
|
||||
thing = $(thing);
|
||||
|
||||
const item = {};
|
||||
|
||||
item.guid = thing.attr('id');
|
||||
item.title = thing.find('.titlelink').text();
|
||||
item.category = thing.find('.sitestr').text();
|
||||
item.author = thing.next().find('.hnuser').text();
|
||||
item.pubDate = parseDate(thing.next().attr('title'));
|
||||
|
||||
item.link = `${rootUrl}/item?id=${item.guid}`;
|
||||
item.origin = thing.find('.titlelink').attr('href');
|
||||
|
||||
item.comments = thing.next().find('a').last().text().split(' comment')[0];
|
||||
item.guid = type === 'sources' ? item.guid : `${item.guid}${item.comments === 'discuss' ? '' : `-${item.comments}`}`;
|
||||
|
||||
item.description = `<a href="${item.link}">Comments on Hacker News</a> | <a href="${item.origin}">Source</a>`;
|
||||
|
||||
return item;
|
||||
})
|
||||
.get();
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
ctx.cache.tryGet(item.guid, async () => {
|
||||
if (item.comments !== 'discuss' && type !== 'sources') {
|
||||
const detailResponse = await got({
|
||||
method: 'get',
|
||||
url: item.link,
|
||||
});
|
||||
|
||||
const content = cheerio.load(detailResponse.data);
|
||||
|
||||
content('.reply').remove();
|
||||
|
||||
item.description = '';
|
||||
|
||||
content('.comtr').each(function () {
|
||||
const author = content(this).find('.hnuser');
|
||||
const comment = content(this).find('.commtext');
|
||||
|
||||
item.description +=
|
||||
`<div><div><small><a href="${rootUrl}/${author.attr('href')}">${author.text()}</a></small>` +
|
||||
`  <small><a href="${rootUrl}/item?id=${content(this).attr('id')}">` +
|
||||
`${content(this).find('.age').attr('title')}</a></small></div>`;
|
||||
|
||||
const commentText = comment.clone();
|
||||
|
||||
commentText.find('p').remove();
|
||||
commentText.html(`<p>${commentText.text()}</p>`);
|
||||
commentText.append(
|
||||
comment
|
||||
.find('p')
|
||||
.toArray()
|
||||
.map((p) => `<p>${content(p).html()}</p>`)
|
||||
);
|
||||
|
||||
item.description += `<div>${commentText.html()}</div></div>`;
|
||||
});
|
||||
}
|
||||
|
||||
item.link = type === 'sources' ? item.origin : item.link;
|
||||
|
||||
delete item.origin;
|
||||
|
||||
return item;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
ctx.state.data = {
|
||||
title: $('title').text(),
|
||||
link: currentUrl,
|
||||
item: items,
|
||||
};
|
||||
};
|
||||
3
lib/v2/hackernews/maintainer.js
Normal file
3
lib/v2/hackernews/maintainer.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
'/:section?/:type?': ['nczitzk'],
|
||||
};
|
||||
13
lib/v2/hackernews/radar.js
Normal file
13
lib/v2/hackernews/radar.js
Normal file
@@ -0,0 +1,13 @@
|
||||
module.exports = {
|
||||
'ycombinator.com': {
|
||||
_name: 'Hacker News',
|
||||
'.': [
|
||||
{
|
||||
title: 'Section',
|
||||
docs: 'https://docs.rsshub.app/programming.html#hacker-news',
|
||||
source: ['/:section', '/'],
|
||||
target: '/hackernews/:section?/:type?',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
3
lib/v2/hackernews/router.js
Normal file
3
lib/v2/hackernews/router.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = function (router) {
|
||||
router.get('/:section?/:type?', require('./index'));
|
||||
};
|
||||
Reference in New Issue
Block a user