rsshub 1.0.0-master.f97cdb2 → 1.0.0-master.fa3428f

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.
Files changed (237) hide show
  1. package/README.md +1 -1
  2. package/lib/config.js +3 -1
  3. package/lib/radar-rules.js +0 -92
  4. package/lib/router.js +68 -71
  5. package/lib/routes/tencent/wechat/miniprogram/framework.js +4 -2
  6. package/lib/utils/common-config.js +4 -0
  7. package/lib/utils/parse-date.js +8 -7
  8. package/lib/utils/rand-user-agent.js +29 -0
  9. package/lib/utils/request-wrapper.js +2 -5
  10. package/lib/utils/wechat-mp.js +106 -10
  11. package/lib/v2/agirls/index.js +6 -0
  12. package/lib/v2/bilibili/video.js +1 -0
  13. package/lib/v2/bookfere/category.js +36 -0
  14. package/lib/v2/bookfere/maintainer.js +3 -0
  15. package/lib/v2/bookfere/radar.js +11 -0
  16. package/lib/v2/bookfere/router.js +3 -0
  17. package/lib/v2/cankaoxiaoxi/index.js +81 -0
  18. package/lib/v2/cankaoxiaoxi/maintainer.js +3 -0
  19. package/lib/v2/cankaoxiaoxi/radar.js +61 -0
  20. package/lib/v2/cankaoxiaoxi/router.js +3 -0
  21. package/lib/{routes → v2}/cctv/category.js +1 -1
  22. package/lib/{routes → v2}/cctv/jx.js +6 -1
  23. package/lib/{routes → v2}/cctv/lm.js +1 -1
  24. package/lib/v2/cctv/maintainer.js +7 -0
  25. package/lib/v2/cctv/radar.js +41 -0
  26. package/lib/v2/cctv/router.js +7 -0
  27. package/lib/{routes → v2}/cctv/special.js +6 -4
  28. package/lib/{routes → v2}/cctv/utils/mzzlbg.js +8 -6
  29. package/lib/{routes → v2}/cctv/utils/news.js +25 -22
  30. package/lib/{routes → v2}/cctv/utils/xinwen1j1.js +20 -17
  31. package/lib/v2/cctv/xwlb.js +50 -0
  32. package/lib/v2/chinacef/experts.js +38 -0
  33. package/lib/v2/chinacef/hot.js +38 -0
  34. package/lib/v2/chinacef/index.js +39 -0
  35. package/lib/v2/chinacef/maintainer.js +5 -0
  36. package/lib/v2/chinacef/radar.js +25 -0
  37. package/lib/v2/chinacef/router.js +5 -0
  38. package/lib/v2/{wechat → chinacef}/templates/description.art +0 -0
  39. package/lib/v2/chinacef/utils.js +55 -0
  40. package/lib/v2/chinanews/index.js +65 -0
  41. package/lib/v2/chinanews/maintainer.js +3 -0
  42. package/lib/v2/chinanews/radar.js +13 -0
  43. package/lib/v2/chinanews/router.js +3 -0
  44. package/lib/v2/cnbeta/index.js +2 -1
  45. package/lib/v2/cnbeta/utils.js +1 -0
  46. package/lib/v2/dapenti/maintainer.js +4 -0
  47. package/lib/v2/dapenti/radar.js +27 -0
  48. package/lib/v2/dapenti/router.js +4 -0
  49. package/lib/{routes → v2}/dapenti/subject.js +1 -1
  50. package/lib/{routes → v2}/dapenti/tugua.js +1 -1
  51. package/lib/v2/dapenti/utils.js +75 -0
  52. package/lib/{routes → v2}/dongqiudi/daily.js +10 -13
  53. package/lib/v2/dongqiudi/maintainer.js +8 -0
  54. package/lib/{routes → v2}/dongqiudi/player_news.js +0 -0
  55. package/lib/v2/dongqiudi/radar.js +45 -0
  56. package/lib/{routes → v2}/dongqiudi/result.js +2 -1
  57. package/lib/v2/dongqiudi/router.js +8 -0
  58. package/lib/{routes → v2}/dongqiudi/special.js +0 -0
  59. package/lib/{routes → v2}/dongqiudi/team_news.js +0 -0
  60. package/lib/{routes → v2}/dongqiudi/top_news.js +12 -15
  61. package/lib/{routes → v2}/dongqiudi/utils.js +47 -28
  62. package/lib/v2/dut/defaults.js +53 -0
  63. package/lib/v2/dut/index.js +78 -0
  64. package/lib/v2/dut/maintainer.js +14 -0
  65. package/lib/v2/dut/radar.js +109 -0
  66. package/lib/v2/dut/router.js +4 -0
  67. package/lib/v2/dut/shortcuts.js +77 -0
  68. package/lib/{routes → v2}/dx2025/index.js +0 -0
  69. package/lib/v2/dx2025/maintainer.js +3 -0
  70. package/lib/v2/dx2025/radar.js +19 -0
  71. package/lib/v2/dx2025/router.js +3 -0
  72. package/lib/v2/e-hentai/radar.js +21 -3
  73. package/lib/v2/eagle/blog.js +47 -0
  74. package/lib/{routes → v2}/eagle/changelog.js +3 -1
  75. package/lib/v2/eagle/maintainer.js +4 -0
  76. package/lib/v2/eagle/radar.js +101 -0
  77. package/lib/v2/eagle/router.js +4 -0
  78. package/lib/{routes → v2}/ehentai/ehapi.js +50 -21
  79. package/lib/{routes → v2}/ehentai/favorites.js +4 -2
  80. package/lib/v2/ehentai/maintainer.js +5 -0
  81. package/lib/v2/ehentai/router.js +5 -0
  82. package/lib/{routes → v2}/ehentai/search.js +5 -3
  83. package/lib/{routes → v2}/ehentai/tag.js +4 -2
  84. package/lib/v2/firefox/index.js +7 -2
  85. package/lib/v2/fortunechina/index.js +1 -1
  86. package/lib/v2/github/comments.js +7 -0
  87. package/lib/v2/gitpod/blog.js +8 -0
  88. package/lib/v2/gov/maintainer.js +1 -0
  89. package/lib/v2/gov/nrta/news.js +63 -0
  90. package/lib/v2/gov/radar.js +11 -0
  91. package/lib/v2/gov/router.js +1 -0
  92. package/lib/v2/guancha/index.js +1 -1
  93. package/lib/v2/guangdiu/cheaps.js +28 -0
  94. package/lib/v2/guangdiu/index.js +44 -0
  95. package/lib/v2/guangdiu/maintainer.js +5 -0
  96. package/lib/v2/guangdiu/radar.js +25 -0
  97. package/lib/v2/guangdiu/rank.js +38 -0
  98. package/lib/v2/guangdiu/router.js +5 -0
  99. package/lib/{routes/guokr/calendar.js → v2/guokr/channel.js} +2 -2
  100. package/lib/v2/guokr/maintainer.js +4 -0
  101. package/lib/v2/guokr/radar.js +19 -0
  102. package/lib/v2/guokr/router.js +4 -0
  103. package/lib/{routes → v2}/guokr/scientific.js +3 -3
  104. package/lib/v2/hkej/index.js +9 -15
  105. package/lib/v2/hkepc/index.js +8 -0
  106. package/lib/v2/hket/index.js +10 -2
  107. package/lib/v2/huangz/index.js +29 -0
  108. package/lib/v2/huangz/maintainer.js +3 -0
  109. package/lib/v2/huangz/radar.js +13 -0
  110. package/lib/v2/huangz/router.js +3 -0
  111. package/lib/v2/huanqiu/index.js +65 -0
  112. package/lib/v2/huanqiu/maintainer.js +3 -0
  113. package/lib/v2/huanqiu/radar.js +13 -0
  114. package/lib/v2/huanqiu/router.js +3 -0
  115. package/lib/v2/miris/blog.js +19 -0
  116. package/lib/v2/miris/maintainer.js +3 -0
  117. package/lib/v2/miris/radar.js +11 -0
  118. package/lib/v2/miris/router.js +3 -0
  119. package/lib/v2/news/whxw.js +2 -2
  120. package/lib/v2/npm/package.js +1 -1
  121. package/lib/v2/npm/router.js +1 -1
  122. package/lib/v2/qbittorrent/maintainer.js +3 -0
  123. package/lib/v2/qbittorrent/news.js +59 -0
  124. package/lib/v2/qbittorrent/radar.js +13 -0
  125. package/lib/v2/qbittorrent/router.js +3 -0
  126. package/lib/v2/rsshub/sponsors.js +1 -0
  127. package/lib/{routes → v2}/sciencenet/blog.js +17 -12
  128. package/lib/v2/sciencenet/maintainer.js +4 -0
  129. package/lib/v2/sciencenet/radar.js +19 -0
  130. package/lib/v2/sciencenet/router.js +4 -0
  131. package/lib/v2/sciencenet/user.js +65 -0
  132. package/lib/v2/sdu/cmse.js +59 -0
  133. package/lib/v2/sdu/cs.js +57 -0
  134. package/lib/v2/sdu/data.js +110 -0
  135. package/lib/v2/sdu/epe.js +55 -0
  136. package/lib/v2/sdu/extractor/index.js +15 -0
  137. package/lib/v2/sdu/extractor/sdrj.js +21 -0
  138. package/lib/v2/sdu/extractor/view.js +21 -0
  139. package/lib/v2/sdu/extractor/wh/jwc.js +24 -0
  140. package/lib/v2/sdu/extractor/wh/news.js +21 -0
  141. package/lib/v2/sdu/maintainer.js +9 -0
  142. package/lib/v2/sdu/mech.js +60 -0
  143. package/lib/v2/sdu/radar.js +159 -0
  144. package/lib/v2/sdu/router.js +9 -0
  145. package/lib/v2/sdu/sc.js +61 -0
  146. package/lib/v2/sdu/wh/jwc.js +42 -0
  147. package/lib/v2/sdu/wh/news.js +38 -0
  148. package/lib/v2/stratechery/index.js +20 -0
  149. package/lib/v2/stratechery/maintainer.js +3 -0
  150. package/lib/v2/stratechery/radar.js +11 -0
  151. package/lib/v2/stratechery/router.js +3 -0
  152. package/lib/{routes → v2}/taptap/changelog.js +2 -1
  153. package/lib/v2/taptap/maintainer.js +5 -0
  154. package/lib/v2/taptap/radar.js +25 -0
  155. package/lib/v2/taptap/review.js +69 -0
  156. package/lib/v2/taptap/router.js +5 -0
  157. package/lib/v2/taptap/templates/videoPost.art +2 -0
  158. package/lib/v2/taptap/topic.js +79 -0
  159. package/lib/v2/taptap/utils.js +48 -0
  160. package/lib/v2/thecover/channel.js +66 -0
  161. package/lib/v2/thecover/maintainer.js +3 -0
  162. package/lib/v2/thecover/radar.js +13 -0
  163. package/lib/v2/thecover/router.js +3 -0
  164. package/lib/{routes → v2}/twreporter/category.js +7 -12
  165. package/lib/{routes → v2}/twreporter/fetch_article.js +5 -4
  166. package/lib/v2/twreporter/maintainer.js +5 -0
  167. package/lib/{routes → v2}/twreporter/newest.js +8 -13
  168. package/lib/v2/twreporter/photography.js +46 -0
  169. package/lib/v2/twreporter/radar.js +25 -0
  170. package/lib/v2/twreporter/router.js +5 -0
  171. package/lib/{routes/tencent → v2}/wechat/announce.js +3 -2
  172. package/lib/v2/wechat/ce.js +69 -0
  173. package/lib/v2/wechat/data258.js +137 -0
  174. package/lib/v2/wechat/ershcimi.js +35 -0
  175. package/lib/{routes/tencent → v2}/wechat/feeds.js +0 -0
  176. package/lib/v2/wechat/maintainer.js +11 -0
  177. package/lib/{routes/tencent → v2}/wechat/mp.js +0 -0
  178. package/lib/{routes/tencent → v2}/wechat/msgalbum.js +0 -0
  179. package/lib/v2/wechat/radar.js +76 -1
  180. package/lib/v2/wechat/router.js +11 -0
  181. package/lib/{routes/tencent → v2}/wechat/tgchannel.js +0 -0
  182. package/lib/{routes/tencent → v2}/wechat/uread.js +0 -0
  183. package/lib/{routes/tencent → v2}/wechat/wemp.js +0 -0
  184. package/lib/{routes/tencent → v2}/wechat/wxnmh.js +0 -0
  185. package/lib/{routes → v2}/xueqiu/favorite.js +2 -1
  186. package/lib/v2/xueqiu/fund.js +50 -0
  187. package/lib/{routes → v2}/xueqiu/hots.js +2 -1
  188. package/lib/v2/xueqiu/maintainer.js +10 -0
  189. package/lib/v2/xueqiu/radar.js +60 -0
  190. package/lib/v2/xueqiu/router.js +10 -0
  191. package/lib/{routes → v2}/xueqiu/snb.js +2 -1
  192. package/lib/{routes → v2}/xueqiu/stock_comments.js +4 -20
  193. package/lib/{routes → v2}/xueqiu/stock_info.js +2 -1
  194. package/lib/v2/xueqiu/templates/comments_description.art +10 -0
  195. package/lib/{routes → v2}/xueqiu/user.js +2 -1
  196. package/lib/{routes → v2}/xueqiu/user_stock.js +3 -2
  197. package/lib/v2/yunspe/maintainer.js +3 -0
  198. package/lib/v2/yunspe/newsflash.js +42 -0
  199. package/lib/v2/yunspe/radar.js +13 -0
  200. package/lib/v2/yunspe/router.js +3 -0
  201. package/lib/{routes → v2}/yystv/category.js +8 -8
  202. package/lib/{routes → v2}/yystv/docs.js +2 -2
  203. package/lib/v2/yystv/maintainer.js +4 -0
  204. package/lib/v2/yystv/radar.js +49 -0
  205. package/lib/v2/yystv/router.js +4 -0
  206. package/lib/{routes/universities → v2}/zju/career/index.js +14 -13
  207. package/lib/{routes/universities → v2}/zju/cst/custom.js +2 -1
  208. package/lib/{routes/universities → v2}/zju/cst/index.js +20 -24
  209. package/lib/v2/zju/grs/index.js +43 -0
  210. package/lib/v2/zju/list.js +66 -0
  211. package/lib/v2/zju/maintainer.js +8 -0
  212. package/lib/v2/zju/physics/index.js +52 -0
  213. package/lib/v2/zju/radar.js +139 -0
  214. package/lib/v2/zju/router.js +8 -0
  215. package/lib/views/atom.art +13 -1
  216. package/lib/views/welcome.art +4 -1
  217. package/package.json +13 -12
  218. package/lib/routes/cctv/xwlb.js +0 -48
  219. package/lib/routes/dapenti/utils.js +0 -73
  220. package/lib/routes/taptap/review.js +0 -39
  221. package/lib/routes/taptap/topic.js +0 -85
  222. package/lib/routes/tencent/wechat/_README +0 -1
  223. package/lib/routes/tencent/wechat/ce.js +0 -40
  224. package/lib/routes/tencent/wechat/ershcimi.js +0 -43
  225. package/lib/routes/twreporter/photography.js +0 -57
  226. package/lib/routes/universities/dut/index.js +0 -60
  227. package/lib/routes/universities/dut/subsite.js +0 -50
  228. package/lib/routes/universities/sdu/cmse.js +0 -55
  229. package/lib/routes/universities/sdu/cs.js +0 -55
  230. package/lib/routes/universities/sdu/epe.js +0 -54
  231. package/lib/routes/universities/sdu/mech.js +0 -58
  232. package/lib/routes/universities/sdu/sc.js +0 -56
  233. package/lib/routes/universities/zju/grs/index.js +0 -44
  234. package/lib/routes/universities/zju/list.js +0 -78
  235. package/lib/routes/universities/zju/physics/index.js +0 -55
  236. package/lib/routes/xueqiu/fund.js +0 -71
  237. package/lib/v2/wechat/templates/image.art +0 -1
