newsnow 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -0
- package/dist/src/cli.js +104 -0
- package/dist/src/crypto.js +11 -0
- package/dist/src/fetch.js +36 -0
- package/dist/src/rss.js +25 -0
- package/dist/src/sources/_36kr.js +66 -0
- package/dist/src/sources/baidu.js +13 -0
- package/dist/src/sources/bilibili.js +52 -0
- package/dist/src/sources/cankaoxiaoxi.js +12 -0
- package/dist/src/sources/chongbuluo.js +28 -0
- package/dist/src/sources/cls/index.js +46 -0
- package/dist/src/sources/cls/utils.js +12 -0
- package/dist/src/sources/coolapk/index.js +44 -0
- package/dist/src/sources/douban.js +20 -0
- package/dist/src/sources/douyin.js +14 -0
- package/dist/src/sources/fastbull.js +52 -0
- package/dist/src/sources/freebuf.js +44 -0
- package/dist/src/sources/gelonghui.js +30 -0
- package/dist/src/sources/ghxi.js +48 -0
- package/dist/src/sources/github.js +29 -0
- package/dist/src/sources/hackernews.js +21 -0
- package/dist/src/sources/hupu.js +17 -0
- package/dist/src/sources/ifeng.js +21 -0
- package/dist/src/sources/index.js +90 -0
- package/dist/src/sources/iqiyi.js +17 -0
- package/dist/src/sources/ithome.js +29 -0
- package/dist/src/sources/jin10.js +24 -0
- package/dist/src/sources/juejin.js +11 -0
- package/dist/src/sources/kaopu.js +12 -0
- package/dist/src/sources/kuaishou.js +23 -0
- package/dist/src/sources/linuxdo.js +31 -0
- package/dist/src/sources/mktnews.js +20 -0
- package/dist/src/sources/nowcoder.js +19 -0
- package/dist/src/sources/pcbeta.js +5 -0
- package/dist/src/sources/producthunt.js +37 -0
- package/dist/src/sources/qqvideo.js +51 -0
- package/dist/src/sources/smzdm.js +17 -0
- package/dist/src/sources/solidot.js +27 -0
- package/dist/src/sources/sputniknewscn.js +25 -0
- package/dist/src/sources/sspai.js +13 -0
- package/dist/src/sources/steam.js +26 -0
- package/dist/src/sources/tencent.js +14 -0
- package/dist/src/sources/thepaper.js +12 -0
- package/dist/src/sources/tieba.js +11 -0
- package/dist/src/sources/toutiao.js +12 -0
- package/dist/src/sources/v2ex.js +14 -0
- package/dist/src/sources/wallstreetcn.js +38 -0
- package/dist/src/sources/weibo.js +46 -0
- package/dist/src/sources/xueqiu.js +18 -0
- package/dist/src/sources/zaobao.js +31 -0
- package/dist/src/sources/zhihu.js +15 -0
- package/dist/src/types.js +1 -0
- package/dist/src/utils.js +46 -0
- package/dist/test/cli.test.js +61 -0
- package/package.json +28 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { myFetch } from "../fetch.js";
|
|
3
|
+
function formatUrl(url, baseUrl = "https://www.freebuf.com") {
|
|
4
|
+
if (!url)
|
|
5
|
+
return "";
|
|
6
|
+
return url.startsWith("http") ? url : `${baseUrl}${url}`;
|
|
7
|
+
}
|
|
8
|
+
function extractIdFromUrl(url) {
|
|
9
|
+
const lastPart = url.slice(url.lastIndexOf("/") + 1);
|
|
10
|
+
const match = lastPart.match(/\d+/);
|
|
11
|
+
return match ? match[0] : "";
|
|
12
|
+
}
|
|
13
|
+
async function handler() {
|
|
14
|
+
const baseUrl = "https://www.freebuf.com";
|
|
15
|
+
const html = await myFetch(baseUrl, {
|
|
16
|
+
headers: {
|
|
17
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
|
|
18
|
+
"Referer": "https://www.freebuf.com/",
|
|
19
|
+
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
const $ = cheerio.load(html);
|
|
23
|
+
const articles = [];
|
|
24
|
+
$(".article-item").each((_, articleElement) => {
|
|
25
|
+
const $article = $(articleElement);
|
|
26
|
+
try {
|
|
27
|
+
const titleLink = $article.find(".title-left .title").parent();
|
|
28
|
+
const title = titleLink.find(".title").text().trim();
|
|
29
|
+
const url = formatUrl(titleLink.attr("href"), baseUrl);
|
|
30
|
+
if (!title)
|
|
31
|
+
return;
|
|
32
|
+
const description = $article.find(".item-right .text-line-2").first().text().trim();
|
|
33
|
+
articles.push({
|
|
34
|
+
id: extractIdFromUrl(url),
|
|
35
|
+
title,
|
|
36
|
+
url,
|
|
37
|
+
extra: { hover: description },
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch { }
|
|
41
|
+
});
|
|
42
|
+
return articles;
|
|
43
|
+
}
|
|
44
|
+
export default { freebuf: handler };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { myFetch } from "../fetch.js";
|
|
3
|
+
import { parseRelativeDate } from "../utils.js";
|
|
4
|
+
async function handler() {
|
|
5
|
+
const baseURL = "https://www.gelonghui.com";
|
|
6
|
+
const html = await myFetch("https://www.gelonghui.com/news/");
|
|
7
|
+
const $ = cheerio.load(html);
|
|
8
|
+
const $main = $(".article-content");
|
|
9
|
+
const news = [];
|
|
10
|
+
$main.each((_, el) => {
|
|
11
|
+
const a = $(el).find(".detail-right>a");
|
|
12
|
+
const url = a.attr("href");
|
|
13
|
+
const title = a.find("h2").text();
|
|
14
|
+
const info = $(el).find(".time > span:nth-child(1)").text();
|
|
15
|
+
const relatieveTime = $(el).find(".time > span:nth-child(3)").text();
|
|
16
|
+
if (url && title && relatieveTime) {
|
|
17
|
+
news.push({
|
|
18
|
+
url: baseURL + url,
|
|
19
|
+
title,
|
|
20
|
+
id: url,
|
|
21
|
+
extra: {
|
|
22
|
+
date: parseRelativeDate(relatieveTime, "Asia/Shanghai").valueOf(),
|
|
23
|
+
info,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return news;
|
|
29
|
+
}
|
|
30
|
+
export default { gelonghui: handler };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { myFetch } from "../fetch.js";
|
|
3
|
+
function relativeTimeToDate(timeStr) {
|
|
4
|
+
const units = {
|
|
5
|
+
"秒": 1000,
|
|
6
|
+
"分钟": 60 * 1000,
|
|
7
|
+
"小时": 60 * 60 * 1000,
|
|
8
|
+
"天": 24 * 60 * 60 * 1000,
|
|
9
|
+
"周": 7 * 24 * 60 * 60 * 1000,
|
|
10
|
+
"月": 30 * 24 * 60 * 60 * 1000,
|
|
11
|
+
"年": 365 * 24 * 60 * 60 * 1000,
|
|
12
|
+
};
|
|
13
|
+
const match = timeStr.match(/^(\d+)\s*([秒天周月年]|分钟|小时)/);
|
|
14
|
+
if (!match)
|
|
15
|
+
return "";
|
|
16
|
+
const num = parseInt(match[1]);
|
|
17
|
+
const unit = match[2];
|
|
18
|
+
const msAgo = num * units[unit];
|
|
19
|
+
return new Date(Date.now() - msAgo).valueOf();
|
|
20
|
+
}
|
|
21
|
+
async function handler() {
|
|
22
|
+
const html = await myFetch("https://www.ghxi.com/category/all");
|
|
23
|
+
const $ = cheerio.load(html);
|
|
24
|
+
const news = [];
|
|
25
|
+
$(".sec-panel .sec-panel-body .post-loop li").each((_, elem) => {
|
|
26
|
+
let summary_title = $(elem).find(".item-content .item-title").text();
|
|
27
|
+
if (summary_title)
|
|
28
|
+
summary_title = summary_title.trim().replaceAll("'", "''");
|
|
29
|
+
let summary_description = $(elem).find(".item-content .item-excerpt").text();
|
|
30
|
+
if (summary_description)
|
|
31
|
+
summary_description = summary_description.trim().replaceAll("'", "''");
|
|
32
|
+
const date = $(elem).find(".item-content .date").text();
|
|
33
|
+
const url = $(elem).find(".item-content .item-title a").attr("href");
|
|
34
|
+
if (url) {
|
|
35
|
+
news.push({
|
|
36
|
+
id: url,
|
|
37
|
+
url,
|
|
38
|
+
title: summary_title,
|
|
39
|
+
extra: {
|
|
40
|
+
hover: summary_description,
|
|
41
|
+
date: relativeTimeToDate(date),
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return news;
|
|
47
|
+
}
|
|
48
|
+
export default { ghxi: handler };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { myFetch } from "../fetch.js";
|
|
3
|
+
const trending = async () => {
|
|
4
|
+
const baseURL = "https://github.com";
|
|
5
|
+
const html = await myFetch("https://github.com/trending?spoken_language_code=");
|
|
6
|
+
const $ = cheerio.load(html);
|
|
7
|
+
const $main = $("main .Box div[data-hpc] > article");
|
|
8
|
+
const news = [];
|
|
9
|
+
$main.each((_, el) => {
|
|
10
|
+
const a = $(el).find(">h2 a");
|
|
11
|
+
const title = a.text().replace(/\n+/g, "").trim();
|
|
12
|
+
const url = a.attr("href");
|
|
13
|
+
const star = $(el).find("[href$=stargazers]").text().replace(/\s+/g, "").trim();
|
|
14
|
+
const desc = $(el).find(">p").text().replace(/\n+/g, "").trim();
|
|
15
|
+
if (url && title) {
|
|
16
|
+
news.push({
|
|
17
|
+
url: `${baseURL}${url}`,
|
|
18
|
+
title,
|
|
19
|
+
id: url,
|
|
20
|
+
extra: { info: `✰ ${star}`, hover: desc },
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return news;
|
|
25
|
+
};
|
|
26
|
+
export default {
|
|
27
|
+
"github": trending,
|
|
28
|
+
"github-trending-today": trending,
|
|
29
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { myFetch } from "../fetch.js";
|
|
3
|
+
async function handler() {
|
|
4
|
+
const baseURL = "https://news.ycombinator.com";
|
|
5
|
+
const html = await myFetch(baseURL);
|
|
6
|
+
const $ = cheerio.load(html);
|
|
7
|
+
const $main = $(".athing");
|
|
8
|
+
const news = [];
|
|
9
|
+
$main.each((_, el) => {
|
|
10
|
+
const a = $(el).find(".titleline a").first();
|
|
11
|
+
const title = a.text();
|
|
12
|
+
const id = $(el).attr("id");
|
|
13
|
+
const score = $(`#score_${id}`).text();
|
|
14
|
+
const url = `${baseURL}/item?id=${id}`;
|
|
15
|
+
if (url && id && title) {
|
|
16
|
+
news.push({ url, title, id, extra: { info: score } });
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
return news;
|
|
20
|
+
}
|
|
21
|
+
export default { hackernews: handler };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { myFetch } from "../fetch.js";
|
|
2
|
+
async function handler() {
|
|
3
|
+
const html = await myFetch(`https://bbs.hupu.com/topic-daily-hot`);
|
|
4
|
+
const regex = /<li class="bbs-sl-web-post-body">[\s\S]*?<a href="(\/[^"]+?\.html)"[^>]*?class="p-title"[^>]*>([^<]+)<\/a>/g;
|
|
5
|
+
const result = [];
|
|
6
|
+
let match;
|
|
7
|
+
while (true) {
|
|
8
|
+
match = regex.exec(html);
|
|
9
|
+
if (!match)
|
|
10
|
+
break;
|
|
11
|
+
const [, path, title] = match;
|
|
12
|
+
const url = `https://bbs.hupu.com${path}`;
|
|
13
|
+
result.push({ id: path, title: title.trim(), url, mobileUrl: url });
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
export default { hupu: handler };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { myFetch } from "../fetch.js";
|
|
2
|
+
async function handler() {
|
|
3
|
+
const html = await myFetch("https://www.ifeng.com/");
|
|
4
|
+
const regex = /var\s+allData\s*=\s*(\{[\s\S]*?\});/;
|
|
5
|
+
const match = regex.exec(html);
|
|
6
|
+
const news = [];
|
|
7
|
+
if (match) {
|
|
8
|
+
const realData = JSON.parse(match[1]);
|
|
9
|
+
const rawNews = realData.hotNews1;
|
|
10
|
+
rawNews.forEach((hotNews) => {
|
|
11
|
+
news.push({
|
|
12
|
+
id: hotNews.url,
|
|
13
|
+
url: hotNews.url,
|
|
14
|
+
title: hotNews.title,
|
|
15
|
+
extra: { date: hotNews.newsTime },
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return news;
|
|
20
|
+
}
|
|
21
|
+
export default { ifeng: handler };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import _36kr from "./_36kr.js";
|
|
2
|
+
import baidu from "./baidu.js";
|
|
3
|
+
import bilibili from "./bilibili.js";
|
|
4
|
+
import cankaoxiaoxi from "./cankaoxiaoxi.js";
|
|
5
|
+
import chongbuluo from "./chongbuluo.js";
|
|
6
|
+
import cls from "./cls/index.js";
|
|
7
|
+
import coolapk from "./coolapk/index.js";
|
|
8
|
+
import douban from "./douban.js";
|
|
9
|
+
import douyin from "./douyin.js";
|
|
10
|
+
import fastbull from "./fastbull.js";
|
|
11
|
+
import freebuf from "./freebuf.js";
|
|
12
|
+
import gelonghui from "./gelonghui.js";
|
|
13
|
+
import ghxi from "./ghxi.js";
|
|
14
|
+
import github from "./github.js";
|
|
15
|
+
import hackernews from "./hackernews.js";
|
|
16
|
+
import hupu from "./hupu.js";
|
|
17
|
+
import ifeng from "./ifeng.js";
|
|
18
|
+
import iqiyi from "./iqiyi.js";
|
|
19
|
+
import ithome from "./ithome.js";
|
|
20
|
+
import jin10 from "./jin10.js";
|
|
21
|
+
import juejin from "./juejin.js";
|
|
22
|
+
import kaopu from "./kaopu.js";
|
|
23
|
+
import kuaishou from "./kuaishou.js";
|
|
24
|
+
import linuxdo from "./linuxdo.js";
|
|
25
|
+
import mktnews from "./mktnews.js";
|
|
26
|
+
import nowcoder from "./nowcoder.js";
|
|
27
|
+
import pcbeta from "./pcbeta.js";
|
|
28
|
+
import producthunt from "./producthunt.js";
|
|
29
|
+
import qqvideo from "./qqvideo.js";
|
|
30
|
+
import smzdm from "./smzdm.js";
|
|
31
|
+
import solidot from "./solidot.js";
|
|
32
|
+
import sputniknewscn from "./sputniknewscn.js";
|
|
33
|
+
import sspai from "./sspai.js";
|
|
34
|
+
import steam from "./steam.js";
|
|
35
|
+
import tencent from "./tencent.js";
|
|
36
|
+
import thepaper from "./thepaper.js";
|
|
37
|
+
import tieba from "./tieba.js";
|
|
38
|
+
import toutiao from "./toutiao.js";
|
|
39
|
+
import v2ex from "./v2ex.js";
|
|
40
|
+
import wallstreetcn from "./wallstreetcn.js";
|
|
41
|
+
import weibo from "./weibo.js";
|
|
42
|
+
import xueqiu from "./xueqiu.js";
|
|
43
|
+
import zaobao from "./zaobao.js";
|
|
44
|
+
import zhihu from "./zhihu.js";
|
|
45
|
+
export const sources = {
|
|
46
|
+
..._36kr,
|
|
47
|
+
...baidu,
|
|
48
|
+
...bilibili,
|
|
49
|
+
...cankaoxiaoxi,
|
|
50
|
+
...chongbuluo,
|
|
51
|
+
...cls,
|
|
52
|
+
...coolapk,
|
|
53
|
+
...douban,
|
|
54
|
+
...douyin,
|
|
55
|
+
...fastbull,
|
|
56
|
+
...freebuf,
|
|
57
|
+
...gelonghui,
|
|
58
|
+
...ghxi,
|
|
59
|
+
...github,
|
|
60
|
+
...hackernews,
|
|
61
|
+
...hupu,
|
|
62
|
+
...ifeng,
|
|
63
|
+
...iqiyi,
|
|
64
|
+
...ithome,
|
|
65
|
+
...jin10,
|
|
66
|
+
...juejin,
|
|
67
|
+
...kaopu,
|
|
68
|
+
...kuaishou,
|
|
69
|
+
...linuxdo,
|
|
70
|
+
...mktnews,
|
|
71
|
+
...nowcoder,
|
|
72
|
+
...pcbeta,
|
|
73
|
+
...producthunt,
|
|
74
|
+
...qqvideo,
|
|
75
|
+
...smzdm,
|
|
76
|
+
...solidot,
|
|
77
|
+
...sputniknewscn,
|
|
78
|
+
...sspai,
|
|
79
|
+
...steam,
|
|
80
|
+
...tencent,
|
|
81
|
+
...thepaper,
|
|
82
|
+
...tieba,
|
|
83
|
+
...toutiao,
|
|
84
|
+
...v2ex,
|
|
85
|
+
...wallstreetcn,
|
|
86
|
+
...weibo,
|
|
87
|
+
...xueqiu,
|
|
88
|
+
...zaobao,
|
|
89
|
+
...zhihu,
|
|
90
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { myFetch } from "../fetch.js";
|
|
2
|
+
const hotRankList = async () => {
|
|
3
|
+
const url = "https://mesh.if.iqiyi.com/portal/lw/v7/channel/card/videoTab?channelName=recommend"
|
|
4
|
+
+ "&data_source=v7_rec_sec_hot_rank_list&tempId=85&count=30&block_id=hot_ranklist"
|
|
5
|
+
+ "&device=14a4b5ba98e790dce6dc07482447cf48&from=webapp";
|
|
6
|
+
const resp = await myFetch(url, {
|
|
7
|
+
headers: { Referer: "https://www.iqiyi.com" },
|
|
8
|
+
});
|
|
9
|
+
return resp?.items[0]?.video[0]?.data.map((item) => ({
|
|
10
|
+
id: item.entity_id,
|
|
11
|
+
title: item.title,
|
|
12
|
+
url: item.page_url,
|
|
13
|
+
pubDate: item?.showDate,
|
|
14
|
+
extra: { info: item.desc, hover: item.description, tag: item.tag },
|
|
15
|
+
}));
|
|
16
|
+
};
|
|
17
|
+
export default { "iqiyi-hot-ranklist": hotRankList };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { myFetch } from "../fetch.js";
|
|
3
|
+
import { parseRelativeDate } from "../utils.js";
|
|
4
|
+
async function handler() {
|
|
5
|
+
const response = await myFetch("https://www.ithome.com/list/");
|
|
6
|
+
const $ = cheerio.load(response);
|
|
7
|
+
const $main = $("#list > div.fl > ul > li");
|
|
8
|
+
const news = [];
|
|
9
|
+
$main.each((_, el) => {
|
|
10
|
+
const $el = $(el);
|
|
11
|
+
const $a = $el.find("a.t");
|
|
12
|
+
const url = $a.attr("href");
|
|
13
|
+
const title = $a.text();
|
|
14
|
+
const date = $(el).find("i").text();
|
|
15
|
+
if (url && title && date) {
|
|
16
|
+
const isAd = url?.includes("lapin") || ["神券", "优惠", "补贴", "京东"].find(k => title.includes(k));
|
|
17
|
+
if (!isAd) {
|
|
18
|
+
news.push({
|
|
19
|
+
url,
|
|
20
|
+
title,
|
|
21
|
+
id: url,
|
|
22
|
+
pubDate: parseRelativeDate(date, "Asia/Shanghai").valueOf(),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return news.sort((m, n) => n.pubDate > m.pubDate ? 1 : -1);
|
|
28
|
+
}
|
|
29
|
+
export default { ithome: handler };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { myFetch } from "../fetch.js";
|
|
2
|
+
import { parseRelativeDate } from "../utils.js";
|
|
3
|
+
async function handler() {
|
|
4
|
+
const timestamp = Date.now();
|
|
5
|
+
const url = `https://www.jin10.com/flash_newest.js?t=${timestamp}`;
|
|
6
|
+
const rawData = await myFetch(url);
|
|
7
|
+
const jsonStr = rawData
|
|
8
|
+
.replace(/^var\s+newest\s*=\s*/, "")
|
|
9
|
+
.replace(/;*$/, "")
|
|
10
|
+
.trim();
|
|
11
|
+
const data = JSON.parse(jsonStr);
|
|
12
|
+
return data.filter(k => (k.data.title || k.data.content) && !k.channel?.includes(5)).map((k) => {
|
|
13
|
+
const text = (k.data.title || k.data.content).replace(/<\/?b>/g, "");
|
|
14
|
+
const [, title, desc] = text.match(/^【([^】]*)】(.*)$/) ?? [];
|
|
15
|
+
return {
|
|
16
|
+
id: k.id,
|
|
17
|
+
title: title ?? text,
|
|
18
|
+
pubDate: parseRelativeDate(k.time, "Asia/Shanghai").valueOf(),
|
|
19
|
+
url: `https://flash.jin10.com/detail/${k.id}`,
|
|
20
|
+
extra: { hover: desc, info: !!k.important && "✰" },
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export default { jin10: handler };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { myFetch } from "../fetch.js";
|
|
2
|
+
async function handler() {
|
|
3
|
+
const url = `https://api.juejin.cn/content_api/v1/content/article_rank?category_id=1&type=hot&spider=0`;
|
|
4
|
+
const res = await myFetch(url);
|
|
5
|
+
return res.data.map((k) => ({
|
|
6
|
+
id: k.content.content_id,
|
|
7
|
+
title: k.content.title,
|
|
8
|
+
url: `https://juejin.cn/post/${k.content.content_id}`,
|
|
9
|
+
}));
|
|
10
|
+
}
|
|
11
|
+
export default { juejin: handler };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { $fetch } from "../fetch.js";
|
|
2
|
+
async function handler() {
|
|
3
|
+
const res = await $fetch("https://kaopustorage.blob.core.windows.net/news-prod/news_list_hans_0.json");
|
|
4
|
+
return res.filter(k => ["财新", "公视"].every(h => k.publisher !== h)).map((k) => ({
|
|
5
|
+
id: k.link,
|
|
6
|
+
title: k.title,
|
|
7
|
+
pubDate: k.pub_date,
|
|
8
|
+
extra: { hover: k.description, info: k.publisher },
|
|
9
|
+
url: k.link,
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
export default { kaopu: handler };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { myFetch } from "../fetch.js";
|
|
2
|
+
async function handler() {
|
|
3
|
+
const html = await myFetch("https://www.kuaishou.com/?isHome=1", {
|
|
4
|
+
headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" },
|
|
5
|
+
});
|
|
6
|
+
const matches = html.match(/window\.__APOLLO_STATE__\s*=\s*(\{.+?\});/);
|
|
7
|
+
if (!matches)
|
|
8
|
+
throw new Error("无法获取快手热榜数据");
|
|
9
|
+
const data = JSON.parse(matches[1]);
|
|
10
|
+
const hotRankId = data.defaultClient.ROOT_QUERY[`visionHotRank({"page":"home"})`].id;
|
|
11
|
+
const hotRankData = data.defaultClient[hotRankId];
|
|
12
|
+
return hotRankData.items.filter((k) => data.defaultClient[k.id].tagType !== "置顶").map((item) => {
|
|
13
|
+
const hotSearchWord = item.id.replace("VisionHotRankItem:", "");
|
|
14
|
+
const hotItem = data.defaultClient[item.id];
|
|
15
|
+
return {
|
|
16
|
+
id: hotSearchWord,
|
|
17
|
+
title: hotItem.name,
|
|
18
|
+
url: `https://www.kuaishou.com/search/video?searchKey=${encodeURIComponent(hotItem.name)}`,
|
|
19
|
+
extra: { icon: hotItem.iconUrl },
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export default { kuaishou: handler };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { myFetch } from "../fetch.js";
|
|
2
|
+
const hot = async () => {
|
|
3
|
+
const res = await myFetch("https://linux.do/top/daily.json", {
|
|
4
|
+
headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" },
|
|
5
|
+
});
|
|
6
|
+
return res.topic_list.topics
|
|
7
|
+
.filter(k => k.visible && !k.archived && !k.pinned)
|
|
8
|
+
.map(k => ({
|
|
9
|
+
id: k.id,
|
|
10
|
+
title: k.title,
|
|
11
|
+
url: `https://linux.do/t/topic/${k.id}`,
|
|
12
|
+
}));
|
|
13
|
+
};
|
|
14
|
+
const latest = async () => {
|
|
15
|
+
const res = await myFetch("https://linux.do/latest.json?order=created", {
|
|
16
|
+
headers: { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" },
|
|
17
|
+
});
|
|
18
|
+
return res.topic_list.topics
|
|
19
|
+
.filter(k => k.visible && !k.archived && !k.pinned)
|
|
20
|
+
.map(k => ({
|
|
21
|
+
id: k.id,
|
|
22
|
+
title: k.title,
|
|
23
|
+
pubDate: new Date(k.created_at).valueOf(),
|
|
24
|
+
url: `https://linux.do/t/topic/${k.id}`,
|
|
25
|
+
}));
|
|
26
|
+
};
|
|
27
|
+
export default {
|
|
28
|
+
"linuxdo": latest,
|
|
29
|
+
"linuxdo-latest": latest,
|
|
30
|
+
"linuxdo-hot": hot,
|
|
31
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { myFetch } from "../fetch.js";
|
|
2
|
+
const flash = async () => {
|
|
3
|
+
const res = await myFetch("https://api.mktnews.net/api/flash?type=0&limit=50");
|
|
4
|
+
return res.data
|
|
5
|
+
.sort((a, b) => new Date(b.time).getTime() - new Date(a.time).getTime())
|
|
6
|
+
.map(item => ({
|
|
7
|
+
id: item.id,
|
|
8
|
+
title: item.data.title || item.data.content.match(/^【([^】]*)】(.*)$/)?.[1] || item.data.content,
|
|
9
|
+
pubDate: item.time,
|
|
10
|
+
extra: {
|
|
11
|
+
info: item.important === 1 ? "Important" : undefined,
|
|
12
|
+
hover: item.data.content,
|
|
13
|
+
},
|
|
14
|
+
url: `https://mktnews.net/flashDetail.html?id=${item.id}`,
|
|
15
|
+
}));
|
|
16
|
+
};
|
|
17
|
+
export default {
|
|
18
|
+
"mktnews": flash,
|
|
19
|
+
"mktnews-flash": flash,
|
|
20
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { myFetch } from "../fetch.js";
|
|
2
|
+
async function handler() {
|
|
3
|
+
const timestamp = Date.now();
|
|
4
|
+
const url = `https://gw-c.nowcoder.com/api/sparta/hot-search/top-hot-pc?size=20&_=${timestamp}&t=`;
|
|
5
|
+
const res = await myFetch(url);
|
|
6
|
+
return res.data.result.map((k) => {
|
|
7
|
+
let itemUrl, id;
|
|
8
|
+
if (k.type === 74) {
|
|
9
|
+
itemUrl = `https://www.nowcoder.com/feed/main/detail/${k.uuid}`;
|
|
10
|
+
id = k.uuid;
|
|
11
|
+
}
|
|
12
|
+
else if (k.type === 0) {
|
|
13
|
+
itemUrl = `https://www.nowcoder.com/discuss/${k.id}`;
|
|
14
|
+
id = k.id;
|
|
15
|
+
}
|
|
16
|
+
return { id: id, title: k.title, url: itemUrl };
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export default { nowcoder: handler };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
import { myFetch } from "../fetch.js";
|
|
3
|
+
async function handler() {
|
|
4
|
+
const apiToken = process.env.PRODUCTHUNT_API_TOKEN;
|
|
5
|
+
const token = `Bearer ${apiToken}`;
|
|
6
|
+
if (!apiToken)
|
|
7
|
+
throw new Error("PRODUCTHUNT_API_TOKEN is not set");
|
|
8
|
+
const query = `
|
|
9
|
+
query {
|
|
10
|
+
posts(first: 30, order: VOTES) {
|
|
11
|
+
edges {
|
|
12
|
+
node { id name tagline votesCount url slug }
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
`;
|
|
17
|
+
const response = await myFetch("https://api.producthunt.com/v2/api/graphql", {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: {
|
|
20
|
+
"Authorization": token,
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
"Accept": "application/json",
|
|
23
|
+
},
|
|
24
|
+
body: JSON.stringify({ query }),
|
|
25
|
+
});
|
|
26
|
+
const posts = response?.data?.posts?.edges || [];
|
|
27
|
+
return posts.map((edge) => {
|
|
28
|
+
const post = edge.node;
|
|
29
|
+
return {
|
|
30
|
+
id: post.id,
|
|
31
|
+
title: post.name,
|
|
32
|
+
url: post.url || `https://www.producthunt.com/posts/${post.slug}`,
|
|
33
|
+
extra: { info: ` △︎ ${post.votesCount || 0}`, hover: post.tagline },
|
|
34
|
+
};
|
|
35
|
+
}).filter((p) => p.id && p.title);
|
|
36
|
+
}
|
|
37
|
+
export default { producthunt: handler };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import dayjs from "dayjs";
|
|
2
|
+
import { myFetch } from "../fetch.js";
|
|
3
|
+
function getQqVideoUrl(cid) {
|
|
4
|
+
return `https://v.qq.com/x/cover/${cid}.html`;
|
|
5
|
+
}
|
|
6
|
+
const hotSearch = async () => {
|
|
7
|
+
const url = "https://pbaccess.video.qq.com/trpc.vector_layout.page_view.PageService/getCard?video_appid=3000010&vversion_platform=2";
|
|
8
|
+
const resp = await myFetch(url, {
|
|
9
|
+
method: "POST",
|
|
10
|
+
headers: { Referer: "https://v.qq.com/" },
|
|
11
|
+
body: {
|
|
12
|
+
page_params: {
|
|
13
|
+
rank_channel_id: "100113",
|
|
14
|
+
rank_name: "HotSearch",
|
|
15
|
+
rank_page_size: "30",
|
|
16
|
+
tab_mvl_sub_mod_id: "792ac_19e77Sub_1b2",
|
|
17
|
+
tab_name: "热搜榜",
|
|
18
|
+
tab_type: "hot_rank",
|
|
19
|
+
tab_vl_data_src: "f5200deb4596bbf3",
|
|
20
|
+
page_id: "scms_shake",
|
|
21
|
+
page_type: "scms_shake",
|
|
22
|
+
source_key: "",
|
|
23
|
+
tag_id: "",
|
|
24
|
+
tag_type: "",
|
|
25
|
+
new_mark_label_enabled: "1",
|
|
26
|
+
},
|
|
27
|
+
page_context: { page_index: "1" },
|
|
28
|
+
flip_info: {
|
|
29
|
+
page_strategy_id: "",
|
|
30
|
+
page_module_id: "792ac_19e77",
|
|
31
|
+
module_strategy_id: {},
|
|
32
|
+
sub_module_id: "20251106065177",
|
|
33
|
+
flip_params: {
|
|
34
|
+
page_id: "scms_shake",
|
|
35
|
+
page_num: "0",
|
|
36
|
+
page_type: "scms_shake",
|
|
37
|
+
source_key: "100113",
|
|
38
|
+
},
|
|
39
|
+
relace_children_key: [],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
return resp?.data?.card?.children_list?.list?.cards?.map((item) => ({
|
|
44
|
+
id: item?.id,
|
|
45
|
+
title: item?.params?.title,
|
|
46
|
+
url: getQqVideoUrl(item?.id),
|
|
47
|
+
pubDate: item?.params?.publish_date ?? dayjs().format("YYYY-MM-DD"),
|
|
48
|
+
extra: { hover: item?.params?.sub_title },
|
|
49
|
+
}));
|
|
50
|
+
};
|
|
51
|
+
export default { "qqvideo-tv-hotsearch": hotSearch };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { myFetch } from "../fetch.js";
|
|
3
|
+
async function handler() {
|
|
4
|
+
const baseURL = "https://post.smzdm.com/hot_1/";
|
|
5
|
+
const html = await myFetch(baseURL);
|
|
6
|
+
const $ = cheerio.load(html);
|
|
7
|
+
const $main = $("#feed-main-list .z-feed-title");
|
|
8
|
+
const news = [];
|
|
9
|
+
$main.each((_, el) => {
|
|
10
|
+
const a = $(el).find("a");
|
|
11
|
+
const url = a.attr("href");
|
|
12
|
+
const title = a.text();
|
|
13
|
+
news.push({ url, title, id: url });
|
|
14
|
+
});
|
|
15
|
+
return news;
|
|
16
|
+
}
|
|
17
|
+
export default { smzdm: handler };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as cheerio from "cheerio";
|
|
2
|
+
import { myFetch } from "../fetch.js";
|
|
3
|
+
import { parseRelativeDate } from "../utils.js";
|
|
4
|
+
async function handler() {
|
|
5
|
+
const baseURL = "https://www.solidot.org";
|
|
6
|
+
const html = await myFetch(baseURL);
|
|
7
|
+
const $ = cheerio.load(html);
|
|
8
|
+
const $main = $(".block_m");
|
|
9
|
+
const news = [];
|
|
10
|
+
$main.each((_, el) => {
|
|
11
|
+
const a = $(el).find(".bg_htit a").last();
|
|
12
|
+
const url = a.attr("href");
|
|
13
|
+
const title = a.text();
|
|
14
|
+
const date_raw = $(el).find(".talk_time").text().match(/发表于(.*?分)/)?.[1];
|
|
15
|
+
const date = date_raw?.replace(/[年月]/g, "-").replace("时", ":").replace(/[分日]/g, "");
|
|
16
|
+
if (url && title && date) {
|
|
17
|
+
news.push({
|
|
18
|
+
url: baseURL + url,
|
|
19
|
+
title,
|
|
20
|
+
id: url,
|
|
21
|
+
pubDate: parseRelativeDate(date, "Asia/Shanghai").valueOf(),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
return news;
|
|
26
|
+
}
|
|
27
|
+
export default { solidot: handler };
|