feat(source): Add Novels Online
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
import { fetchHtml } from '@utils/fetch/fetch';
|
||||
import * as cheerio from 'cheerio';
|
||||
import {
|
||||
SourceChapter,
|
||||
SourceChapterItem,
|
||||
SourceNovel,
|
||||
SourceNovelItem,
|
||||
} from '../types';
|
||||
|
||||
const sourceId = 163;
|
||||
const sourceName = 'novelsOnline';
|
||||
|
||||
// const baseUrl = 'https://novelsonline.net';
|
||||
|
||||
const searchNovels = async (searchTerm: string) => {
|
||||
const result = await fetchHtml({
|
||||
sourceId,
|
||||
url: 'https://novelsonline.net/sResults.php',
|
||||
init: {
|
||||
headers: {
|
||||
'Accept': '*/*',
|
||||
'Accept-Language': 'pl,en-US;q=0.7,en;q=0.3',
|
||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
},
|
||||
method: 'POST',
|
||||
body: 'q=' + encodeURIComponent(searchTerm),
|
||||
},
|
||||
});
|
||||
let $ = cheerio.load(result);
|
||||
|
||||
const headers = $('li');
|
||||
return headers
|
||||
.map((i, h) => {
|
||||
const novelName = $(h).text();
|
||||
const novelUrl = $(h).find('a').attr('href');
|
||||
const novelCover = $(h).find('img').attr('src');
|
||||
|
||||
if (!novelUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
sourceId,
|
||||
novelName,
|
||||
novelCover,
|
||||
novelUrl,
|
||||
} as SourceNovelItem;
|
||||
})
|
||||
.get()
|
||||
.filter(sr => sr !== null);
|
||||
};
|
||||
|
||||
const parseNovelAndChapters = async (novelUrl: string) => {
|
||||
let novel: SourceNovel = {
|
||||
sourceId,
|
||||
sourceName,
|
||||
url: novelUrl,
|
||||
novelUrl,
|
||||
chapters: [],
|
||||
};
|
||||
|
||||
const result = await fetchHtml({ url: novelUrl });
|
||||
let $ = cheerio.load(result);
|
||||
|
||||
novel.novelName = $('h1').text();
|
||||
novel.novelCover = $('.novel-cover').find('a > img').attr('src');
|
||||
novel.author = $(
|
||||
'div.novel-details > div:nth-child(5) > div.novel-detail-body',
|
||||
)
|
||||
.find('li')
|
||||
.map((_, el) => $(el).text())
|
||||
.get()
|
||||
.join(', ');
|
||||
|
||||
novel.genre = $(
|
||||
'div.novel-details > div:nth-child(2) > div.novel-detail-body',
|
||||
)
|
||||
.find('li')
|
||||
.map((_, el) => $(el).text())
|
||||
.get()
|
||||
.join(',');
|
||||
|
||||
novel.summary = $(
|
||||
'div.novel-right > div > div:nth-child(1) > div.novel-detail-body',
|
||||
).text();
|
||||
|
||||
novel.chapters = $('ul.chapter-chs > li > a')
|
||||
.map((_, el) => {
|
||||
const chapterUrl = $(el).attr('href');
|
||||
const chapterName = $(el).text();
|
||||
|
||||
return {
|
||||
sourceId,
|
||||
chapterName,
|
||||
releaseDate: null,
|
||||
chapterUrl,
|
||||
} as SourceChapterItem;
|
||||
})
|
||||
.get();
|
||||
|
||||
return novel;
|
||||
};
|
||||
|
||||
const popularNovels = async () => {
|
||||
return { novels: [] as SourceNovelItem[] }; /** TO DO */
|
||||
};
|
||||
|
||||
const parseChapter = async (novelUrl: string, chapterUrl: string) => {
|
||||
const result = await fetchHtml({ url: novelUrl });
|
||||
let loadedCheerio = cheerio.load(result);
|
||||
|
||||
const chapterName = loadedCheerio('h1').text();
|
||||
const chapterText = loadedCheerio('#contentall').html() || '';
|
||||
|
||||
const chapter: SourceChapter = {
|
||||
sourceId,
|
||||
novelUrl,
|
||||
chapterUrl,
|
||||
chapterName,
|
||||
chapterText,
|
||||
};
|
||||
|
||||
return chapter;
|
||||
};
|
||||
|
||||
const NovelsOnlineScraper = {
|
||||
popularNovels,
|
||||
parseNovelAndChapters,
|
||||
parseChapter,
|
||||
searchNovels,
|
||||
};
|
||||
|
||||
export default NovelsOnlineScraper;
|
||||
@@ -154,6 +154,7 @@ import {
|
||||
SiScraper,
|
||||
KodScraper,
|
||||
} from './multisrc/noveltl/NovelTlGenerator';
|
||||
import NovelsOnlineScraper from './en/NovelOnline';
|
||||
|
||||
interface PopularNovelsResponse {
|
||||
novels: SourceNovelItem[];
|
||||
@@ -321,7 +322,8 @@ export const sourceManager = (sourceId: number): Scraper => {
|
||||
159: BelScraper, // @ts-ignore
|
||||
160: RedScraper, // @ts-ignore
|
||||
161: SiScraper, // @ts-ignore
|
||||
162: KodScraper, // @ts-ignore
|
||||
162: KodScraper,
|
||||
163: NovelsOnlineScraper,
|
||||
};
|
||||
|
||||
return scrapers[sourceId];
|
||||
|
||||
@@ -985,5 +985,12 @@
|
||||
"url": "https://kod.novel.tl",
|
||||
"lang": "Russian",
|
||||
"icon": "https://kod.novel.tl/logo.png"
|
||||
},
|
||||
{
|
||||
"sourceId": 163,
|
||||
"sourceName": "Novels Online",
|
||||
"url": "https://novelsonline.net/",
|
||||
"lang": "English",
|
||||
"icon": "https://novelsonline.net/assets/images/logo.png?v=norm"
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user