@@ -2,19 +2,19 @@
2
2
  * Author: @Rongronggg9
3
3
  *
4
4
  * There are at least three folders which are relevant with WeChat MP (Official Account Platform / Media Platform):
5
- * lib/route/tencent/wechat
6
5
  * lib/v2/wechat
7
6
  * lib/v2/gzh360
7
+ * lib/v2/sdu/cs
8
8
  *
9
9
  * If your new route is not in the above folders, please add it to the list.
10
10
  *
11
- * If your route need to fetch MP articles from mp.weixin.qq.com, you SHOULD use `finishArticleItem`.
11
+ * If your route needs to fetch MP articles from mp.weixin.qq.com, you SHOULD use `finishArticleItem`.
12
12
  * However, if your route need to determine some metadata by itself, you MAY use `fetchArticle`.
13
13
  * If you find more metadata on the webpage, consider modifying `fetchArticle` to include them.
14
14
  * NEVER fetch MP articles from mp.weixin.qq.com in your route in order to avoid cache key collision.
15
15
  * NO NEED TO use cache if you are using `finishArticleItem` or `fetchArticle`, they will handle cache for you.
16
16
  *
17
- * If your route fetch MP articles from other websites, you SHOULD use `fixArticleContent` to fix the content format.
17
+ * If your route fetches MP articles from other websites, you SHOULD use `fixArticleContent` to fix the content format.
18
18
  * If you find more fixes that should be applied, consider modifying `fixArticleContent` to include them.
