1
1
import { Route } from '@/types' ;
2
2
import cache from '@/utils/cache' ;
3
- import got from '@/utils/got ' ;
3
+ import ofetch from '@/utils/ofetch ' ;
4
4
import { load } from 'cheerio' ;
5
5
import { parseDate } from '@/utils/parse-date' ;
6
6
7
+ const mainCategories = {
8
+ local : 119 ,
9
+ international : 120 ,
10
+ entertainment : 500 ,
11
+ life : 501 ,
12
+ technology : 502 ,
13
+ finance : 121 ,
14
+ } ;
15
+
7
16
const categories = {
8
17
tracker : 123 ,
9
18
feature : 124 ,
@@ -25,7 +34,8 @@ export const route: Route = {
25
34
} ,
26
35
radar : [
27
36
{
28
- source : [ 'news.now.com/' ] ,
37
+ source : [ 'news.now.com/home/:category?' , 'news.now.com/' ] ,
38
+ target : '/news/:category?' ,
29
39
} ,
30
40
] ,
31
41
name : '新聞' ,
@@ -52,53 +62,103 @@ export const route: Route = {
52
62
} ;
53
63
54
64
async function handler ( ctx ) {
55
- const category = ctx . req . param ( 'category' ) || '' ;
56
- const id = ctx . req . param ( 'id' ) || '' ;
65
+ const { category = '' , id = '' } = ctx . req . param ( ) ;
66
+ const limit = Number . parseInt ( ctx . req . query ( 'limit' ) || '20' , 10 ) ;
67
+ const hasTopicId = id && Object . hasOwn ( categories , category ) ;
57
68
58
69
const rootUrl = 'https://news.now.com' ;
59
70
60
- const currentUrl = Object . hasOwn ( categories , category ) ? `${ rootUrl } /home/${ category } /detail?catCode=${ categories [ category ] } &topicId=${ id } ` : `${ rootUrl } /home${ category ? `/${ category } ` : '' } ` ;
61
-
62
- const response = await got ( {
63
- method : 'get' ,
64
- url : currentUrl ,
65
- } ) ;
66
-
67
- const $ = load ( response . data ) ;
68
-
69
- const list = $ ( `${ category === '' ? '.homeFeaturedNews ' : '.newsCategoryColLeft ' } .newsTitle` )
70
- . toArray ( )
71
- . map ( ( item ) => {
72
- item = $ ( item ) ;
73
-
74
- return {
75
- title : item . text ( ) ,
76
- link : `${ rootUrl } ${ item . parent ( ) . parent ( ) . attr ( 'href' ) } ` ,
77
- } ;
78
- } ) ;
71
+ const pageUrl = hasTopicId ? `${ rootUrl } /home/${ category } /detail?catCode=${ categories [ category ] } &topicId=${ id } ` : `${ rootUrl } /home${ category ? `/${ category } ` : '' } ` ;
72
+
73
+ let apiUrl ;
74
+ if ( hasTopicId ) {
75
+ apiUrl = pageUrl ;
76
+ } else if ( category === 'sports' ) {
77
+ apiUrl = `https://sportsapi.now.com/api/getNewsList?pageSize=${ limit } &pageNo=1&searchTagsKey=allSportsSearchTags` ;
78
+ } else if ( category ) {
79
+ apiUrl = `https://d3sli7vh0lsda4.cloudfront.net/api/getNewsList?category=${ mainCategories [ category ] } &pageNo=1&pageSize=${ limit } ` ;
80
+ } else {
81
+ apiUrl = pageUrl ;
82
+ }
83
+
84
+ const response = await ofetch ( apiUrl ) ;
85
+ const isApi = typeof response === 'object' && Array . isArray ( response ) ;
86
+ const $ = load ( response ) ;
87
+
88
+ let list ;
89
+ if ( isApi ) {
90
+ list =
91
+ category === 'sports'
92
+ ? response . map ( ( item ) => {
93
+ const image = item . newsPhotos
94
+ ?. filter ( ( p ) => p . sizeType === '3' )
95
+ ?. map ( ( p ) => `<img src="${ p . imageFileUrl } ">` )
96
+ . join ( '' ) ;
97
+ return {
98
+ title : item . headlineChi ,
99
+ description : image ,
100
+ link : `https://news.now.com/home/${ category } /player?newsId=${ item . newsId } ` ,
101
+ pubDate : parseDate ( item . publishDate , 'x' ) ,
102
+ category : [ ...item . sportTypes . map ( ( t ) => t . sportTypeNameChi ) , ...item . players . map ( ( p ) => p . playerFullNameChi ) , ...item . teams . map ( ( t ) => t . teamCodeChi ) ] ,
103
+ image : item . newsPhotos ?. filter ( ( p ) => p . sizeType === '3' ) ?. [ 0 ] ?. imageUrl ,
104
+ newsId : item . newsId ,
105
+ } ;
106
+ } )
107
+ : response . map ( ( item ) => {
108
+ const image = item . image2Url ?? item . imageUrl ?? item . image3Url ;
109
+ return {
110
+ title : item . title ,
111
+ description : ( image ? `<img src="${ image } ">` : '' ) + item . leading + item . summary ,
112
+ link : `https://news.now.com/home/${ category } /player?newsId=${ item . newsId } ` ,
113
+ pubDate : parseDate ( item . publishDate , 'x' ) ,
114
+ updated : parseDate ( item . lastModifyDate , 'x' ) ,
115
+ category : item . newsTags . map ( ( t ) => t . tag ) ,
116
+ image,
117
+ } ;
118
+ } ) ;
119
+ } else {
120
+ list = $ ( `${ category === '' ? '.homeFeaturedNews ' : '.newsCategoryColLeft ' } .newsTitle` )
121
+ . toArray ( )
122
+ . slice ( 0 , limit )
123
+ . map ( ( item ) => {
124
+ item = $ ( item ) ;
125
+
126
+ return {
127
+ title : item . text ( ) ,
128
+ link : `${ rootUrl } ${ item . parent ( ) . parent ( ) . attr ( 'href' ) } ` ,
129
+ } ;
130
+ } ) ;
131
+ }
79
132
80
133
const items = await Promise . all (
81
134
list . map ( ( item ) =>
82
135
cache . tryGet ( item . link , async ( ) => {
83
- const detailResponse = await got ( {
84
- method : 'get' ,
85
- url : item . link ,
86
- } ) ;
87
- const content = load ( detailResponse . data ) ;
136
+ if ( ! item . pubDate || item . newsId ) {
137
+ const detailResponse = await ofetch ( item . link ) ;
138
+ const $ = load ( detailResponse ) ;
139
+
140
+ const newsData = JSON . parse (
141
+ $ ( 'script:contains("var newsData")' )
142
+ . text ( )
143
+ . match ( / v a r n e w s D a t a = ( .* ?) ; / ) ?. [ 1 ] || '{}'
144
+ ) ;
88
145
89
- const images = detailResponse . data . match ( / " i m a g e U r l " : " ( . * ? ) " , " i m a g e 2 U r l " : / ) ;
146
+ const images = newsData . imageList ? newsData . imageList . map ( ( img ) => `<img src=" ${ img . image2Url } ">` ) . join ( '' ) : '' ;
90
147
91
- item . pubDate = parseDate ( content ( '.published' ) . attr ( 'datetime' ) ) ;
92
- item . description = ( images ? `<img src="${ images [ 1 ] } ">` : '' ) + content ( '.newsLeading' ) . html ( ) ;
148
+ item . description = item . description ? item . description + ( $ ( '.img_caption' ) . prop ( 'outerHTML' ) ?? '' ) + $ ( '.newsLeading' ) . html ( ) : images + $ ( '.newsLeading' ) . html ( ) ;
149
+ item . pubDate ||= parseDate ( newsData . publishDate , 'x' ) ;
150
+ item . updated ||= parseDate ( newsData . lastModifyDate , 'x' ) ;
151
+ item . category ||= [ ...new Set ( [ newsData . categoryName , ...newsData . newsTags . map ( ( t ) => t . tag ) , ...newsData . newsTopics . map ( ( t ) => t . topicName ) ] ) ] ;
152
+ }
93
153
94
154
return item ;
95
155
} )
96
156
)
97
157
) ;
98
158
99
159
return {
100
- title : String ( Object . hasOwn ( categories , category ) ? $ ( 'title' ) . text ( ) : ( $ ( '.smallSpace.active' ) . text ( ) || '首頁' ) + ' | Now 新聞' ) ,
101
- link : currentUrl ,
160
+ title : Object . hasOwn ( categories , category ) ? $ ( 'title' ) . text ( ) : ( $ ( '.smallSpace.active' ) . text ( ) || '首頁' ) + ' | Now 新聞' ,
161
+ link : pageUrl ,
102
162
item : items ,
103
163
} ;
104
164
}
0 commit comments