19
19
  *
20
20
  * For more details of these functions, please refer to the jsDoc in the source code.
@@ -35,6 +35,31 @@ const replaceTag = ($, oldTag, newTagName) => {
35
35
  oldTag.replaceWith(NewTag);
36
36
  };
37
37
 
38
+ const detectOriginalArticleUrl = ($) => {
39
+ // No article content get, try the original url
40
+ // example: https://mp.weixin.qq.com/s/f6sKObaZZhADTYU2Jl5Bnw
41
+ if (!$('#js_content').text()) {
42
+ return $('#js_share_source').attr('data-url');
43
+ }
44
+ // Article content is too short, try the first link
45
+ // example: https://mp.weixin.qq.com/s/9saVB4KaolRyJfpajzeFRg
46
+ if ($('#js_content').text().length < 80) {
47
+ return $('#js_content a').attr('href');
48
+ }
49
+ return null;
50
+ };
51
+
52
+ const detectSourceUrl = ($) => {
53
+ const matchs = $.root()
54
+ .html()
55
+ .match(/msg_source_url = '(.+)';/);
56
+
57
+ if (matchs) {
58
+ return matchs[1];
59
+ }
60
+ return null;
61
+ };
62
+
38
63
  /**
39
64
  * Articles from WeChat MP have weird formats, this function is used to fix them.
40
65
  *
@@ -77,11 +102,69 @@ const fixArticleContent = (html, skipImg = false) => {
77
102
  replaceTag($, section, 'div');
78
103
  }
79
104
  });
105
+
106
+ // fix single picture article
107
+ // example: https://mp.weixin.qq.com/s/4p5YmYuASiQSYFiy7KqydQ
108
+ $('script').each((_, script) => {
109
+ script = $(script);
110
+ const matchs = script.html().match(/document\.getElementById\('js_image_desc'\)\.innerHTML = "(.*)"\.replace/);
111
+
112
+ if (matchs) {
113
+ script.replaceWith(matchs[1].replace(/\r/g, '').replace(/\n/g, '<br>').replace(/\\x0d/g, '').replace(/\\x0a/g, '<br>'));
114
+ }
115
+ });
116
+
80
117
  // clean scripts
81
118
  $('script').remove();
82
119
  return $.html();
83
120
  };
84
121
 
122
+ // Ref:
123
+ // https://soaked.in/2020/08/wechat-platform-url/
124
+ // Known params (permanent long link):
125
+ // __biz (essential), mid (essential), idx (essential), sn (essential), chksm, mpshare, scene, ascene, subscene, srcid,
126
+ // lang, sharer_sharetime, sharer_shareid, version, exportkey, pass_ticket, clicktime, enterid, devicetype, nettype,
127
+ // abtest_cookie, wx_header
128
+ // Known params (temporary link):
129
+ // src, timestamp, ver, signature, new (unessential)
130
+ const normalizeUrl = (url, bypassHostCheck = false) => {
131
+ const oriUrl = url;
132
+ const urlObj = new URL(url);
133
+ if (!bypassHostCheck && urlObj.host !== 'mp.weixin.qq.com') {
134
+ throw new Error('wechat-mp: URL host must be "mp.weixin.qq.com", but got ' + oriUrl);
135
+ }
136
+ urlObj.protocol = 'https:';
137
+ urlObj.hash = ''; // remove hash
138
+ if (urlObj.pathname.match(/^\/s\/.+/)) {
139
+ // a short link, just remove all the params
140
+ urlObj.search = '';
141
+ } else if (urlObj.pathname.match(/^\/s$/)) {
142
+ const biz = urlObj.searchParams.get('__biz');
143
+ const mid = urlObj.searchParams.get('mid') || urlObj.searchParams.get('appmsgid');
144
+ const idx = urlObj.searchParams.get('idx') || urlObj.searchParams.get('itemidx');
145
+ const sn = urlObj.searchParams.get('sn') || urlObj.searchParams.get('sign');
146
+ if (biz && mid && idx && sn) {
147
+ // a permanent long link, remove all unessential params
148
+ // no need to escape anything so no need to use `new URLSearchParams({...}).toString()`
149
+ urlObj.search = `?__biz=${biz}&mid=${mid}&idx=${idx}&sn=${sn}`;
150
+ } else {
151
+ const src = urlObj.searchParams.get('src');
152
+ const timestamp = urlObj.searchParams.get('timestamp');
153
+ const ver = urlObj.searchParams.get('ver');
154
+ const signature = urlObj.searchParams.get('signature');
155
+ if (src && timestamp && ver && signature) {
156
+ // a temporary link, remove all unessential params
157
+ urlObj.search = `?src=${src}&timestamp=${timestamp}&ver=${ver}&signature=${signature}`;
158
+ } else {
159
+ // unknown link, just let it go
160
+ }
161
+ }
162
+ } else {
163
+ // IDK what it is, just let it go
164
+ }
165
+ return urlObj.href;
166
+ };
167
+
85
168
  /**
86
169
  * Fetch article and its metadata from WeChat MP (mp.weixin.qq.com).
87
170
  *
@@ -92,20 +175,30 @@ const fixArticleContent = (html, skipImg = false) => {
92
175
  * @return {Promise<object>} - An object containing the article and its metadata.
93
176
  */
94
177
  const fetchArticle = async (ctx, url, bypassHostCheck = false) => {
95
- const oriUrl = url;
96
- url = url.replace(/^http:\/\//, 'https://').replace(/#\w*$/, ''); // normalize url
97
- if (!bypassHostCheck && !url.startsWith('https://mp.weixin.qq.com/')) {
98
- throw new Error('wechat-mp: URL must start with https://mp.weixin.qq.com/ or http://mp.weixin.qq.com/, but got ' + oriUrl);
99
- }
178
+ url = normalizeUrl(url, bypassHostCheck);
100
179
  return await ctx.cache.tryGet(url, async () => {
101
180
  const response = await got(url);
102
181
  const $ = cheerio.load(response.data);
103
182
 
104
- const title = $('meta[property="og:title"]').attr('content');
183
+ const title = ($('meta[property="og:title"]').attr('content') || '').replace(/\\r/g, '').replace(/\\n/g, ' ');
105
184
  const author = $('meta[name=author]').attr('content');
106
185
  let summary = $('meta[name=description]').attr('content');
107
186
  summary = summary !== title ? summary : '';
108
- const description = fixArticleContent($('div#js_content.rich_media_content'));
187
+ let description = fixArticleContent($('#js_content'));
188
+
189
+ // No article get or article is too short, try the original url
190
+ const originalUrl = detectOriginalArticleUrl($);
191
+ if (originalUrl) {
192
+ // try to fetch the description from the original article
193
+ const originalResponse = await got(normalizeUrl(originalUrl, bypassHostCheck));
194
+ const original$ = cheerio.load(originalResponse.data);
195
+ description += fixArticleContent(original$('#js_content'));
196
+ }
197
+
198
+ const sourceUrl = detectSourceUrl($);
199
+ if (sourceUrl) {
200
+ description += `<a href="${sourceUrl}">阅读原文</a>`;
201
+ }
109
202
 
110
203
  let pubDate;
111
204
  const publish_time_script = $('script[nonce][type="text/javascript"]:contains("var ct")').first().html();
@@ -161,4 +254,7 @@ module.exports = {
161
254
  fixArticleContent,
162
255
  fetchArticle,
163
256
  finishArticleItem, // a new route SHOULD use this function instead of manually calling the above functions
257
+ _internal: {
258
+ normalizeUrl, // for internal use only, exported for testing
259
+ },
164
260
  };
@@ -4,6 +4,9 @@ const { parseDate } = require('@/utils/parse-date');
4
4
  const timezone = require('@/utils/timezone');
5
5
  const path = require('path');
6
6
  const { art } = require('@/utils/render');
7
+ const { CookieJar } = require('tough-cookie');
8
+
9
+ const cookieJar = new CookieJar();
7
10
 
8
11
  module.exports = async (ctx) => {
9
12
  const baseUrl = 'https://agirls.aotter.net';
@@ -14,6 +17,7 @@ module.exports = async (ctx) => {
14
17
  headers: {
15
18
  Referer: baseUrl,
16
19
  },
20
+ cookieJar,
17
21
  });
18
22
 
19
23
  const $ = cheerio.load(response.data);
@@ -36,6 +40,7 @@ module.exports = async (ctx) => {
36
40
  headers: {
37
41
  Referer: baseUrl + '/posts/' + (category ? `/${category}` : ''),
38
42
  },
43
+ cookieJar,
39
44
  });
40
45
  const content = cheerio.load(detailResponse.data);
41
46
 
@@ -67,5 +72,6 @@ module.exports = async (ctx) => {
67
72
  description: $('head meta[name=description]').attr('content'),
68
73
  item: items,
69
74
  language: $('html').attr('lang'),
75
+ cookieJar,
70
76
  };
71
77
  };
@@ -32,6 +32,7 @@ module.exports = async (ctx) => {
32
32
  pubDate: new Date(item.created * 1000).toUTCString(),
33
33
  link: item.created > utils.bvidTime && item.bvid ? `https://www.bilibili.com/video/${item.bvid}` : `https://www.bilibili.com/video/av${item.aid}`,
34
34
  author: name,
35
+ comments: item.comment,
35
36
  })),
36
37
  };
37
38
  };
@@ -0,0 +1,36 @@
1
+ const got = require('@/utils/got');
2
+ const cheerio = require('cheerio');
3
+ const { parseDate } = require('@/utils/parse-date');
4
+
5
+ module.exports = async (ctx) => {
6
+ const url = 'https://bookfere.com/category/' + ctx.params.category;
7
+ const response = await got({
8
+ method: 'get',
9
+ url,
10
+ });
11
+
12
+ const data = response.data;
13
+
14
+ const $ = cheerio.load(data);
15
+ const list = $('main div div section');
16
+
17
+ ctx.state.data = {
18
+ title: $('head title').text(),
19
+ link: url,
20
+ item:
21
+ list &&
22
+ list
23
+ .map((index, item) => {
24
+ item = $(item);
25
+ const date = item.find('time').attr('datetime');
26
+ const pubDate = parseDate(date);
27
+ return {
28
+ title: item.find('h2 a').text(),
29
+ link: item.find('h2 a').attr('href'),
30
+ pubDate,
31
+ description: item.find('p').text(),
32
+ };
33
+ })
34
+ .get(),
35
+ };
36
+ };
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ '/:category': ['OdinZhang'],
3
+ };
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ 'bookfere.com': {
3
+ _name: '书伴',
4
+ '.': [
5
+ {
6
+ title: '分类',
7
+ docs: 'https://docs.rsshub.app/reading.html#shu-ban',
8
+ },
9
+ ],
10
+ },
11
+ };
@@ -0,0 +1,3 @@
1
+ module.exports = function (router) {
2
+ router.get('/:category', require('./category'));
3
+ };
@@ -0,0 +1,81 @@
1
+ const got = require('@/utils/got');
2
+ const timezone = require('@/utils/timezone');
3
+ const { parseDate } = require('@/utils/parse-date');
4
+ const cheerio = require('cheerio');
5
+
6
+ const nodes = {
7
+ china_news: {
8
+ title: '中国',
9
+ url: 'https://china.cankaoxiaoxi.com/',
10
+ },
11
+ world_news: {
12
+ title: '国际',
13
+ url: 'https://world.cankaoxiaoxi.com/',
14
+ },
15
+ military_news: {
16
+ title: '军事',
17
+ url: 'https://mil.cankaoxiaoxi.com/',
18
+ },
19
+ taiwan_news: {
20
+ title: '台海',
21
+ url: 'https://tw.cankaoxiaoxi.com/',
22
+ },
23
+ finance_news: {
24
+ title: '财经',
25
+ url: 'https://finance.cankaoxiaoxi.com/',
26
+ },
27
+ technology_news: {
28
+ title: '科技',
29
+ url: 'https://science.cankaoxiaoxi.com/',
30
+ },
31
+ culture_news: {
32
+ title: '文化',
33
+ url: 'https://culture.cankaoxiaoxi.com/',
34
+ },
35
+ };
36
+
37
+ module.exports = async (ctx) => {
38
+ const category = ctx.params.category;
39
+
40
+ const currentUrl = nodes[category].url;
41
+ const response = await got({
42
+ method: 'get',
43
+ url: currentUrl,
44
+ });
45
+
46
+ const $ = cheerio.load(response.data);
47
+
48
+ const list = $('a', '.toutiao')
49
+ .filter(function () {
50
+ return $(this).text() !== '';
51
+ })
52
+ .map((_, item) => ({
53
+ link: $(item).attr('href'),
54
+ }))
55
+ .get();
56
+
57
+ const items = await Promise.all(
58
+ list.map((item) =>
59
+ ctx.cache.tryGet(item.link, async () => {
60
+ const detailResponse = await got({
61
+ method: 'get',
62
+ url: item.link,
63
+ });
64
+ const content = cheerio.load(detailResponse.data);
65
+ item.title = content('h1.articleHead').text();
66
+ item.pubDate = timezone(parseDate(content('span#pubtime_baidu').text()), +8);
67
+ item.author = content('span#source_baidu').text();
68
+ item.description = content('div.articleText').html();
69
+ return item;
70
+ })
71
+ )
72
+ );
73
+
74
+ ctx.state.data = {
75
+ title: `${nodes[category].title} 参考消息`,
76
+ link: currentUrl,
77
+ description: '参考消息',
78
+ language: 'zh-cn',
79
+ item: items,
80
+ };
81
+ };
@@ -0,0 +1,3 @@
1
+ module.exports = {
2
+ '/news/:category': ['yuxinliu-alex'],
3
+ };
@@ -0,0 +1,61 @@
1
+ module.exports = {
2
+ 'cankaoxiaoxi.com': {
3
+ _name: '参考消息',
4
+ china: [
5
+ {
6
+ title: '中国新闻',
7
+ docs: 'https://docs.rsshub.app/traditional-media.html#can-kao-xiao-xi',
8
+ source: ['/'],
9
+ target: '/cankaoxiaoxi/news/china_news',
10
+ },
11
+ ],
12
+ culture: [
13
+ {
14
+ title: '文化新闻',
15
+ docs: 'https://docs.rsshub.app/traditional-media.html#can-kao-xiao-xi',
16
+ source: ['/'],
17
+ target: '/cankaoxiaoxi/news/culture_news',
18
+ },
19
+ ],
20
+ finance: [
21
+ {
22
+ title: '财经新闻',
23
+ docs: 'https://docs.rsshub.app/traditional-media.html#can-kao-xiao-xi',
24
+ source: ['/'],
25
+ target: '/cankaoxiaoxi/news/finance_news',
26
+ },
27
+ ],
28
+ mil: [
29
+ {
30
+ title: '军事新闻',
31
+ docs: 'https://docs.rsshub.app/traditional-media.html#can-kao-xiao-xi',
32
+ source: ['/'],
33
+ target: '/cankaoxiaoxi/news/military_news',
34
+ },
35
+ ],
36
+ science: [
37
+ {
38
+ title: '科技新闻',
39
+ docs: 'https://docs.rsshub.app/traditional-media.html#can-kao-xiao-xi',
40
+ source: ['/'],
41
+ target: '/cankaoxiaoxi/news/technology_news',
42
+ },
43
+ ],
44
+ tw: [
45
+ {
46
+ title: '台海新闻',
47
+ docs: 'https://docs.rsshub.app/traditional-media.html#can-kao-xiao-xi',
48
+ source: ['/'],
49
+ target: '/cankaoxiaoxi/news/taiwan_news',
50
+ },
51
+ ],
52
+ world: [
53
+ {
54
+ title: '国际新闻',
55
+ docs: 'https://docs.rsshub.app/traditional-media.html#can-kao-xiao-xi',
56
+ source: ['/'],
57
+ target: '/cankaoxiaoxi/news/world_news',
58
+ },
59
+ ],
60
+ },
61
+ };
@@ -0,0 +1,3 @@
1
+ module.exports = function (router) {
2
+ router.get('/news/:category', require('./index'));
3
+ };
@@ -9,7 +9,7 @@ module.exports = async (ctx) => {
9
9
  } else if (category === 'xinwen1j1') {
10
10
  // 新闻1+1
11
11
  const xinwen1j1 = require('./utils/xinwen1j1');
12
- responseData = await xinwen1j1(category, ctx);
12
+ responseData = await xinwen1j1(ctx);
13
13
  } else {
14
14
  // 央视新闻
15
15
  const getNews = require('./utils/news');
@@ -1,5 +1,6 @@
1
1
  const got = require('@/utils/got');
2
2
  const cheerio = require('cheerio');
3
+ const { parseDate } = require('@/utils/parse-date');
3
4
 
4
5
  module.exports = async (ctx) => {
5
6
  const rootUrl = 'https://photo.cctv.com';
@@ -12,7 +13,7 @@ module.exports = async (ctx) => {
12
13
  const $ = cheerio.load(response.data);
13
14
 
14
15
  const list = $('.textr a')
15
- .slice(0, 10)
16
+ .slice(0, ctx.query.limit ? parseInt(ctx.query.limit) : 10)
16
17
  .map((_, item) => {
17
18
  item = $(item);
18
19
  return {
@@ -30,6 +31,10 @@ module.exports = async (ctx) => {
30
31
  url: item.link,
31
32
  });
32
33
  const content = cheerio.load(detailResponse.data);
34
+ const date = content('head')
35
+ .html()
36
+ .match(/publishDate ="(.*) ";/)[1];
37
+ item.pubDate = date ? parseDate(date, 'YYYYMMDDHHmmss') : null;
33
38
 
34
39
  item.description = content('.tujitop').html();
35
40
 
@@ -4,7 +4,7 @@ const timezone = require('@/utils/timezone');
4
4
  const { parseDate } = require('@/utils/parse-date');
5
5
 
6
6
  module.exports = async (ctx) => {
7
- const id = ctx.params.id || 'xwzk';
7
+ const id = ctx.params.id ?? 'xwzk';
8
8
 
9
9
  const rootUrl = 'https://tv.cctv.com';
10
10
  const apiRootUrl = 'https://api.cntv.cn';
@@ -0,0 +1,7 @@
1
+ module.exports = {
2
+ '/lm/:id?': ['nczitzk'],
3
+ '/photo/jx': ['nczitzk'],
4
+ '/special/:id?': ['nczitzk'],
5
+ '/xwlb': ['zengxs'],
6
+ '/:category': ['idealclover', 'xyqfer'],
7
+ };
@@ -0,0 +1,41 @@
1
+ module.exports = {
2
+ 'cctv.com': {
3
+ _name: '央视新闻',
4
+ news: [
5
+ {
6
+ title: '新闻专题',
7
+ docs: 'https://docs.rsshub.app/traditional-media.html#yang-shi-xin-wen',
8
+ source: ['/special/*id'],
9
+ target: (params) => `/cctv/special/${params.id.split('/')[0]}`,
10
+ },
11
+ {
12
+ title: '专题',
13
+ docs: 'https://docs.rsshub.app/traditional-media.html#yang-shi-xin-wen',
14
+ source: ['/:category'],
15
+ target: '/cctv/:category',
16
+ },
17
+ ],
18
+ photo: [
19
+ {
20
+ title: '央视网图片《镜象》',
21
+ docs: 'https://docs.rsshub.app/traditional-media.html#yang-shi-xin-wen',
22
+ source: ['/jx', '/'],
23
+ target: '/cctv/photo/jx',
24
+ },
25
+ ],
26
+ tv: [
27
+ {
28
+ title: '新闻联播',
29
+ docs: 'https://docs.rsshub.app/traditional-media.html#yang-shi-xin-wen',
30
+ source: ['/lm/xwlb', '/'],
31
+ target: '/cctv/xwlb',
32
+ },
33
+ {
34
+ title: '栏目',
35
+ docs: 'https://docs.rsshub.app/traditional-media.html#yang-shi-xin-wen',
36
+ source: ['/lm/*path', '/'],
37
+ target: (params) => `/cctv/lm/${params.path.replace('/videoset', '')}`,
38
+ },
39
+ ],
40
+ },
41
+ };
@@ -0,0 +1,7 @@
1
+ module.exports = (router) => {
2
+ router.get('/lm/:id?', require('./lm'));
3
+ router.get('/photo/jx', require('./jx'));
4
+ router.get('/special/:id?', require('./special'));
5
+ router.get('/xwlb', require('./xwlb'));
6
+ router.get('/:category', require('./category'));
7
+ };
@@ -1,8 +1,10 @@
1
1
  const got = require('@/utils/got');
2
2
  const cheerio = require('cheerio');
3
+ const { parseDate } = require('@/utils/parse-date');
4
+ const timezone = require('@/utils/timezone');
3
5
 
4
6
  module.exports = async (ctx) => {
5
- ctx.params.id = ctx.params.id || '315';
7
+ ctx.params.id = ctx.params.id ?? '315';
6
8
 
7
9
  let rootUrl;
8
10
 
@@ -75,10 +77,10 @@ module.exports = async (ctx) => {
75
77
  dateSpan = content('span.time').text();
76
78
  }
77
79
 
78
- date = dateSpan.replace(/年/g, '-').replace(/月/g, '-').replace(/日/g, '');
80
+ date = timezone(parseDate(dateSpan, 'YYYY年MM月DD日 HH:mm:ss'), +8);
79
81
  } else {
80
82
  const dateString = match[1];
81
- date = `${dateString.slice(0, 4)}-${dateString.slice(4, 6)}-${dateString.slice(6, 8)} ${dateString.slice(8, 10)}:${dateString.slice(10, 12)}:${dateString.slice(12, 14)}`;
83
+ date = timezone(parseDate(dateString, 'YYYYMMDDHHmmss'), +8);
82
84
  }
83
85
 
84
86
  if (content('#content_area').html() !== null) {
@@ -93,7 +95,7 @@ module.exports = async (ctx) => {
93
95
  }
94
96
  }
95
97
 
96
- item.pubDate = new Date(date + ' GMT+8').toUTCString();
98
+ item.pubDate = date;
97
99
 
98
100
  return item;
99
101
  })
@@ -1,7 +1,9 @@
1
1
  const got = require('@/utils/got');
2
+ const { parseDate } = require('@/utils/parse-date');
3
+ const timezone = require('@/utils/timezone');
2
4
 
3
5
  module.exports = async () => {
4
- const url = 'http://api.cntv.cn/video/videolistById?serviceId=cbox&vsid=C10354&em=01&p=1&n=50';
6
+ const url = 'https://api.cntv.cn/video/videolistById?serviceId=cbox&vsid=C10354&em=01&p=1&n=50';
5
7
 
6
8
  const response = await got({
7
9
  method: 'get',
@@ -12,26 +14,26 @@ module.exports = async () => {
12
14
 
13
15
  const resultItem = await Promise.all(
14
16
  data.video.map(async (video) => {
15
- const url = `http://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid=${video.vid}`;
17
+ const url = `https://vdn.apps.cntv.cn/api/getHttpVideoInfo.do?pid=${video.vid}`;
16
18
  const item = {
17
19
  title: video.t,
18
- description: '',
20
+ description: video.desc,
19
21
  link: video.url,
20
- pubDate: new Date(video.ptime).toUTCString(),
22
+ pubDate: timezone(parseDate(video.ptime), +8),
21
23
  };
22
24
  const { data: videoDetail } = await got({
23
25
  method: 'get',
24
26
  url,
25
27
  });
26
28
 
27
- item.description = `<video src="${videoDetail.hls_url}" controls="controls" poster="${video.img.replace(/\?.+/g, '')}" style="width: 100%"></video>`;
29
+ item.description += `<br><video src="${videoDetail.hls_url}" controls="controls" poster="${video.img.replace(/\?.+/g, '')}" style="width: 100%"></video>`;
28
30
  return item;
29
31
  })
30
32
  );
31
33
 
32
34
  return {
33
35
  title: '每周质量报告',
34
- link: 'http://tv.cctv.com/lm/mzzlbg/videoset/index.shtml',
36
+ link: 'https://tv.cctv.com/lm/mzzlbg/videoset/index.shtml',
35
37
  description:
36
38
  '《每周质量报告》是CCTV-新闻频道一档以消费者为核心收视人群的新闻专题栏目。创办于2003年,始终致力于产品质量和食品安全领域的调查报道,以打假除劣扶优,推动质量进步为第一诉求,是我国电视新闻界质量新闻领域的旗帜性节目。首播时间:CCTV-新闻周日12:35—12:55。',
37
39
  item: resultItem,