Create v2

This commit is contained in:
Rajarshee Chatterjee
2021-09-21 22:20:26 +05:30
parent b1c1b960c9
commit 7825ac33f7
202 changed files with 6189 additions and 10785 deletions
+186
View File
@@ -0,0 +1,186 @@
import cheerio from "react-native-cheerio";
const sourceId = 59;
const sourceName = "ArNovel";
const baseUrl = "https://arnovel.me/";
const popularNovels = async (page) => {
let totalPages = 21;
let url = baseUrl + "novels/page/" + page;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".page-item-detail").each(function () {
const novelName = $(this).find(".h5 > a").text();
const novelCover =
"https://github.com/LNReader/lnreader-sources/blob/main/src/coverNotAvailable.jpg?raw=true";
let novelUrl = $(this).find(".h5 > a").attr("href").split("/")[4];
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}novel/${novelUrl}`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = { sourceId, sourceName, url, novelUrl };
novel.novelName = $(".post-title > h1")
.text()
.replace(/[\t\n]/g, "")
.trim();
novel.novelCover =
"https://github.com/LNReader/lnreader-sources/blob/main/src/coverNotAvailable.jpg?raw=true";
$(".post-content_item").each(function () {
detailName = $(this)
.find(".summary-heading > h5")
.text()
.replace(/[\t\n]/g, "")
.trim();
detail = $(this)
.find(".summary-content")
.text()
.replace(/[\t\n]/g, "")
.trim();
switch (detailName) {
case "التصنيفات":
novel.genre = detail.trim().replace(/[\t\n]/g, ",");
break;
case "المؤلف (ين)":
novel.author = detail.trim();
break;
case "الحالة":
novel.status = detail.trim();
break;
}
});
$(".description-summary > div.summary__content").find("em").remove();
novel.summary = $(".description-summary > div.summary__content")
.text()
.trim();
let novelChapters = [];
const novelId = $("#manga-chapters-holder").attr("data-id");
let formData = new FormData();
formData.append("action", "manga_get_chapters");
formData.append("manga", novelId);
const data = await fetch("https://www.arnovel.me/wp-admin/admin-ajax.php", {
method: "POST",
body: formData,
});
const text = await data.text();
$ = cheerio.load(text);
$(".wp-manga-chapter").each(function () {
chapterName = $(this)
.find("a")
.text()
.replace(/[\t\n]/g, "")
.trim();
releaseDate = $(this).find("span").text().trim();
chapterUrl = $(this).find("a").attr("href").split("/");
chapterUrl[6]
? (chapterUrl = chapterUrl[5] + "/" + chapterUrl[6])
: (chapterUrl = chapterUrl[5]);
novelChapters.push({ chapterName, releaseDate, chapterUrl });
});
novel.chapters = novelChapters.reverse();
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}novel/${novelUrl}/${chapterUrl}/`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
const chapterName = $("h1#chapter-heading").text();
const chapterText = $(".reading-content").html();
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".c-tabs-item__content").each(function () {
const novelName = $(this).find(".h4 > a").text();
const novelCover =
"https://github.com/LNReader/lnreader-sources/blob/main/src/coverNotAvailable.jpg?raw=true";
let novelUrl = $(this).find(".h4 > a").attr("href").split("/")[4];
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const ArNovelScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default ArNovelScraper;
+183
View File
@@ -0,0 +1,183 @@
import cheerio from "react-native-cheerio";
const baseUrl = "https://m.yushubo.com";
const popularNovels = async (page) => {
const url = `${baseUrl}/all/order/hits_week+desc.html?page=${page}`;
const totalPages = 5846;
const result = await fetch(url, {
headers: {
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
},
});
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".clearfix > li").each(function (result) {
const novelUrl =
$(this).find("a").attr("href").replace(".html", "").substring(1) +
"/";
const novelName = $(this).find("a").text();
let novelCover = $(this).find("img").attr("src");
novelCover = novelCover.includes("https://tva1.sinaimg.cn/")
? `${novelCover}`
: `${baseUrl}${novelCover}`;
const novel = {
sourceId: 52,
novelUrl,
novelName,
novelCover,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}/${novelUrl.slice(0, -1)}.html`;
const result = await fetch(url, {
headers: {
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
},
});
const body = await result.text();
$ = cheerio.load(body);
let novel = {};
novel.sourceId = 52;
novel.sourceName = "Yushubo";
novel.url = url;
novel.novelUrl = novelUrl;
novel.novelName = $("dd > h2").text();
novel.novelCover = $("dt > img").attr("src");
novel.summary = $("div.content > p").text();
let info = [];
$(".info a").each(function (result) {
info.push($(this).text());
});
novel.genre = info[0];
novel.author = info[1];
novel.artist = null;
novel.status = "Unknown";
let chapters = [];
$(".bookshelf-list a").each(function (result) {
let chapterUrl = $(this).attr("href").substring(1);
let chapterName = $(this).attr("title");
let releaseDate = null;
chapters.push({
chapterName,
releaseDate,
chapterUrl,
});
});
novel.chapters = chapters;
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}/${chapterUrl}`;
const result = await fetch(url, {
headers: {
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
},
});
const body = await result.text();
$ = cheerio.load(body);
const chapterName = $(".read-section h3").text();
let chapterText = $(".read-section").html();
const chapter = {
sourceId: 52,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const searchUrl = `${baseUrl}/search.html`;
const result = await fetch(searchUrl, {
method: "post",
body: JSON.stringify({ keyword: searchTerm }),
headers: {
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
"Content-Type": "application/json",
},
});
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".clearfix > li").each(function (result) {
let novelUrl =
$(this).find("a").attr("href").replace(".html", "").substring(1) +
"/";
const novelName = $(this).find("a").text();
let novelCover = $(this).find("img").attr("src");
novelCover = novelCover.includes("https://tva1.sinaimg.cn/")
? `${novelCover}`
: `${baseUrl}${novelCover}`;
const novel = {
sourceId: 52,
novelUrl,
novelName,
novelCover,
};
novels.push(novel);
});
return novels;
};
const YushuboScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default YushuboScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const YushuboScraper = require("./YushuboScraper");
const router = express.Router();
router.get("/novels/", YushuboScraper.novelsScraper);
router.get("/novel/:novelUrl", YushuboScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", YushuboScraper.chapterScraper);
router.get("/search/", YushuboScraper.searchScraper);
module.exports = router;
-177
View File
@@ -1,177 +0,0 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const UserAgent = require("user-agents");
const userAgent = new UserAgent();
const baseUrl = "https://m.yushubo.com";
const novelsScraper = async (req, res) => {
const url = `${baseUrl}/all/order/hits_week+desc.html`;
const result = await fetch(url, { headers: { "User-Agent": userAgent } });
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".clearfix > li").each(function (result) {
const novelUrl =
$(this).find("a").attr("href").replace(".html", "").substring(1) + "/";
const novelName = $(this).find("a").text();
const novelCover = $(this).find("img").attr("src");
const novel = {
extensionId: 50,
novelUrl,
novelName,
novelCover,
};
novels.push(novel);
});
res.json(novels);
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}/${novelUrl}.html`;
const result = await fetch(url, { headers: { "User-Agent": userAgent } });
const body = await result.text();
$ = cheerio.load(body);
let novel = {};
novel.extensionId = 50;
novel.sourceName = "Yushubo";
novel.sourceUrl = url;
novel.novelUrl = novelUrl + "/";
novel.novelName = $("dd > h2").text();
novel.novelCover = $("dt > img").attr("src");
novel.novelSummary = $("div.content > p").text();
let info = [];
$(".info a").each(function (result) {
info.push($(this).text());
});
novel["Author(s)"] = info[0];
novel["Genre(s)"] = info[1];
novel["Artist(s)"] = null;
novel.Status = "Unknown";
let chapters = [];
$(".bookshelf-list a").each(function (result) {
let chapterUrl = $(this).attr("href").substring(1);
let chapterName = $(this).attr("title");
let releaseDate = null;
chapters.push({
chapterName,
releaseDate,
chapterUrl,
});
});
novel.novelChapters = chapters;
res.json(novel);
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl.replace(".html/", "");
let chapterUrl = req.params.chapterUrl;
const url = `${baseUrl}/${chapterUrl}`;
const result = await fetch(url, { headers: { "User-Agent": userAgent } });
const body = await result.text();
$ = cheerio.load(body);
const chapterName = $(".read-section h3").text();
const chapterText = $(".read-section p").text();
let nextChapter = null;
if ($(".btn-next").attr("href")) {
nextChapter = $(".btn-prev").attr("href");
}
let prevChapter = null;
if ($(".btn-prev").attr("href")) {
prevChapter = $(".btn-prev").attr("href");
}
const chapter = {
extensionId: 50,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchUrl = `${baseUrl}/search.html`;
const result = await fetch(searchUrl, {
method: "post",
body: JSON.stringify({ keyword: searchTerm }),
headers: { "User-Agent": userAgent, "Content-Type": "application/json" },
});
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".clearfix > li").each(function (result) {
let novelUrl =
$(this).find("a").attr("href").replace(".html", "").substring(1) + "/";
const novelName = $(this).find("a").text();
let novelCover = $(this).find("img").attr("src");
novelCover = novelCover.startsWith("https://tva1.sinaimg.cn/")
? `${novelCover}`
: `${baseUrl}${novelCover}`;
const novel = {
extensionId: 50,
novelUrl,
novelName,
novelCover,
};
novels.push(novel);
});
res.json(novels);
};
module.exports = YushuboScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
};
Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

@@ -1,15 +1,13 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://boxnovel.com/novel";
const searchUrl = "https://boxnovel.com/";
const novelsScraper = async (req, res) => {
const orderBy = req.params.o;
const pageNo = req.params.pageNo;
const sourceId = 1;
let url = `${baseUrl}/page/1/?m_orderby=${orderBy}`;
const popularNovels = async (page) => {
let url = `${baseUrl}/page/${page}/?m_orderby=rating`;
let totalPages = 73;
const result = await fetch(url);
const body = await result.text();
@@ -26,7 +24,7 @@ const novelsScraper = async (req, res) => {
novelUrl = novelUrl.replace(`${baseUrl}/`, "");
const novel = {
extensionId: 1,
sourceId,
novelName,
novelCover,
novelUrl,
@@ -35,12 +33,11 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}/${novelUrl}/`;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}/${novelUrl}`;
console.log(url);
@@ -53,13 +50,13 @@ const novelScraper = async (req, res) => {
$(".post-title > h3 > span").remove();
novel.extensionId = 1;
novel.sourceId = 1;
novel.sourceName = "BoxNovel";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $(".post-title > h3")
.text()
@@ -80,44 +77,53 @@ const novelScraper = async (req, res) => {
.replace(/[\t\n]/g, "")
.trim();
novel[detailName] = detail;
switch (detailName) {
case "Genre(s)":
novel.genre = detail.trim().replace(/[\t\n]/g, ",");
break;
case "Author(s)":
novel.author = detail.trim();
break;
case "Artist(s)":
novel.status = detail.trim();
break;
}
});
$(".description-summary > div.summary__content").find("em").remove();
novel.novelSummary = $(".description-summary > div.summary__content > div")
novel.summary = $(".description-summary > div.summary__content")
.text()
.replace(/[\t\n]/g, "");
.replace(/[\t\n]|Description|Summary/g, "");
let novelChapters = [];
$(".wp-manga-chapter").each(function (result) {
chapterName = $(this)
const chapterName = $(this)
.find("a")
.text()
.replace(/[\t\n]/g, "")
.trim();
releaseDate = $(this)
const releaseDate = $(this)
.find("span")
.text()
.replace(/[\t\n]/g, "")
.trim();
chapterUrl = $(this).find("a").attr("href").replace(url, "");
const chapterUrl = $(this).find("a").attr("href").replace(url, "");
novelChapters.push({ chapterName, releaseDate, chapterUrl });
const chapter = { chapterName, releaseDate, chapterUrl };
novelChapters.push(chapter);
});
novel.novelChapters = novelChapters.reverse();
novel.chapters = novelChapters.reverse();
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}/${novelUrl}/${chapterUrl}`;
const result = await fetch(url);
@@ -127,47 +133,19 @@ const chapterScraper = async (req, res) => {
const chapterName = $("div.text-left > h3").text();
let chapterText = $(".reading-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($(".nav-next").length) {
nextChapter = $(".nav-next")
.find("a")
.attr("href")
.replace(baseUrl + "/" + novelUrl + "/", "");
}
let prevChapter = null;
if ($(".nav-previous").length) {
prevChapter = $(".nav-previous")
.find("a")
.attr("href")
.replace(baseUrl + "/" + novelUrl + "/", "");
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
const chapter = {
extensionId: 1,
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const orderBy = req.query.o;
const url = `${searchUrl}?s=${searchTerm}&post_type=wp-manga&m_orderby=${orderBy}`;
const searchNovels = async (searchTerm) => {
const url = `${searchUrl}?s=${searchTerm}&post_type=wp-manga&m_orderby=rating`;
const result = await fetch(url);
const body = await result.text();
@@ -184,7 +162,7 @@ const searchScraper = async (req, res) => {
novelUrl = novelUrl.replace(`${baseUrl}/`, "");
const novel = {
extensionId: 1,
sourceId,
novelName,
novelCover,
novelUrl,
@@ -193,12 +171,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = boxNovelScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const BoxNovelScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default BoxNovelScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const boxNovelScraper = require("./BoxNovelScraper");
const router = express.Router();
router.get("/novels/:pageNo", boxNovelScraper.novelsScraper);
router.get("/novel/:novelUrl", boxNovelScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", boxNovelScraper.chapterScraper);
router.get("/search/", boxNovelScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

+204
View File
@@ -0,0 +1,204 @@
import cheerio from "react-native-cheerio";
const sourceId = 27;
const sourceName = "Comrade Mao";
const baseUrl = "https://comrademao.com/";
const popularNovels = async (page) => {
let url = baseUrl + "novel/page/" + page;
const totalPages = 111;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$("div.container")
.find("section")
.each(function () {
const novelName = $(this)
.find("div.columns > div:nth-child(2) > a")
.text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this)
.find("div.columns > div:nth-child(2) > a")
.attr("href");
novelUrl = novelUrl.replace(baseUrl + "novel/", "");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { novels, totalPages };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = baseUrl + "novel/" + novelUrl;
console.log(url);
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = { sourceId, sourceName, url, novelUrl };
novel.novelName = $(
"#NovelInfo > div > div.column.is-one-third.has-text-centered > p"
)
.text()
.trim();
novel.novelCover = $("img.attachment-post-thumbnail").attr("src");
novel.summary = $("#NovelInfo > div > div:nth-child(2) > p").text().trim();
novel.genre = $("#NovelInfo > p:nth-child(2)")
.text()
.replace(/Genre(s):|\s/g, "");
novel.status = $("#NovelInfo > p:nth-child(5)")
.text()
.replace(/Status:|\s/g, "")
.trim();
novel.author = $("#NovelInfo > p:nth-child(4)")
.text()
.replace(/Publisher:|\s/g, "")
.trim();
let novelChapters = [];
// $("table > tbody")
// .find("tr")
// .each(function () {
// const releaseDate = $(this).find("span").text();
// const chapterName = $(this).find("a").text();
// const chapterUrl = $(this).find("a").attr("href").split("/")[5];
// novelChapters.push({
// chapterName,
// chapterUrl,
// releaseDate,
// });
// });
// $("small").remove();
let chapterUrlPrefix = $("table > tbody")
.find("tr")
.first()
.find("a")
.attr("href")
.slice(0, -1)
.split("/")
.pop()
.split("-");
chapterUrlPrefix.pop();
chapterUrlPrefix = chapterUrlPrefix.join("-").toLowerCase();
let latestChapter = $("table > tbody")
.find("tr")
.first()
.find("a")
.text()
.replace(/^\D+/g, "");
for (let i = 1; i <= latestChapter; i++) {
const chapterName = "Chapter " + i;
const releaseDate = null;
const chapterUrl = chapterUrlPrefix + "-" + i + "/";
const chapter = {
chapterName,
releaseDate,
chapterUrl,
};
novelChapters.push(chapter);
}
novel.chapters = novelChapters;
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}mtl/${novelUrl}/${chapterUrl}`;
console.log(url);
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let chapterName = "";
let chapterText = $("#content").html();
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const url = baseUrl + "?s=" + searchTerm + "&post_type=novel";
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".newbox")
.find("li")
.each(function () {
const novelName = $(this).find("h3").text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this).find("a").attr("href");
novelUrl = novelUrl.replace(baseUrl + "novel/", "");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const ComradeMaoScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default ComradeMaoScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const ComradeMaoScraper = require("./ComradeMaoScraper");
const router = express.Router();
router.get("/novels/", ComradeMaoScraper.novelsScraper);
router.get("/novel/:novelUrl", ComradeMaoScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", ComradeMaoScraper.chapterScraper);
router.get("/search/", ComradeMaoScraper.searchScraper);
module.exports = router;
-211
View File
@@ -1,211 +0,0 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { htmlToText } = require("html-to-text");
const { parseHtml } = require("../../helper");
const baseUrl = "https://comrademao.com/";
const novelsScraper = async (req, res) => {
let url = baseUrl;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$("article.blog-article").each(function (result) {
const novelName = $(this).find("h5 > a").text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this).find("h5 > a").attr("href");
novelUrl = novelUrl.replace(baseUrl + "novel/", "");
const novel = {
extensionId: 27,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
res.json(novels);
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = baseUrl + "novel/" + novelUrl;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = {};
novel.extensionId = 27;
novel.sourceName = "Comrade Mao";
novel.sourceUrl = url;
novel.novelUrl = novelUrl + "/";
function getNovelName(y) {
return y
.replace("-", " ")
.replace(/(?:^|\s)\S/g, (a) => a.toUpperCase());
}
novelName = getNovelName(novelUrl);
novel.novelName = novelName;
novel.novelCover = $("#thumbnail > img").attr("src");
let novelSummary = $("div#Description").html();
novel.novelSummary = htmlToText(novelSummary);
novel["Genre(s)"] = $("div#Genre")
.text()
.replace(/Genre:|\s/g, "");
novel.Status = $("div#Status")
.text()
.replace(/Status:|\s/g, "");
novel["Author(s)"] = $("div#Publisher")
.text()
.replace(/Publisher:|\s/g, "");
// novel['Genre(s)'] = $("div#Genre").
let novelChapters = [];
let chapterUrlPrefix = $("tbody > tr")
.first()
.next()
.find("td > a")
.text()
.split(" ");
chapterUrlPrefix.pop();
chapterUrlPrefix = chapterUrlPrefix.join("-").toLowerCase();
const latestChapter = $("tbody > tr")
.first()
.next()
.find("td > a")
.text()
.replace(/^\D+/g, "");
for (let i = 1; i <= latestChapter; i++) {
const chapterName = "Chapter " + i;
const releaseDate = null;
const chapterUrl = chapterUrlPrefix + "-" + i + "/";
const chapter = {
chapterName,
releaseDate,
chapterUrl,
};
novelChapters.push(chapter);
}
novel.novelChapters = novelChapters;
res.json(novel);
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const url = `${baseUrl}mtl/${novelUrl}/${chapterUrl}`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let chapterName = $(".entry-title").text();
let chapterText = $(".entry-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($(".nav-next").find("a").length) {
nextChapter = $(".nav-next")
.find("a")
.attr("href")
.replace(baseUrl + "mtl/" + novelUrl + "/", "");
}
let prevChapter = null;
if ($(".nav-previous").find("a").length) {
prevChapter = $(".nav-previous")
.find("a")
.attr("href")
.replace(baseUrl + "mtl/" + novelUrl + "/", "");
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
const chapter = {
extensionId: 27,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const url = baseUrl + "?s=" + searchTerm + "&post_type=novel";
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$("article.blog-article").each(function (result) {
const novelName = $(this).find("h5 > a").text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this).find("h5 > a").attr("href");
novelUrl = novelUrl.replace(baseUrl + "novel/", "");
const novel = {
extensionId: 27,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
res.json(novels);
};
module.exports = vipNovelScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
};
Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

+152
View File
@@ -0,0 +1,152 @@
import cheerio from "react-native-cheerio";
const sourceId = 70;
const sourceName = "Divine Dao Library";
const baseUrl = "https://www.divinedaolibrary.com/";
const popularNovels = async (page) => {
let url = baseUrl + "novels";
const totalPages = 1;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$("#main")
.find("li")
.each(function () {
const novelName = $(this).find("a").text();
const novelCover = null;
const novelUrl = $(this).find(" a").attr("href");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { novels, totalPages };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = novelUrl;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = { sourceId, sourceName, url, novelUrl };
novel.novelName = $("h1.entry-title").text().trim();
novel.novelCover =
$(".entry-content").find("img").attr("src") ||
"https://github.com/LNReader/lnreader-sources/blob/main/src/coverNotAvailable.jpg?raw=true";
novel.summary = $("#main > article > div > p:nth-child(6)").text().trim();
novel.genre = null;
novel.status = null;
novel.author = $("#main > article > div > h3:nth-child(2)")
.text()
.replace(/Author:/g, "")
.trim();
let novelChapters = [];
$("#main")
.find("li > span > a")
.each(function () {
const chapterName = $(this).text().trim();
const releaseDate = null;
const chapterUrl = $(this).attr("href");
novelChapters.push({ chapterName, releaseDate, chapterUrl });
});
novel.chapters = novelChapters;
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const url = chapterUrl;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let chapterName = $(".entry-title").text().trim();
let chapterText = $(".entry-content").html();
if (!chapterText) {
chapterText = $(".page-header").html();
}
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
let url = baseUrl + "novels";
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$("#main")
.find("li")
.each(function () {
const novelName = $(this).find("a").text();
const novelCover = null;
const novelUrl = $(this).find(" a").attr("href");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
novels = novels.filter((novel) =>
novel.novelName.toLowerCase().includes(searchTerm.toLowerCase())
);
return novels;
};
const DivineDaoLibraryScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default DivineDaoLibraryScraper;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

@@ -1,13 +1,14 @@
const cheerio = require("cheerio");
const { scraper } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://fastnovel.net";
const searchUrl = `https://fastnovel.net/search/`;
const novelsScraper = async (req, res) => {
const url = `${baseUrl}/list/most-popular.html`;
const popularNovels = async (page) => {
let totalPages = 39;
const url = `${baseUrl}/list/most-popular.html?page=${page}`;
const body = await scraper(url);
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
@@ -19,7 +20,7 @@ const novelsScraper = async (req, res) => {
const novelUrl = $(this).find("a").attr("href").substring(1);
const novel = {
extensionId: 3,
sourceId: 3,
novelName,
novelCover,
novelUrl,
@@ -28,50 +29,59 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}/${novelUrl}/`;
const body = await scraper(url);
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = {};
novel.extensionId = 3;
novel.sourceId = 3;
novel.sourceName = "FastNovel";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = novelUrl + "/";
novel.novelUrl = novelUrl;
novel.novelName = $("h1").text();
novel.novelCover = $(".book-cover").attr("data-original");
novel.novelSummary = $("div.film-content > p").text();
novel.summary = $("div.film-content > p").text();
novel["Author(s)"] = $("li > label")
novel.author = $("li > label")
.filter(function () {
return $(this).text().trim() === "Author:";
})
.next()
.text();
novel["Genre(s)"] = $("li")
novel.genre = $("li")
.filter(function () {
return $(this).find("label").text().trim() === "Genre:";
})
.text()
.replace("Genre:", "");
novel["Artist(s)"] = null;
novel.artist = null;
novel.Status = null;
novel.status = null;
novel.status = $("li")
.filter(function () {
return $(this).find("label").text().trim() === "Status:";
})
.text()
.includes("Completed")
? "Completed"
: "Ongoing";
let novelChapters = [];
@@ -90,64 +100,38 @@ const novelScraper = async (req, res) => {
novelChapters.push(novel);
});
novel.novelChapters = novelChapters;
novel.chapters = novelChapters;
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}/${novelUrl}/${chapterUrl}`;
const body = await scraper(url);
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
const chapterName = $(".episode-name").text();
const chapterText = $("#chapter-body").text();
let nextChapter = null;
nextChapter = $("div.btn-group > a")
.filter(function () {
return $(this).text().trim() === "Next Chapter";
})
.attr("href")
.replace("/", "");
let prevChapter = null;
prevChapter = $("div.btn-group > a")
.filter(function () {
return $(this).text().trim() === "Prev Chapter";
})
.attr("href")
.replace("/", "");
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
let chapterText = $("#chapter-body").html();
const chapter = {
extensionId: 3,
sourceId: 3,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = `${searchUrl}${searchTerm}`;
const body = await scraper(url);
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
@@ -159,7 +143,7 @@ const searchScraper = async (req, res) => {
const novelUrl = $(this).find("a").attr("href").substring(1);
const novel = {
extensionId: 3,
sourceId: 3,
novelName,
novelCover,
novelUrl,
@@ -168,12 +152,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = fastNovelScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const fastNovelScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default fastNovelScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const fastNovelScraper = require("./FastNovelScraper");
const router = express.Router();
router.get("/novels/", fastNovelScraper.novelsScraper);
router.get("/novel/:novelUrl", fastNovelScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", fastNovelScraper.chapterScraper);
router.get("/search/", fastNovelScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

@@ -1,12 +1,10 @@
const cheerio = require("cheerio");
const FormData = require("form-data");
const fetch = require("node-fetch");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://foxaholic.com/";
const novelsScraper = async (req, res) => {
let url = baseUrl + "novel/?m_orderby=rating";
const popularNovels = async (page) => {
let totalPages = 5;
let url = baseUrl + "novel/page/" + page + "/?m_orderby=rating";
const result = await fetch(url);
const body = await result.text();
@@ -23,7 +21,7 @@ const novelsScraper = async (req, res) => {
novelUrl += "/";
const novel = {
extensionId: 22,
sourceId: 22,
novelName,
novelCover,
novelUrl,
@@ -32,12 +30,11 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}novel/${novelUrl}/`;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}novel/${novelUrl}`;
const result = await fetch(url);
const body = await result.text();
@@ -46,13 +43,13 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 22;
novel.sourceId = 22;
novel.sourceName = "Foxaholic";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $(".post-title > h1")
.text()
@@ -73,22 +70,24 @@ const novelScraper = async (req, res) => {
.replace(/[\t\n]/g, "")
.trim();
novel[detailName] = detail;
switch (detailName) {
case "Genre":
novel.genre = detail.trim().replace(/[\t\n]/g, ",");
break;
case "Author":
novel.author = detail.trim();
break;
case "Novel":
novel.status = detail.trim();
break;
}
});
novel["Genre(s)"] = novel.Genre.replace(/, /g, ",");
novel["Author(s)"] = novel.Author;
novel.Status = null;
novel["Artist(s)"] = null;
delete novel.Genre;
delete novel.Author;
$(".description-summary > div.summary__content").find("em").remove();
novel.novelSummary = $(".description-summary > div.summary__content")
novel.summary = $(".description-summary > div.summary__content")
.text()
.replace(/[\t\n]/g, "");
.trim();
let novelChapters = [];
@@ -127,25 +126,13 @@ const novelScraper = async (req, res) => {
novelChapters.push({ chapterName, releaseDate, chapterUrl });
});
novel.novelChapters = novelChapters.reverse();
novel.chapters = novelChapters.reverse();
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
let volumeUrl = req.params.volumeUrl;
let optionalUrl;
if (volumeUrl) {
optionalUrl = volumeUrl + "/";
} else {
optionalUrl = "";
}
const url = `${baseUrl}novel/${novelUrl}/${optionalUrl}${chapterUrl}/`;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}novel/${novelUrl}${chapterUrl}/`;
const result = await fetch(url);
const body = await result.text();
@@ -154,45 +141,18 @@ const chapterScraper = async (req, res) => {
const chapterName = $("h1#chapter-heading").text();
let chapterText = $(".reading-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($(".nav-next").length) {
nextChapter = $(".nav-next").find("a").attr("href").split("/");
nextChapter[6]
? (nextChapter = nextChapter[5] + "/" + nextChapter[6])
: (nextChapter = nextChapter[5]);
}
let prevChapter = null;
if ($(".nav-previous").length) {
prevChapter = $(".nav-previous").find("a").attr("href").split("/");
prevChapter[6]
? (prevChapter = prevChapter[5] + "/" + prevChapter[6])
: (prevChapter = prevChapter[5]);
}
novelUrl += "/";
chapterUrl = optionalUrl + chapterUrl;
const chapter = {
extensionId: 22,
sourceId: 22,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`;
const result = await fetch(url);
@@ -209,7 +169,7 @@ const searchScraper = async (req, res) => {
let novelUrl = $(this).find(".h4 > a").attr("href").split("/")[4];
novelUrl += "/";
const novel = {
extensionId: 22,
sourceId: 22,
novelName,
novelCover,
novelUrl,
@@ -218,12 +178,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = novelTrenchScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const FoxaHolicScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default FoxaHolicScraper;
-16
View File
@@ -1,16 +0,0 @@
const express = require("express");
const FoxaholicScraper = require("./FoxaholicScraper");
const router = express.Router();
router.get("/novels/", FoxaholicScraper.novelsScraper);
router.get("/novel/:novelUrl", FoxaholicScraper.novelScraper);
router.get(
"/novel/:novelUrl/:volumeUrl?/:chapterUrl",
FoxaholicScraper.chapterScraper
);
router.get("/search/", FoxaholicScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

+183
View File
@@ -0,0 +1,183 @@
import cheerio from "react-native-cheerio";
const baseUrl = "https://freewebnovel.com/";
const popularNovels = async (page) => {
let totalPages = 30;
let url = baseUrl + "completed-novel/" + page;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".li-row").each(function (result) {
const novelName = $(this).find(".tit").text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this)
.find("h3 > a")
.attr("href")
.replace(".html", "")
.slice(1);
const novel = {
sourceId: 13,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}${novelUrl.replace("/", "")}.html`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = {};
novel.sourceId = 13;
novel.sourceName = "FreeWebNovel";
novel.url = url;
novel.novelUrl = novelUrl;
novel.novelName = $("h1.tit").text();
novel.novelCover = $(".pic > img").attr("src");
novel.genre = $("[title=Genre]")
.next()
.text()
.replace(/[\t\n]/g, "");
novel.author = $("[title=Author]")
.next()
.text()
.replace(/[\t\n]/g, "");
novel.artist = null;
novel.status = $("[title=Status]")
.next()
.text()
.replace(/[\t\n]/g, "");
let novelSummary = $(".inner").text().trim();
novel.summary = novelSummary;
let novelChapters = [];
let latestChapter;
$("h3.tit").each(function (res) {
if ($(this).find("a").text() === novel.novelName) {
latestChapter = $(this).next().find("span.s3").text().match(/\d+/);
}
});
latestChapter = latestChapter[0];
for (let i = 1; i <= parseInt(latestChapter); i++) {
const chapterName = "Chapter " + i;
const releaseDate = null;
const chapterUrl = "chapter-" + i;
const chapter = { chapterName, releaseDate, chapterUrl };
novelChapters.push(chapter);
}
novel.chapters = novelChapters;
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
let novelId = novelUrl.replace("/", "");
const url = `${baseUrl}${novelId}/${chapterUrl}.html`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let chapterName = $("h1.tit").text();
let chapterText = $("div.txt").html();
const chapter = {
sourceId: 13,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const url = baseUrl + "search/";
const formData = new FormData();
formData.append("searchkey", searchTerm);
const result = await fetch(url, {
method: "POST",
body: formData,
});
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".li-row > .li > .con").each(function (result) {
const novelName = $(this).find(".tit").text();
const novelCover = $(this).find(".pic > a > img").attr("data-cfsrc");
let novelUrl = $(this)
.find("h3 > a")
.attr("href")
.replace(".html", "")
.slice(1);
novelUrl += "/";
const novel = {
sourceId: 13,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const FreeWebNovelScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default FreeWebNovelScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const freeWebNovelScraper = require("./FreeWebNovelScraper");
const router = express.Router();
router.get("/novels/", freeWebNovelScraper.novelsScraper);
router.get("/novel/:novelUrl", freeWebNovelScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", freeWebNovelScraper.chapterScraper);
router.get("/search/", freeWebNovelScraper.searchScraper);
module.exports = router;
-218
View File
@@ -1,218 +0,0 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const request = require("request");
const { htmlToText } = require("html-to-text");
const { parseHtml } = require("../../helper");
const baseUrl = "https://freewebnovel.com/";
const novelsScraper = async (req, res) => {
let url = baseUrl + "most-popular-novel/";
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".li-row").each(function (result) {
const novelName = $(this).find(".tit").text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this)
.find("h3 > a")
.attr("href")
.replace(".html", "")
.slice(1);
novelUrl += "/";
const novel = {
extensionId: 13,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
res.json(novels);
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}${novelUrl}.html`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = {};
novel.extensionId = 13;
novel.sourceName = "FreeWebNovel";
novel.sourceUrl = url;
novel.novelUrl = `${novelUrl.replace(".html", "")}/`;
novel.novelName = $("h1.tit").text();
novel.novelCover = $(".pic > img").attr("src");
novel["Genre(s)"] = $("[title=Genre]")
.next()
.text()
.replace(/[\t\n]/g, "");
novel["Author(s)"] = $("[title=Author]")
.next()
.text()
.replace(/[\t\n]/g, "");
novel["Artist(s)"] = null;
novel.Status = $("[title=Status]")
.next()
.text()
.replace(/[\t\n]/g, "");
novel.Alternative = $("[title='Alternative names']")
.next()
.text()
.replace(/[\t\n]/g, "");
let novelSummary = $(".inner").html();
novel.novelSummary = htmlToText(novelSummary);
let novelChapters = [];
let latestChapter;
$("h3.tit").each(function (res) {
if ($(this).find("a").text() === novel.novelName) {
// console.log($(this).find("a").text());
// console.log(novel.novelName);
latestChapter = $(this).next().find("span.s3").text().match(/\d+/);
}
});
latestChapter = latestChapter[0];
for (let i = 1; i <= parseInt(latestChapter); i++) {
const chapterName = "Chapter " + i;
const releaseDate = null;
const chapterUrl = "chapter-" + i;
const chapter = { chapterName, releaseDate, chapterUrl };
novelChapters.push(chapter);
}
novel.novelChapters = novelChapters;
res.json(novel);
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const url = `${baseUrl}${novelUrl}/${chapterUrl}.html`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let chapterName = $("h1.tit").text();
let chapterText = $("div.txt").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($("[title='Read Next chapter']").length) {
nextChapter = $("[title='Read Next chapter']")
.attr("href")
.replace("/" + novelUrl + "/", "")
.replace(".html", "");
}
let prevChapter = null;
if ($("[title='Read Privious Chapter']").length) {
prevChapter = $("[title='Read Privious Chapter']")
.attr("href")
.replace("/" + novelUrl + "/", "")
.replace(".html", "");
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl;
const chapter = {
extensionId: 13,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const url = baseUrl + "search/";
request.post(
{ url, form: { searchkey: searchTerm } },
(err, response, body) => {
$ = cheerio.load(body);
let novels = [];
$(".li-row > .li > .con").each(function (result) {
const novelName = $(this).find(".tit").text();
const novelCover = $(this)
.find(".pic > a > img")
.attr("data-cfsrc");
let novelUrl = $(this)
.find("h3 > a")
.attr("href")
.replace(".html", "")
.slice(1);
novelUrl += "/";
const novel = {
extensionId: 13,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
res.json(novels);
}
);
};
module.exports = vipNovelScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
};
Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

@@ -1,12 +1,13 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://jpmtl.com/";
const novelsScraper = async (req, res) => {
const popularNovels = async (page) => {
let totalPages = 157;
let url =
"https://jpmtl.com/v2/book/show/browse?query=&categories=&content_type=0&direction=0&page=2&limit=20&type=5&status=all&language=3&exclude_categories=";
"https://jpmtl.com/v2/book/show/browse?query=&categories=&content_type=0&direction=0&page=" +
page +
"&limit=20&type=5&status=all&language=3&exclude_categories=";
const result = await fetch(url);
const body = await result.json();
@@ -18,16 +19,15 @@ const novelsScraper = async (req, res) => {
const novelCover = item.cover;
const novelUrl = item.id + "/";
const novel = { extensionId: 14, novelName, novelCover, novelUrl };
const novel = { sourceId: 14, novelName, novelCover, novelUrl };
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}books/${novelUrl}`;
const result = await fetch(url);
@@ -37,13 +37,13 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 14;
novel.sourceId = 14;
novel.sourceName = "JPMTL";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $("h1.book-sidebar__title").text();
@@ -64,18 +64,28 @@ const novelScraper = async (req, res) => {
novel[detailName] = detail;
});
novel.novelSummary = $(".main-book__synopsis").text();
novel.summary = $(".main-book__synopsis").text();
novel["Genre(s)"] = "";
novel.genre = "";
$("a.main-book__category").each(function (result) {
novel["Genre(s)"] += $(this).text();
novel.genre += $(this).text();
});
novel["Author(s)"] = $(".book-sidebar__author > .book-sidebar__info")
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
const info = $(".book-sidebar__author > .book-sidebar__info")
.text()
.replace(/[\t\n]/g, "")
.trim();
.trim()
.split("・");
if (info) {
novel.author = info[0];
novel.status = capitalizeFirstLetter(info[1]);
}
let novelChapters = [];
@@ -91,7 +101,7 @@ const novelScraper = async (req, res) => {
const chapterUrl = chapter.id;
const obj = {
extensionId: 14,
sourceId: 14,
chapterName,
releaseDate,
chapterUrl,
@@ -101,60 +111,35 @@ const novelScraper = async (req, res) => {
});
});
novel.novelChapters = novelChapters;
novel.chapters = novelChapters;
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const url = `${baseUrl}books/${novelUrl}/${chapterUrl}`;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}books/${novelUrl}${chapterUrl}`;
const result = await fetch(url);
const body = await result.text();
console.log(url);
$ = cheerio.load(body);
const chapterName = $(".chapter-content__title").text();
let chapterText = $(".chapter-content__content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
let prevChapter = null;
$(".chapter-wrapper__nav").each(function (result) {
const chId = $(this)
.attr("href")
.replace("/books/" + novelUrl + "/", "");
if (chId < chapterUrl) {
prevChapter = chId;
} else {
nextChapter = chId;
}
});
novelUrl += "/";
const chapter = {
extensionId: 14,
sourceId: 14,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = `https://jpmtl.com/v2/book/show/browse?query=${searchTerm}&categories=&content_type=2&direction=0&page=1&limit=20&type=5&status=all&language=3&exclude_categories=`;
const result = await fetch(url);
@@ -167,17 +152,19 @@ const searchScraper = async (req, res) => {
const novelCover = item.cover;
const novelUrl = item.id + "/";
const novel = { extensionId: 14, novelName, novelCover, novelUrl };
const novel = { sourceId: 14, novelName, novelCover, novelUrl };
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = novelTrenchScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const JPMTLScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default JPMTLScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const JPMTLScraper = require("./JPMTLScraper");
const router = express.Router();
router.get("/novels/", JPMTLScraper.novelsScraper);
router.get("/novel/:novelUrl", JPMTLScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", JPMTLScraper.chapterScraper);
router.get("/search/", JPMTLScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

@@ -1,11 +1,12 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://kisslightnovels.info/";
const novelsScraper = async (req, res) => {
const result = await fetch(baseUrl);
const popularNovels = async (page) => {
let totalPages = 26;
const url = `${baseUrl}light-novel/page/${page}`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
@@ -20,7 +21,7 @@ const novelsScraper = async (req, res) => {
novelUrl = novelUrl.replace(`${baseUrl}novel/`, "");
const novel = {
extensionId: 11,
sourceId: 11,
novelName,
novelCover,
novelUrl,
@@ -29,12 +30,11 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}novel/${novelUrl}/`;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}novel/${novelUrl}`;
const result = await fetch(url);
const body = await result.text();
@@ -43,13 +43,13 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 11;
novel.sourceId = 11;
novel.sourceName = "KissLightNovels";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $(".post-title > h1")
.text()
@@ -70,12 +70,22 @@ const novelScraper = async (req, res) => {
.replace(/[\t\n]/g, "")
.trim();
novel[detailName] = detail;
switch (detailName) {
case "Genre(s)":
novel.genre = detail.trim().replace(/[\t\n]/g, ",");
break;
case "Author(s)":
novel.author = detail.trim();
break;
case "Artist(s)":
novel.status = detail.trim();
break;
}
});
$(".description-summary > div.summary__content").find("em").remove();
novel.novelSummary = $(".description-summary > div.summary__content")
novel.summary = $(".description-summary > div.summary__content")
.text()
.replace(/[\t\n]/g, "");
@@ -99,15 +109,12 @@ const novelScraper = async (req, res) => {
novelChapters.push({ chapterName, releaseDate, chapterUrl });
});
novel.novelChapters = novelChapters.reverse();
novel.chapters = novelChapters.reverse();
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}novel/${novelUrl}/${chapterUrl}`;
const result = await fetch(url);
@@ -118,46 +125,20 @@ const chapterScraper = async (req, res) => {
$("#snippet-box").remove();
const chapterName = $("div.text-left > h4").text();
let chapterText = $(".reading-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($(".nav-next").length) {
nextChapter = $(".nav-next")
.find("a")
.attr("href")
.replace(baseUrl + "novel/" + novelUrl + "/", "");
}
let prevChapter = null;
if ($(".nav-previous").length) {
prevChapter = $(".nav-previous")
.find("a")
.attr("href")
.replace(baseUrl + "novel/" + novelUrl + "/", "");
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
const chapter = {
extensionId: 11,
sourceId: 11,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga&m_orderby=rating`;
const result = await fetch(url);
@@ -175,7 +156,7 @@ const searchScraper = async (req, res) => {
novelUrl = novelUrl.replace(`${baseUrl}novel/`, "");
const novel = {
extensionId: 11,
sourceId: 11,
novelName,
novelCover,
novelUrl,
@@ -184,12 +165,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = kissLightNovelScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const kissLightNovelScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default kissLightNovelScraper;
-17
View File
@@ -1,17 +0,0 @@
const express = require("express");
const kissLightNovelsScraper = require("./KissLightNovelsScraper");
const router = express.Router();
router.get("/novels/", kissLightNovelsScraper.novelsScraper);
router.get("/novel/:novelUrl", kissLightNovelsScraper.novelScraper);
router.get(
"/novel/:novelUrl/:chapterUrl",
kissLightNovelsScraper.chapterScraper
);
router.get("/search/", kissLightNovelsScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

+215
View File
@@ -0,0 +1,215 @@
import cheerio from "react-native-cheerio";
const baseUrl = "https://www.lightnovelpub.com/";
const popularNovels = async (page) => {
let totalPages = 33;
let url = baseUrl + "browse/all/popular/all/" + page;
let headers = new Headers({
Accept: "application/json",
"Content-Type": "application/json",
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
});
const result = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".novel-item.ads").remove();
$(".novel-item").each(function () {
const novelName = $(this)
.find(".novel-title")
.text()
.replace(/[\t\n]/g, "");
const novelCover = $(this).find("img").attr("data-src");
let novelUrl = $(this)
.find(".novel-title > a")
.attr("href")
.replace(`/novel/`, "");
novelUrl += "/";
const novel = {
sourceId: 15,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}novel/${novelUrl}/`;
let headers = new Headers({
Accept: "application/json",
"Content-Type": "application/json",
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
});
const result = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
$ = cheerio.load(body);
let novel = {};
novel.sourceId = 15;
novel.sourceName = "LightNovelPub";
novel.url = url;
novel.novelUrl = novelUrl;
novel.novelName = $("h1.novel-title")
.text()
.replace(/[\t\n]/g, "")
.trim();
novel.novelCover = $("figure.cover > img").attr("data-src");
novel.genre = "";
$("div.categories > ul > li").each(function () {
novel.genre +=
$(this)
.text()
.replace(/[\t\n]/g, "") + ",";
});
$("div.header-stats > span").each(function () {
if ($(this).find("small").text() === "Status") {
novel.status = $(this).find("strong").text();
}
});
novel.genre = novel.genre.slice(0, -1);
novel.author = $(".author > a > span").text();
novel.summary = $(".summary > .content").text().trim();
let novelChapters = [];
let totalChapters;
totalChapters = $(".header-stats > span").first().text().match(/\d+/)[0];
for (let i = 1; i <= totalChapters; i++) {
const chapterName = "Chapter " + i;
const releaseDate = null;
const chapterUrl = "chapter-" + i;
const chapter = { chapterName, releaseDate, chapterUrl };
novelChapters.push(chapter);
}
novel.chapters = novelChapters;
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}novel/${novelUrl}/${chapterUrl}`;
let headers = new Headers({
Accept: "application/json",
"Content-Type": "application/json",
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
});
const result = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
$ = cheerio.load(body);
const chapterName = $("h2").text();
let chapterText = $("#chapter-container").html();
const chapter = {
sourceId: 15,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const url = `${baseUrl}lnwsearchlive?inputContent=${searchTerm}`;
let headers = new Headers({
Accept: "application/json",
"Content-Type": "application/json",
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
});
const result = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
let results = JSON.parse($("body").text());
$ = cheerio.load(results.resultview);
$(".novel-item").each(function () {
const novelName = $(this).find("h4.novel-title").text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this).find("a").attr("href").replace(`/novel/`, "");
novelUrl += "/";
const novel = {
sourceId: 15,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const lightNovelPubScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default lightNovelPubScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const lightNovelPubScraper = require("./LightNovelPubScraper");
const router = express.Router();
router.get("/novels/", lightNovelPubScraper.novelsScraper);
router.get("/novel/:novelUrl", lightNovelPubScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", lightNovelPubScraper.chapterScraper);
router.get("/search/", lightNovelPubScraper.searchScraper);
module.exports = router;
@@ -1,204 +0,0 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { htmlToText } = require("html-to-text");
const { parseHtml } = require("../../helper");
const { scraper } = require("../../helper");
const baseUrl = "https://www.lightnovelpub.com/";
const novelsScraper = async (req, res) => {
let url = baseUrl + "browse/all/popular/all/1";
const body = await scraper(url);
$ = cheerio.load(body);
let novels = [];
$(".novel-item.ads").remove();
$(".novel-item").each(function (result) {
const novelName = $(this)
.find(".novel-title")
.text()
.replace(/[\t\n]/g, "");
const novelCover = $(this).find("img").attr("data-src");
let novelUrl = $(this)
.find(".novel-title > a")
.attr("href")
.replace(`/novel/`, "");
novelUrl += "/";
const novel = {
extensionId: 15,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
res.json(novels);
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}novel/${novelUrl}/`;
const body = await scraper(url);
$ = cheerio.load(body);
let novel = {};
novel.extensionId = 15;
novel.sourceName = "LightNovelPub";
novel.sourceUrl = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelName = $("h1.novel-title")
.text()
.replace(/[\t\n]/g, "")
.trim();
novel.novelCover = $("figure.cover > img").attr("src");
novel["Genre(s)"] = "";
$("div.categories > ul > li").each(function (result) {
novel["Genre(s)"] +=
$(this)
.text()
.replace(/[\t\n]/g, "") + ",";
});
$("div.header-stats > span").each(function (result) {
if ($(this).find("small").text() === "Status") {
novel.Status = $(this).find("strong").text();
}
});
novel["Genre(s)"] = novel["Genre(s)"].slice(0, -1);
novel["Author(s)"] = $(".author > a > span").text();
novelSummary = $(".summary > .content").html();
novel.novelSummary = htmlToText(novelSummary);
let novelChapters = [];
let firstChapterNo, totalChapters;
totalChapters = $(".header-stats > span").first().text().match(/\d+/)[0];
firstChapterNo = $(".chapter-no").first().text().match(/\d+/)[0];
for (let i = firstChapterNo; i <= totalChapters; i++) {
const chapterName = "Chapter " + i;
const releaseDate = null;
const chapterUrl = "chapter-" + i;
const chapter = { chapterName, releaseDate, chapterUrl };
novelChapters.push(chapter);
}
novel.novelChapters = novelChapters;
res.json(novel);
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const url = `${baseUrl}novel/${novelUrl}/${chapterUrl}`;
const body = await scraper(url);
$ = cheerio.load(body);
const chapterName = $("h2").text();
let chapterText = $("#chapter-container").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if (!$("a.nextchap.isDisabled").length) {
nextChapter = $("a.nextchap")
.attr("href")
.replace("/novel/" + novelUrl + "/", "");
}
let prevChapter = null;
if (!$("a.prevchap.isDisabled").length) {
prevChapter = $("a.prevchap")
.attr("href")
.replace("/novel/" + novelUrl + "/", "");
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
const chapter = {
extensionId: 15,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const url = `${baseUrl}lnwsearchlive?inputContent=${searchTerm}`;
const result = await scraper(url);
$ = cheerio.load(result);
let novels = [];
let results = JSON.parse($("body").text());
$ = cheerio.load(results.resultview);
$(".novel-item").each(function (result) {
const novelName = $(this).find("h4.novel-title").text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this).find("a").attr("href").replace(`/novel/`, "");
novelUrl += "/";
const novel = {
extensionId: 15,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
res.json(novels);
};
module.exports = lightNovelPubScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
};
Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

+159
View File
@@ -0,0 +1,159 @@
import cheerio from "react-native-cheerio";
import NovelUpdatesScraper from "./novelupdates";
const sourceId = 72;
const sourceName = "LightNovelUpdates";
const baseUrl = "https://www.lightnovelupdates.com/";
const popularNovels = async (page) => {
let url = `${baseUrl}novel/page/${page}/?m_orderby=rating`;
let totalPages = 500;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".page-item-detail").each(function () {
const novelName = $(this).find(".h5 > a").text();
const novelCover = $(this).find("img").attr("src");
const novelUrl = $(this).find(".h5 > a").attr("href");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = novelUrl;
console.log(url);
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = { sourceId, sourceName, novelUrl, url };
novel.novelName = $(".post-title > h1").text().trim();
novel.novelCover =
$(".summary_image > a > img").attr("src") ||
"https://github.com/LNReader/lnreader-sources/blob/main/src/coverNotAvailable.jpg?raw=true";
$(".post-content_item").each(function (result) {
detailName = $(this).find(".summary-heading > h5").text().trim();
detail = $(this).find(".summary-content").text().trim();
switch (detailName) {
case "Genre(s)":
novel.genre = detail.trim().replace(/[\t\n]/g, ",");
break;
case "Author(s)":
novel.author = detail.trim();
break;
case "Artist(s)":
novel.status = detail.trim();
break;
}
});
novel.summary = $("div.summary__content").text();
let novelChapters = [];
const novelId = $(".rating-post-id").attr("value");
let formData = new FormData();
formData.append("action", "manga_get_chapters");
formData.append("manga", novelId);
const data = await fetch(
"https://www.lightnovelupdates.com/wp-admin/admin-ajax.php",
{
method: "POST",
body: formData,
}
);
const text = await data.text();
$ = cheerio.load(text);
$(".wp-manga-chapter").each(function () {
const chapterName = $(this).find("a").text().trim();
const releaseDate = $(this).find("span").text().trim();
const chapterUrl = $(this).find("a").attr("href");
const chapter = { chapterName, releaseDate, chapterUrl };
novelChapters.push(chapter);
});
novel.chapters = novelChapters.reverse();
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const chapterName = "";
const chapterText = (
await NovelUpdatesScraper.parseChapter(novelUrl, chapterUrl)
).chapterText;
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga&m_orderby=rating`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".c-tabs-item__content").each(function (result) {
const novelName = $(this).find(".h4 > a").text();
const novelCover = $(this).find("img").attr("src");
const novelUrl = $(this).find(".h4 > a").attr("href");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const LightNovelUpdatesScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default LightNovelUpdatesScraper;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

@@ -1,11 +1,12 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
import { showToast } from "../../hooks/showToast";
import { htmlToText } from "../helpers/htmlToText";
const baseUrl = "https://lnmtl.com/";
const novelsScraper = async (req, res) => {
let url = baseUrl + "novel?page=1"; // + page;
const popularNovels = async (page) => {
const totalPages = 63;
let url = baseUrl + "novel?page=" + page;
const result = await fetch(url);
const body = await result.text();
@@ -22,7 +23,7 @@ const novelsScraper = async (req, res) => {
novelUrl = novelUrl.replace(baseUrl + "novel/", "");
const novel = {
extensionId: 37,
sourceId: 37,
novelName,
novelCover,
novelUrl,
@@ -31,11 +32,12 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
showToast("LNMTL might take around 20-30 seconds.");
const url = baseUrl + "novel/" + novelUrl;
const result = await fetch(url);
@@ -45,11 +47,11 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 37;
novel.sourceId = 37;
novel.sourceName = "LNMTL";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = novelUrl;
@@ -57,19 +59,19 @@ const novelScraper = async (req, res) => {
novel.novelCover = $("div.novel").find("img").attr("src");
novel.novelSummary = $("div.description").text().trim();
novel.summary = $("div.description").text().trim();
novel["Author(s)"] = $(
novel.author = $(
"main > div:nth-child(3) > div > div.col-lg-3.col-md-4 > div:nth-child(2) > div.panel-body > dl:nth-child(1) > dd > span"
).text();
novel.Status = $(
novel.status = $(
"main > div:nth-child(3) > div > div.col-lg-3.col-md-4 > div:nth-child(2) > div.panel-body > dl:nth-child(2) > dd"
)
.text()
.trim();
novel["Genre(s)"] = $(
novel.genre = $(
"main > div.container > div > div.col-lg-3.col-md-4 > div:nth-child(4) > div.panel-body > ul"
)
.text()
@@ -112,17 +114,13 @@ const novelScraper = async (req, res) => {
}
}
novel.novelChapters = chapters;
novel.chapters = chapters;
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}chapter/${chapterUrl}`;
console.log(url);
const result = await fetch(url);
const body = await result.text();
@@ -134,27 +132,28 @@ const chapterScraper = async (req, res) => {
$(".original").remove();
let chapterText = $(".chapter-body").html();
chapterText = chapterName + "\n\n" + parseHtml(chapterText);
let nextChapter = null;
let prevChapter = null;
if (!chapterText) {
chapterText = $(".alert.alert-warning").text();
}
chapterText =
chapterName +
"\n\n" +
htmlToText(chapterText, { removeLineBreaks: false });
const chapter = {
extensionId: 37,
sourceId: 37,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = "https://lnmtl.com/term";
const result = await fetch(url);
@@ -172,22 +171,24 @@ const searchScraper = async (req, res) => {
novels = JSON.parse(novels);
novels = novels.filter((novel) =>
novel.name.toLowerCase().includes(searchTerm)
novel.name.toLowerCase().includes(searchTerm.toLowerCase())
);
novels = novels.map((novel) => ({
extensionId: 37,
sourceId: 37,
novelName: novel.name,
novelUrl: novel.slug,
novelCover: novel.image,
}));
res.json(novels);
return novels;
};
module.exports = lnmtlScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const LNMTLScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default LNMTLScraper;
-11
View File
@@ -1,11 +0,0 @@
const express = require("express");
const lnmtlScraper = require("./LNMTLScraper");
const router = express.Router();
router.get("/novels/", lnmtlScraper.novelsScraper);
router.get("/novel/:novelUrl", lnmtlScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", lnmtlScraper.chapterScraper);
router.get("/search/", lnmtlScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

@@ -1,16 +1,24 @@
const cheerio = require("cheerio");
const FormData = require("form-data");
const fetch = require("node-fetch");
const UserAgent = require("user-agents");
const { scraper, parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://www.mtlnovel.com";
const novelsScraper = async (req, res) => {
const url = `${baseUrl}/alltime-rank/`;
const popularNovels = async (page) => {
let totalPages = 10;
const url = `${baseUrl}/alltime-rank/page/${page}`;
const body = await scraper(url);
console.log(url);
let headers = new Headers({
referer: "https://www.mtlnovel.com/",
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
});
const result = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
$ = cheerio.load(body);
@@ -24,7 +32,7 @@ const novelsScraper = async (req, res) => {
novelUrl = novelUrl.replace("https://www.mtlnovel.com/", "");
const novel = {
extensionId: 5,
sourceId: 5,
novelUrl,
novelName,
novelCover,
@@ -33,35 +41,43 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}/${novelUrl}`;
const body = await scraper(url);
let headers = new Headers({
referer: "https://www.mtlnovel.com/alltime-rank/",
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
});
const result = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
$ = cheerio.load(body);
let novel = {};
novel.extensionId = 5;
novel.sourceId = 5;
novel.sourceName = "MTLNovel";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = novelUrl + "/";
novel.novelUrl = novelUrl;
novel.novelName = $("h1.entry-title").text();
novel.novelCover = $(".nov-head > amp-img").attr("src");
novel.novelSummary = $("div.desc > h2").next().text();
novel.summary = $("div.desc > h2").next().text();
novel["Author(s)"] = $("tr > td")
novel.author = $("tr > td")
.filter(function () {
return $(this).prev().text().trim() === "Author";
})
@@ -69,7 +85,7 @@ const novelScraper = async (req, res) => {
.text()
.replace("Auhtor:", "");
novel.Status = $("tr > td")
novel.status = $("tr > td")
.filter(function () {
return $(this).prev().text().trim() === "Status";
})
@@ -77,7 +93,7 @@ const novelScraper = async (req, res) => {
.text()
.replace("Status:", "");
novel["Genre(s)"] = $("td")
novel.genre = $("td")
.filter(function () {
return $(this).prev().text().trim() === "Genre";
})
@@ -85,12 +101,13 @@ const novelScraper = async (req, res) => {
.text()
.replace("Genre:", "");
novel["Artist(s)"] = null;
novel.artist = null;
const chapterListUrl = url + "/chapter-list/";
const getChapters = async () => {
const body = await scraper(chapterListUrl);
const result = await fetch(chapterListUrl);
const body = await result.text();
$ = cheerio.load(body);
@@ -104,7 +121,7 @@ const novelScraper = async (req, res) => {
let chapterUrl = $(this).attr("href");
chapterUrl = chapterUrl.replace(
`https://www.mtlnovel.com/${novelUrl}/`,
`https://www.mtlnovel.com/${novelUrl}`,
""
);
@@ -114,60 +131,44 @@ const novelScraper = async (req, res) => {
releaseDate,
});
});
return novelChapters;
return novelChapters.reverse();
};
novel.novelChapters = await getChapters();
novel.chapters = await getChapters();
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}/${novelUrl}${chapterUrl}`;
console.log(url);
const url = `${baseUrl}/${novelUrl}/${chapterUrl}/`;
const body = await scraper(url);
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
const chapterName = $("h1.main-title").text();
let chapterText = $("div.par").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($("a.next").attr("href")) {
nextChapter = $("a.next").attr("href").replace(`/${novelUrl}/`, "");
}
let prevChapter = null;
if ($("a.prev").attr("href")) {
prevChapter = $("a.prev").attr("href").replace(`/${novelUrl}/`, "");
}
chapter = {
extensionId: 5,
const chapter = {
sourceId: 5,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const searchUrl =
"https://www.mtlnovel.com/wp-admin/admin-ajax.php?action=autosuggest&q=" +
searchTerm +
"&__amp_source_origin=https%3A%2F%2Fwww.mtlnovel.com";
const result = await scraper(searchUrl);
const res = await fetch(searchUrl);
const result = await res.text();
$ = cheerio.load(result);
@@ -183,17 +184,19 @@ const searchScraper = async (req, res) => {
""
);
const novel = { extensionId: 5, novelName, novelCover, novelUrl };
const novel = { sourceId: 5, novelName, novelCover, novelUrl };
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = mtlNovelScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const mtlNovelScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default mtlNovelScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const mtlNovelScraper = require("./MTLNovelScraper");
const router = express.Router();
router.get("/novels/", mtlNovelScraper.novelsScraper);
router.get("/novel/:novelUrl", mtlNovelScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", mtlNovelScraper.chapterScraper);
router.get("/search/", mtlNovelScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

@@ -1,11 +1,10 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://novelfull.com";
const novelsScraper = async (req, res) => {
const url = `${baseUrl}/most-popular`;
const popularNovels = async (page) => {
let totalPages = 42;
const url = `${baseUrl}/most-popular?page=${page}`;
const result = await fetch(url);
const body = await result.text();
@@ -28,7 +27,7 @@ const novelsScraper = async (req, res) => {
novelUrl = `${novelUrl}/`;
const novel = {
extensionId: 8,
sourceId: 8,
novelUrl,
novelName,
novelCover,
@@ -37,12 +36,11 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}/${novelUrl}.html`;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}/${novelUrl.slice(0, -1)}.html`;
const result = await fetch(url);
const body = await result.text();
@@ -51,37 +49,37 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 8;
novel.sourceId = 8;
novel.sourceName = "NovelFull";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $("div.book > img").attr("alt");
novel.novelCover = baseUrl + $("div.book > img").attr("src");
novel.novelSummary = $("div.desc-text").text();
novel.summary = $("div.desc-text").text().trim();
novel["Author(s)"] = $("div.info > div > h3")
novel.author = $("div.info > div > h3")
.filter(function () {
return $(this).text().trim() === "Author:";
})
.siblings()
.text();
novel["Genre(s)"] = $("div.info > div")
novel.genre = $("div.info > div")
.filter(function () {
return $(this).find("h3").text().trim() === "Genre:";
})
.text()
.replace("Genre:", "");
novel["Artist(s)"] = null;
novel.artist = null;
novel.Status = $("div.info > div > h3")
novel.status = $("div.info > div > h3")
.filter(function () {
return $(this).text().trim() === "Status:";
})
@@ -105,7 +103,7 @@ const novelScraper = async (req, res) => {
let chapterName = $(this).text();
let releaseDate = null;
let chapterUrl = $(this).attr("value");
chapterUrl = chapterUrl.replace(`/${novelUrl}/`, "");
chapterUrl = chapterUrl.replace(`/${novelUrl}`, "");
novelChapters.push({
chapterName,
@@ -116,16 +114,13 @@ const novelScraper = async (req, res) => {
return novelChapters;
};
novel.novelChapters = await getChapters(novelId);
novel.chapters = await getChapters(novelId);
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
const novelUrl = req.params.novelUrl.replace(".html/", "");
const chapterUrl = req.params.chapterUrl;
const url = `${baseUrl}/${novelUrl}/${chapterUrl}`;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}/${novelUrl}${chapterUrl}`;
const result = await fetch(url);
const body = await result.text();
@@ -134,37 +129,18 @@ const chapterScraper = async (req, res) => {
const chapterName = $(".chapter-title").attr("title");
let chapterText = $("#chapter-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($("a#next_chap").attr("href")) {
nextChapter = $("a#next_chap")
.attr("href")
.replace(`/${novelUrl}/`, "");
}
let prevChapter = null;
if ($("a#prev_chap").attr("href")) {
prevChapter = $("a#prev_chap")
.attr("href")
.replace(`/${novelUrl}/`, "");
}
const chapter = {
extensionId: 8,
sourceId: 8,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const searchUrl = `https://novelfull.com/search?keyword=`;
const url = `${searchUrl}${searchTerm}`;
@@ -188,7 +164,7 @@ const searchScraper = async (req, res) => {
const novelCover = baseUrl + $(this).find("img").attr("src");
const novel = {
extensionId: 8,
sourceId: 8,
novelUrl,
novelName,
novelCover,
@@ -197,12 +173,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = novelFullScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const novelFullScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default novelFullScraper;
-13
View File
@@ -1,13 +0,0 @@
const express = require("express");
const novelFullScraper = require("./NovelFullScraper");
const router = express.Router();
router.get("/novels/", novelFullScraper.novelsScraper);
router.get("/novel/:novelUrl", novelFullScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", novelFullScraper.chapterScraper);
router.get("/search/", novelFullScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

@@ -1,10 +1,9 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://www.novelhall.com/";
const novelsScraper = async (req, res) => {
const popularNovels = async (page) => {
let totalPages = 1;
const result = await fetch(baseUrl);
const body = await result.text();
@@ -20,7 +19,7 @@ const novelsScraper = async (req, res) => {
const novelUrl = $(this).find("a").attr("href").substring(1);
const novel = {
extensionId: 6,
sourceId: 6,
novelName,
novelCover,
novelUrl,
@@ -29,11 +28,10 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}${novelUrl}/`;
const result = await fetch(url);
@@ -43,29 +41,29 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 6;
novel.sourceId = 6;
novel.sourceName = "NovelHall";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $("h1").text();
novel.novelCover = $("div.book-img > img").attr("src");
novel.novelSummary = $("div.intro")
novel.summary = $("div.intro")
.text()
.replace(/[\t\n]/g, "");
novel["Author(s)"] = $("span.blue").first().text().replace("Author:", "");
novel.author = $("span.blue").first().text().replace("Author:", "");
novel["Genre(s)"] = $("a.red").text();
novel.genre = $("a.red").text();
novel["Artist(s)"] = null;
novel.artist = null;
novel.Status = $("span.blue").first().next().text().replace("Status:", "");
novel.status = $("span.blue").first().next().text().replace("Status:", "");
let novelChapters = [];
@@ -91,15 +89,12 @@ const novelScraper = async (req, res) => {
novelChapters.push(chapter);
});
novel.novelChapters = novelChapters;
novel.chapters = novelChapters;
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl.replace(".html/", "");
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}${novelUrl}/${chapterUrl}`;
const result = await fetch(url);
@@ -109,38 +104,18 @@ const chapterScraper = async (req, res) => {
const chapterName = $("h1").text();
let chapterText = $("div.entry-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
nextChapter = $('a[rel="next"]').attr("href");
if (nextChapter) {
nextChapter = nextChapter.replace(`/${req.params.novelUrl}/`, "");
}
let prevChapter = null;
prevChapter = $('a[rel="prev"]').attr("href");
if (prevChapter) {
prevChapter = prevChapter.replace(`/${req.params.novelUrl}/`, "");
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
chapter = {
extensionId: 6,
sourceId: 6,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const searchUrl = `${baseUrl}index.php?s=so&module=book&keyword=`;
const url = `${searchUrl}${searchTerm}`;
@@ -164,7 +139,7 @@ const searchScraper = async (req, res) => {
}
novel = {
extensionId: 6,
sourceId: 6,
novelName,
novelCover,
novelUrl,
@@ -173,12 +148,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = novelhallScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const novelhallScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default novelhallScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const novelhallScraper = require("./NovelhallScraper");
const router = express.Router();
router.get("/novels/", novelhallScraper.novelsScraper);
router.get("/novel/:novelUrl", novelhallScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", novelhallScraper.chapterScraper);
router.get("/search/", novelhallScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

+158
View File
@@ -0,0 +1,158 @@
import cheerio from "react-native-cheerio";
import { Status } from "../helpers/constants";
const sourceId = 71;
const sourceName = "NovelOnlineFull.com";
const baseUrl = "https://novelonlinefull.com/";
const popularNovels = async (page) => {
let url =
baseUrl + "novel_list?type=topview&category=all&state=all&page=" + page;
const totalPages = 2155;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".update_item.list_category").each(function () {
const novelName = $(this).find("h3").text().trim();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this).find("h3 > a").attr("href");
novelUrl = novelUrl.replace(baseUrl + "novel/", "");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { novels, totalPages };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = baseUrl + "novel/" + novelUrl;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = { sourceId, sourceName, url, novelUrl };
novel.novelName = $("h1").text().trim();
novel.novelCover = $(".info_image > img").attr("src");
novel.summary = $("#noidungm").text().trim();
novel.genre = $("div.truyen_if_wrap > ul > li:nth-child(3)")
.text()
.replace("GENRES: ", "")
.replace(/ - /g, ",")
.trim();
console.log(novel.genre);
novel.status =
$(" div.truyen_if_wrap > ul > li:nth-child(4) > a")
.text()
.replace("STATUS", "")
.trim() === "ONGOING"
? Status.ONGOING
: Status.COMPLETED;
novel.author = $("div.truyen_if_wrap > ul > li:nth-child(2)")
.text()
.replace("Author(s):", "")
.trim();
let novelChapters = [];
$(".chapter-list")
.find(".row")
.each(function () {
const releaseDate = $(this).find("span:nth-child(2)").text();
const chapterName = $(this).find("span:nth-child(1) > a").text();
const chapterUrl = $(this).find("a").attr("href");
novelChapters.push({
chapterName,
chapterUrl,
releaseDate,
});
});
novel.chapters = novelChapters.reverse();
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const url = chapterUrl;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let chapterName = $(".name_chapter").text();
let chapterText = $("#vung_doc").html();
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const url = baseUrl + "search_novels/" + searchTerm;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".update_item.list_category").each(function () {
const novelName = $(this).find("h3").text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this).find("h3 > a").attr("href");
novelUrl = novelUrl.replace(baseUrl + "novel/", "");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const NovelOnlineFullScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default NovelOnlineFullScraper;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

@@ -1,12 +1,12 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { htmlToText } = require("html-to-text");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
import moment from "moment";
const baseUrl = "https://www.novelpassion.com/";
const novelsScraper = async (req, res) => {
let url = baseUrl + "category/all?p=1&s=1&f=4";
const popularNovels = async (page) => {
const totalPages = 42;
let url = baseUrl + "category/all?p=" + page + "&s=1&f=4";
const result = await fetch(url);
const body = await result.text();
@@ -27,7 +27,7 @@ const novelsScraper = async (req, res) => {
novelUrl = novelUrl.replace("/novel/", "");
const novel = {
extensionId: 33,
sourceId: 33,
novelName,
novelCover,
novelUrl,
@@ -36,11 +36,10 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
const url = baseUrl + "novel/" + novelUrl;
const result = await fetch(url);
@@ -50,11 +49,11 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 33;
novel.sourceId = 33;
novel.sourceName = "NovelPassion";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = novelUrl;
@@ -63,8 +62,8 @@ const novelScraper = async (req, res) => {
novel.novelCover = baseUrl + $("i.g_thumb > img").attr("src");
let novelSummary = $("div.j_synopsis").html();
novel.novelSummary = htmlToText(novelSummary);
let novelSummary = $("div.j_synopsis").text().trim();
novel.summary = novelSummary;
$("address.lh20.m14.pr").each(function (result) {
detailName = $(this).find("p.ell.dib.vam").text().trim();
@@ -73,15 +72,15 @@ const novelScraper = async (req, res) => {
switch (detailName) {
case "Categories:":
novel["Genre(s)"] = detail.trim().replace(/ - /g, ",");
novel.genre = detail.trim().replace(/ - /g, ",");
break;
case "Author:":
novel["Author(s)"] = detail.trim().replace(/ - /g, ", ");
novel.author = detail.trim().replace(/ - /g, ", ");
break;
}
if (detailName.includes("Status:")) {
novel.Status = detailName.replace("Status:", "").trim();
novel.status = detailName.replace("Status:", "").trim();
}
});
@@ -92,7 +91,8 @@ const novelScraper = async (req, res) => {
.each(function (result) {
const chapterName = $(this).find("span.sp1").text();
const releaseDate = $(this).find("i.sp2").text();
let releaseDate = $(this).find("i.sp2").text();
releaseDate = moment(new Date(releaseDate)).format("MM/DD/YY");
const chapterUrl = $(this)
.find("a")
@@ -106,15 +106,12 @@ const novelScraper = async (req, res) => {
});
});
novel.novelChapters = novelChapters;
novel.chapters = novelChapters.reverse();
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}novel/${novelUrl}/${chapterUrl}`;
const result = await fetch(url);
@@ -125,27 +122,18 @@ const chapterScraper = async (req, res) => {
let chapterName = $("div.cha-content").find("strong").text();
let chapterText = $("div.cha-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
let prevChapter = null;
const chapter = {
extensionId: 33,
sourceId: 33,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = baseUrl + "search?keyword=" + searchTerm;
const result = await fetch(url);
@@ -167,7 +155,7 @@ const searchScraper = async (req, res) => {
novelUrl = novelUrl.replace("/novel/", "");
const novel = {
extensionId: 33,
sourceId: 33,
novelName,
novelCover,
novelUrl,
@@ -176,12 +164,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = vipNovelScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const NovelPassionScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default NovelPassionScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const NovelPassionScraper = require("./NovelPassionScraper");
const router = express.Router();
router.get("/novels/", NovelPassionScraper.novelsScraper);
router.get("/novel/:novelUrl", NovelPassionScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", NovelPassionScraper.chapterScraper);
router.get("/search/", NovelPassionScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

@@ -1,11 +1,10 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://noveltrench.com/";
const novelsScraper = async (req, res) => {
let url = baseUrl;
const popularNovels = async (page) => {
let totalPages = 270;
let url = baseUrl + "manga/page/" + page;
const result = await fetch(url);
const body = await result.text();
@@ -22,7 +21,7 @@ const novelsScraper = async (req, res) => {
novelUrl = novelUrl.replace(`${baseUrl}manga/`, "");
const novel = {
extensionId: 9,
sourceId: 9,
novelName,
novelCover,
novelUrl,
@@ -31,12 +30,11 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}manga/${novelUrl}/`;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}manga/${novelUrl}`;
const result = await fetch(url);
const body = await result.text();
@@ -45,13 +43,13 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 9;
novel.sourceId = 9;
novel.sourceName = "NovelTrench";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $(".post-title > h1")
.text()
@@ -72,12 +70,22 @@ const novelScraper = async (req, res) => {
.replace(/[\t\n]/g, "")
.trim();
novel[detailName] = detail;
switch (detailName) {
case "Genre(s)":
novel.genre = detail.trim().replace(/[\t\n]/g, ",");
break;
case "Author(s)":
novel.author = detail.trim();
break;
case "Artist(s)":
novel.status = detail.trim();
break;
}
});
$(".description-summary > div.summary__content").find("em").remove();
novel.novelSummary = $(".description-summary > div.summary__content")
novel.summary = $(".description-summary > div.summary__content")
.text()
.replace(/[\t\n]/g, "");
@@ -97,20 +105,16 @@ const novelScraper = async (req, res) => {
.trim();
chapterUrl = $(this).find("a").attr("href").replace(url, "");
novelChapters.push({ chapterName, releaseDate, chapterUrl });
});
novel.novelChapters = novelChapters.reverse();
novel.chapters = novelChapters.reverse();
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const url = `${baseUrl}manga/${novelUrl}/${chapterUrl}`;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}manga/${novelUrl}${chapterUrl}`;
const result = await fetch(url);
const body = await result.text();
@@ -119,45 +123,18 @@ const chapterScraper = async (req, res) => {
const chapterName = $("h1#chapter-heading").text();
let chapterText = $(".reading-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($(".nav-next").length) {
nextChapter = $(".nav-next")
.find("a")
.attr("href")
.replace(baseUrl + "manga/" + novelUrl + "/", "");
}
let prevChapter = null;
if ($(".nav-previous").length) {
prevChapter = $(".nav-previous")
.find("a")
.attr("href")
.replace(baseUrl + "manga/" + novelUrl + "/", "");
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
const chapter = {
extensionId: 9,
sourceId: 9,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`;
const result = await fetch(url);
@@ -175,7 +152,7 @@ const searchScraper = async (req, res) => {
novelUrl = novelUrl.replace(`${baseUrl}manga/`, "");
const novel = {
extensionId: 9,
sourceId: 9,
novelName,
novelCover,
novelUrl,
@@ -184,12 +161,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = novelTrenchScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const novelTrenchScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default novelTrenchScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const novelTrenchScraper = require("./NovelTrenchScraper");
const router = express.Router();
router.get("/novels/", novelTrenchScraper.novelsScraper);
router.get("/novel/:novelUrl", novelTrenchScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", novelTrenchScraper.chapterScraper);
router.get("/search/", novelTrenchScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

+310
View File
@@ -0,0 +1,310 @@
import cheerio from "react-native-cheerio";
const sourceId = 50;
const sourceName = "Novel Updates";
const baseUrl = "https://www.novelupdates.com/";
let headers = new Headers({
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
});
const popularNovels = async (page) => {
const totalPages = 100;
let url = `${baseUrl}series-ranking/?rank=week&pg=` + page;
const result = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
const $ = cheerio.load(body);
const novels = [];
$("div.search_main_box_nu").each(function (res) {
const novelCover = $(this).find("img").attr("src");
const novelName = $(this).find(".search_title > a").text();
const novelUrl = $(this)
.find(".search_title > a")
.attr("href")
.split("/")[4];
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}series/${novelUrl}`;
const result = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
$ = cheerio.load(body);
let novel = {
sourceId,
sourceName,
url,
novelUrl,
};
novel.novelName = $(".seriestitlenu").text();
novel.novelCover = $(".seriesimg > img").attr("src");
novel.author = $("#showauthors").text().trim();
novel.genre = $("#seriesgenre").text().trim().replace(/\s/g, ",");
novel.status = $("#editstatus").text().includes("Ongoing")
? "Ongoing"
: "Completed";
let type = $("#showtype").text().trim();
let summary = $("#editdescription").text().trim();
novel.summary = summary + `\n\nType: ${type}`;
let novelChapters = [];
const novelId = $("input#mypostid").attr("value");
let formData = new FormData();
formData.append("action", "nd_getchapters");
formData.append("mygrr", 0);
formData.append("mypostid", parseInt(novelId));
const data = await fetch(
"https://www.novelupdates.com/wp-admin/admin-ajax.php",
{
method: "POST",
headers,
body: formData,
}
);
const text = await data.text();
$ = cheerio.load(text);
$("li.sp_li_chp").each(function () {
const chapterName = $(this).text().trim();
const releaseDate = null;
const chapterUrl =
"https:" + $(this).find("a").first().next().attr("href");
novelChapters.push({ chapterName, releaseDate, chapterUrl });
});
novel.chapters = novelChapters.reverse();
return novel;
};
function getLocation(href) {
var match = href.match(
/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/
);
return match && `${match[1]}//${match[3]}`;
}
const parseChapter = async (novelUrl, chapterUrl) => {
const url = chapterUrl;
// console.log("Original URL: ", url);
let result, body;
let chapterName = "";
try {
result = await fetch(url, {
method: "GET",
headers: headers,
});
body = await result.text();
// console.log(result.url);
// console.log("Redirected URL: ", result.url);
$ = cheerio.load(body);
let isWuxiaWorld = result.url.toLowerCase().includes("wuxiaworld");
let isBlogspot = result.url.toLowerCase().includes("blogspot");
let isTumblr = result.url.toLowerCase().includes("tumblr");
/**
* Checks if its a wwordpress site
*/
let isWordPress =
$('meta[name="generator"]').attr("content") || $("footer").text();
if (isWordPress) {
isWordPress =
isWordPress.toLowerCase().includes("wordpress") ||
isWordPress.includes("Site Kit by Google") ||
$(".powered-by").text().toLowerCase().includes("wordpress");
}
let isRainOfSnow = result.url.toLowerCase().includes("rainofsnow");
let isWebNovel = result.url.toLowerCase().includes("webnovel");
let isHostedNovel = result.url.toLowerCase().includes("hostednovel");
let isScribbleHub = result.url.toLowerCase().includes("scribblehub");
if (isWuxiaWorld) {
chapterText = $("#chapter-content").html();
} else if (isRainOfSnow) {
chapterText = $("div.content").html();
} else if (isTumblr) {
chapterText = $(".post").html();
} else if (isBlogspot) {
$(".post-share-buttons").remove();
chapterText = $(".entry-content").html();
} else if (isHostedNovel) {
chapterText = $(".chapter").html();
} else if (isScribbleHub) {
chapterText = $("div.chp_raw").html();
} else if (isWordPress) {
/**
* Remove wordpress bloat tags
*/
const bloatClasses = [
".c-ads",
"#madara-comments",
"#comments",
".content-comments",
".sharedaddy",
".wp-dark-mode-switcher",
".wp-next-post-navi",
".wp-block-buttons",
".wp-block-columns",
".post-cats",
".sidebar",
".author-avatar",
".ezoic-ad",
];
bloatClasses.map((tag) => $(tag).remove());
chapterText =
$(".entry-content").html() ||
$(".single_post").html() ||
$(".post-entry").html() ||
$(".main-content").html() ||
$("article.post").html() ||
$(".content").html() ||
$("#content").html();
} else if (isWebNovel) {
chapterText = $(".cha-words").html();
if (!chapterText) {
chapterText = $("._content").html();
}
} else {
/**
* Remove unnecessary tags
*/
const tags = ["nav", "header", "footer", ".hidden"];
tags.map((tag) => $(tag).remove());
chapterText = $("body").html();
}
if (!chapterText) {
chapterText =
"Chapter not available.\n\nReport if it's available in webview.";
} else {
/**
* Convert relative urls to absolute
*/
chapterText = chapterText.replace(
/href="\//g,
`href="${getLocation(result.url)}/`
);
}
} catch (error) {
chapterText = `Chapter not available (Error: ${error.message}).\n\nReport if it's available in webview.`;
}
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const url =
"https://www.novelupdates.com/?s=" +
searchTerm +
"&post_type=seriesplans";
const res = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await res.text();
$ = cheerio.load(body);
let novels = [];
$("div.search_main_box_nu").each(function (res) {
const novelCover = $(this).find("img").attr("src");
const novelName = $(this).find(".search_title > a").text();
const novelUrl = $(this)
.find(".search_title > a")
.attr("href")
.split("/")[4];
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const NovelUpdatesScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default NovelUpdatesScraper;
-14
View File
@@ -1,14 +0,0 @@
// const express = require("express");
// const novelUpdatesScraper = require("./NovelUpdatesScraper");
// const router = express.Router();
// router.get("/novels/", novelUpdatesScraper.novelsScraper);
// router.get("/novel/:novelUrl", novelUpdatesScraper.novelScraper);
// router.get("/novel/:novelUrl/:chapterUrl", novelUpdatesScraper.chapterScraper);
// router.get("/search/", novelUpdatesScraper.searchScraper);
// module.exports = router;
-194
View File
@@ -1,194 +0,0 @@
// import cheerio from "react-native-cheerio";
// import { htmlToText } from "../helpers/htmlToText";
// import moment from "moment";
// const sourceId = 50;
// const sourceName = "Novel Updates";
// const baseUrl = "https://www.novelupdates.com/";
// let headers = new Headers({
// "User-Agent":
// "'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
// });
// const popularNovels = async (page) => {
// const totalPages = 100;
// let url = `${baseUrl}series-ranking/?rank=sixmonths&pg=` + page;
// const result = await fetch(url, {
// method: "GET",
// headers: headers,
// });
// const body = await result.text();
// const $ = cheerio.load(body);
// const novels = [];
// $("div.search_main_box_nu").each(function (res) {
// const novelCover = $(this).find("img").attr("src");
// const novelName = $(this).find(".search_title > a").text();
// const novelUrl = $(this)
// .find(".search_title > a")
// .attr("href")
// .split("/")[4];
// const novel = {
// sourceId,
// novelName,
// novelCover,
// novelUrl,
// };
// novels.push(novel);
// });
// return { totalPages, novels };
// };
// const parseNovelAndChapters = async (novelUrl) => {
// const url = `${baseUrl}series/${novelUrl}`;
// const result = await fetch(url, {
// method: "GET",
// headers: headers,
// });
// const body = await result.text();
// $ = cheerio.load(body);
// let novel = {
// sourceId,
// sourceName,
// url,
// novelUrl,
// };
// novel.novelName = $(".seriestitlenu").text();
// novel.novelCover = $(".seriesimg > img").attr("src");
// novel.author = $("#showauthors").text().trim();
// novel.genre = $(".book-generes").text().trim();
// novel.status = $("#editstatus").text().includes("Ongoing")
// ? "Ongoing"
// : "Completed";
// novel.summary = $("#editdescription").text().trim();
// let novelChapters = [];
// const novelId = $("input#mypostid").attr("value");
// let formData = new FormData();
// formData.append("action", "nd_getchapters");
// formData.append("mygrr", 0);
// formData.append("mypostid", parseInt(novelId));
// const data = await fetch(
// "https://www.novelupdates.com/wp-admin/admin-ajax.php",
// {
// method: "POST",
// headers,
// body: formData,
// }
// );
// const text = await data.text();
// $ = cheerio.load(text);
// $("li.sp_li_chp").each(function () {
// const chapterName = $(this).text().trim();
// const releaseDate = null;
// const chapterUrl =
// "https:" + $(this).find("a").first().next().attr("href");
// novelChapters.push({ chapterName, releaseDate, chapterUrl });
// });
// novel.chapters = novelChapters.reverse();
// return novel;
// };
// const parseChapter = async (novelUrl, chapterUrl) => {
// const url = chapterUrl;
// const result = await fetch(url, {
// method: "GET",
// headers: headers,
// });
// const body = await result.text();
// $ = cheerio.load(body);
// let chapterName = "";
// let chapterText = body;
// let nextChapter = null;
// let prevChapter = null;
// const chapter = {
// sourceId,
// novelUrl,
// chapterUrl,
// chapterName,
// chapterText,
// nextChapter,
// prevChapter,
// };
// return chapter;
// };
// const searchNovels = async (searchTerm) => {
// const url =
// "https://www.novelupdates.com/?s=" +
// searchTerm +
// "&post_type=seriesplans";
// const res = await fetch(url, {
// method: "GET",
// headers: headers,
// });
// const body = await res.text();
// $ = cheerio.load(body);
// let novels = [];
// $("div.search_main_box_nu").each(function (res) {
// const novelCover = $(this).find("img").attr("src");
// const novelName = $(this).find(".search_title > a").text();
// const novelUrl = $(this)
// .find(".search_title > a")
// .attr("href")
// .split("/")[4];
// const novel = {
// sourceId,
// novelName,
// novelCover,
// novelUrl,
// };
// novels.push(novel);
// });
// return novels;
// };
// const NovelUpdatesScraper = {
// popularNovels,
// parseNovelAndChapters,
// parseChapter,
// searchNovels,
// };
// export default NovelUpdatesScraper;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

@@ -1,11 +1,9 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { htmlToText } = require("html-to-text");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://www.novelupdates.cc/";
const novelsScraper = async (req, res) => {
const popularNovels = async (page) => {
let totalPages = 1;
const result = await fetch(baseUrl);
const body = await result.text();
@@ -20,7 +18,7 @@ const novelsScraper = async (req, res) => {
let novelUrl = $(this).find("a").attr("href").slice(1);
const novel = {
extensionId: 18,
sourceId: 18,
novelName,
novelCover,
novelUrl,
@@ -29,11 +27,10 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}${novelUrl}/`;
const result = await fetch(url);
@@ -43,26 +40,26 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 18;
novel.sourceId = 18;
novel.sourceName = "NovelUpdates.cc";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $(".book-name").text();
novel.novelCover = $("div.book-img > img").attr("src");
novel["Genre(s)"] = $("div.book-catalog > span.txt").text();
novel.genre = $("div.book-catalog > span.txt").text();
novel.Status = $("div.book-state > span.txt").text();
novel.status = $("div.book-state > span.txt").text();
novel["Author(s)"] = $("div.author > span.name").text();
novel.author = $("div.author > span.name").text();
novelSummary = $("div.content > p.desc").html();
novel.novelSummary = htmlToText(novelSummary);
novelSummary = $("div.content > p.desc").text();
novel.summary = novelSummary.trim();
let novelChapters = [];
@@ -78,15 +75,12 @@ const novelScraper = async (req, res) => {
});
});
novel.novelChapters = novelChapters;
novel.chapters = novelChapters;
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}${chapterUrl}`;
const result = await fetch(url);
@@ -96,39 +90,18 @@ const chapterScraper = async (req, res) => {
const chapterName = $("h1.chapter-title").text();
let chapterText = $("div.chapter-entity").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($("a.next").length) {
nextChapter = $("a.next").attr("href").slice(1);
}
let prevChapter = null;
if ($("a.prev").length) {
prevChapter = $("a.prev").attr("href").slice(1);
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
const chapter = {
extensionId: 18,
sourceId: 18,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = `${baseUrl}search/${searchTerm}/1`;
const result = await fetch(url);
@@ -147,7 +120,7 @@ const searchScraper = async (req, res) => {
let novelUrl = $(this).find("a").attr("href").slice(1);
const novel = {
extensionId: 18,
sourceId: 18,
novelName,
novelCover,
novelUrl,
@@ -156,12 +129,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = wuxiaWorldCoScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const novelUpdatesCcScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default novelUpdatesCcScraper;
-17
View File
@@ -1,17 +0,0 @@
const express = require("express");
const NovelUpdatesCcScraper = require("./NovelUpdatesCcScraper");
const router = express.Router();
router.get("/novels/", NovelUpdatesCcScraper.novelsScraper);
router.get("/novel/:novelUrl", NovelUpdatesCcScraper.novelScraper);
router.get(
"/novel/:novelUrl/:chapterUrl",
NovelUpdatesCcScraper.chapterScraper
);
router.get("/search/", NovelUpdatesCcScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

+140
View File
@@ -0,0 +1,140 @@
import cheerio from "react-native-cheerio";
import { Status } from "../helpers/constants";
const sourceId = 78;
const sourceName = "RainOfSnow";
const baseUrl = "https://rainofsnow.com/";
const popularNovels = async (page) => {
let url = baseUrl + "novels/page/" + page;
const totalPages = 5;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".minbox").each(function () {
const novelName = $(this).find("h3").text();
const novelCover = $(this).find("img").attr("data-src");
const novelUrl = $(this).find("h3 > a").attr("href");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { novels, totalPages };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = novelUrl;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = { sourceId, sourceName, url, novelUrl };
novel.novelName = $("h2").text().trim();
novel.novelCover = $(".imagboca1 > img").attr("data-src");
novel.summary = $("#synop").text().trim();
novel.genre = $(
"body > div.queen > div > div > div.row > div.col-md-12.col-lg-7 > div > div.backcolor1 > ul > li:nth-child(5) > small"
)
.text()
.trim();
novel.author = $(
"body > div.queen > div > div > div.row > div.col-md-12.col-lg-7 > div > div.backcolor1 > ul > li:nth-child(2) > small"
).text();
novel.status = Status.UNKNOWN;
let novelChapters = [];
$("#chapter")
.find("li")
.each(function () {
const chapterName = $(this).find(".chapter").first().text().trim();
const releaseDate = $(this).find("small").text();
const chapterUrl = $(this).find("a").attr("href");
novelChapters.push({ chapterName, releaseDate, chapterUrl });
});
novel.chapters = novelChapters;
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const result = await fetch(chapterUrl);
const body = await result.text();
$ = cheerio.load(body);
let chapterName = $(".content > h2").text();
let chapterText = $(".content").html();
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
let url = baseUrl + "?s=" + searchTerm;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".minbox").each(function () {
const novelName = $(this).find("h3").text();
const novelCover = $(this).find("img").attr("data-src");
const novelUrl = $(this).find("h3 > a").attr("href");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const RainOfSnowScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default RainOfSnowScraper;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

+228
View File
@@ -0,0 +1,228 @@
import cheerio from "react-native-cheerio";
import moment from "moment";
import { showToast } from "../../hooks/showToast";
const sourceId = 51;
const sourceName = "Ranobes";
const baseUrl = "https://ranobes.net/";
const popularNovels = async (page) => {
const totalPages = 152;
let url = `${baseUrl}novels/page/${page}`;
let headers = new Headers({
referer: "https://ranobes.net/",
"user-agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
});
const result = await fetch(url, { method: "GET", headers: headers });
const body = await result.text();
let $ = cheerio.load(body);
let novels = [];
$("article.block.story.shortstory.mod-poster").each(function () {
const novelName = $(this).find("h2.title").text();
let novelCover = $(this).find("figure").attr("style");
let novelUrl = $(this)
.find("a")
.attr("href")
.replace(baseUrl + "novels/", "");
novelCover = novelCover
.match(/background-image: url(.*);/)[1]
.slice(1, -1);
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl) => {
showToast("Ranobes: Only has latest 25 chapters.");
const url = `${baseUrl}novels/${novelUrl}`;
const result = await fetch(url);
const body = await result.text();
let $ = cheerio.load(body);
let novel = {
sourceId,
sourceName,
url,
novelUrl,
};
novel.novelName = $('meta[property="og:title"]').attr("content");
novel.novelCover = baseUrl + $(".poster > a > img").attr("src");
novel.author = $("dl.author > dd").text();
novel.genre = $(".book-generes").text().trim();
novel.summary = $('div[itemprop="description"]').text().trim();
novel.author = $('span[itemprop="author"]').text();
novel.genre = $('span[itemprop="genre"]').text().replace(", ", ",");
let tempNovelUrl = $(".r-fullstory-chapters-foot")
.find("a")
.next()
.next()
.attr("href")
.split("/")[2];
const chapterListUrl = `${baseUrl}up/${tempNovelUrl}/page/1`;
const chaptersHtml = await fetch(chapterListUrl);
const chapterHtmlToString = await chaptersHtml.text();
$ = cheerio.load(chapterHtmlToString);
// let lastPage = $("div.pages > a").last().text();
let novelChapters = [];
$("#dle-content > div.cat_block.cat_line").each(function () {
const chapterName = $(this).find(".title").text();
let releaseDate = new Date();
let timeAgo = $(this).find("small").text();
timeAgo = timeAgo.match(/\d+/)[0];
if (timeAgo.includes("hours ago")) {
releaseDate.setTime(releaseDate.getTime() - timeAgo);
}
if (timeAgo.includes("months ago")) {
releaseDate.setMonth(releaseDate.getMonth() - timeAgo);
}
if (timeAgo.includes("days ago")) {
releaseDate.setDate(releaseDate.getDate() - timeAgo);
}
releaseDate = moment(releaseDate).format("MM/DD/YY");
const chapterUrl = $(this)
.find("a")
.attr("href")
.replace(baseUrl + "up/", "");
const chapter = {
chapterName,
releaseDate,
chapterUrl,
};
novelChapters.push(chapter);
});
// for (i = 1; i <= lastPage; i++) {
// const chapterPageUrl = `${baseUrl}up/${tempNovelUrl}/page/${i}`;
// const chaptersHtml = await fetch(chapterPageUrl);
// const chapterHtmlToString = await chaptersHtml.text();
// $ = cheerio.load(chapterHtmlToString);
// $("#dle-content > div.cat_block.cat_line").each(function () {
// const chapterName = $(this).find(".title").text();
// let releaseDate = new Date();
// let timeAgo = $(this).find("small").text();
// timeAgo = timeAgo.match(/\d+/)[0];
// if (timeAgo.includes("hours ago")) {
// releaseDate.setTime(releaseDate.getTime() - timeAgo);
// }
// if (timeAgo.includes("months ago")) {
// releaseDate.setMonth(releaseDate.getMonth() - timeAgo);
// }
// if (timeAgo.includes("days ago")) {
// releaseDate.setDate(releaseDate.getDate() - timeAgo);
// }
// releaseDate = moment(releaseDate).format("MM/DD/YY");
// const chapterUrl = $(this)
// .find("a")
// .attr("href")
// .replace(baseUrl + "up/", "");
// const chapter = {
// chapterName,
// releaseDate,
// chapterUrl,
// };
// novelChapters.push(chapter);
// });
// }
novel.chapters = novelChapters.reverse();
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}up/${chapterUrl}`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let chapterName = $("h1.title").text();
let chapterText = $("#arrticle").html();
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
/**
* TODO
*/
showToast("Ranobes: Search does not work");
return [];
};
const RanobesScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default RanobesScraper;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

+214
View File
@@ -0,0 +1,214 @@
import cheerio from "react-native-cheerio";
const sourceId = 2;
const sourceName = "ReadLightNovel";
const lang = "en";
const baseUrl = "https://www.readlightnovel.me";
const searchUrl = "https://www.readlightnovel.me/detailed-search";
const popularNovels = async (page) => {
let totalPages = 1751;
const url = `${baseUrl}/top-novel/${page}`;
const result = await fetch(url);
const body = await result.text();
const $ = cheerio.load(body);
const novels = [];
$(".top-novel-block").each(function (result) {
const novelName = $(this).find("h2 > a").text();
const novelCover = $(this).find("img").attr("src");
const novelUrl = $(this)
.find("h2 > a")
.attr("href")
.replace(`${baseUrl}/`, "");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}/${novelUrl}`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel;
const novelName = $(".block-title > h1").text();
const novelCover = $(".novel-cover > a > img").attr("src");
let author, artist, genre, summary, status;
$(".novel-detail-item").each(function (result) {
const detailName = $(this).find(".novel-detail-header > h6").text();
const detail = $(this).find(".novel-detail-body").text().trim();
switch (detailName) {
case "Genre":
genre = detail.trim().replace(/\s{2,}/g, ",");
break;
case "Author(s)":
author = detail;
break;
case "Artist(s)":
artist = detail;
break;
case "Description":
summary = detail;
break;
case "Status":
status = detail;
break;
}
});
let chapters = [];
$(".panel").each(function () {
let volumeName = $(this).find("h4.panel-title").text();
$(this)
.find("ul.chapter-chs > li")
.each(function () {
let chapterName = $(this).find("a").text();
const releaseDate = null;
const chapterUrl = $(this)
.find("a")
.attr("href")
.replace(`${baseUrl}/${novelUrl}/`, "");
if (volumeName.includes("Volume")) {
chapterName = volumeName + " " + chapterName;
}
const chapter = {
chapterName,
releaseDate,
chapterUrl,
};
chapters.push(chapter);
});
});
novel = {
sourceId,
sourceName,
url,
novelUrl,
novelName,
novelCover,
genre,
author,
status,
artist,
summary,
chapters,
};
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}/${novelUrl}/${chapterUrl}/`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
$(".block-title > h1").find("a").remove();
const chapterName = $(".block-title > h1").text().replace(" - ", "");
$(".alert").remove();
$(".hidden").remove();
$("iframe").remove();
$("button").remove();
$(".hid").remove();
$("center").remove();
$(
'div[style="float: left; margin-top: 20px; font-style: italic;margin-left: 50px; font-size: 14px;"]'
).remove();
$('div[style="float:left;margin-top:15px;margin-bottom:15px;"]').remove();
let chapterText = $(".desc").html();
const chapter = {
sourceId: 2,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const formData = new FormData();
formData.append("keyword", searchTerm);
formData.append("search", 1);
const result = await fetch(searchUrl, {
method: "POST",
body: formData,
});
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".top-novel-block").each(function (result) {
const novelName = $(this).find(".top-novel-header > h2 > a").text();
const novelCover = $(this).find("img").attr("src");
const novelUrl = $(this)
.find(".top-novel-header > h2 > a")
.attr("href")
.replace(`${baseUrl}/`, "");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const ReadLightNovelScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default ReadLightNovelScraper;
-17
View File
@@ -1,17 +0,0 @@
const express = require("express");
const readLightNovelScraper = require("./ReadLightNovelScraper.js");
const router = express.Router();
router.get("/novels/", readLightNovelScraper.novelsScraper);
router.get("/novel/:novelUrl", readLightNovelScraper.novelScraper);
router.get(
"/novel/:novelUrl/:chapterUrl/:volumeUrl?",
readLightNovelScraper.chapterScraper
);
router.get("/search/", readLightNovelScraper.searchScraper);
module.exports = router;
@@ -1,238 +0,0 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const request = require("request");
const { parseHtml } = require("../../helper");
const baseUrl = "https://www.readlightnovel.org";
const searchUrl = "https://www.readlightnovel.org/detailed-search";
const novelsScraper = async (req, res) => {
const url = `${baseUrl}/top-novel?change_type=top_rated`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".top-novel-block").each(function (result) {
const novelName = $(this).find(".top-novel-header > h2 > a").text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this)
.find(".top-novel-header > h2 > a")
.attr("href")
.replace(`${baseUrl}/`, "");
novelUrl = novelUrl + "/";
const novel = {
extensionId: 2,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
res.json(novels);
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}/${novelUrl}`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = {};
novel.extensionId = 2;
novel.sourceName = "ReadLightNovel";
novel.sourceUrl = url;
novel.novelUrl = novelUrl + "/";
novel.novelName = $(".block-title > h1").text();
novel.novelCover = $(".novel-cover > a > img").attr("src");
$(".novel-detail-item").each(function (result) {
const detailName = $(this)
.find(".novel-detail-header > h6")
.text()
.replace(/[\t\n]/g, "")
.trim();
const detail = $(this).find(".novel-detail-body").text().trim();
novel[detailName] = detail;
});
novel.Alternative = novel["Alternative Names"];
novel.novelSummary = novel.Description;
novel["Genre(s)"] = novel.Genre.replace(/[\t\n]/g, ", ");
novel.Release = novel.Year;
delete novel["Alternative Names"];
delete novel.Description;
delete novel.Genre;
delete novel.Year;
let novelChapters = [];
$(".panel").each(function (res) {
let volumeName = $(this).find("h4.panel-title").text();
$(this)
.find("ul.chapter-chs > li")
.each(function (result) {
chapterName = $(this)
.find("a")
.text()
.replace(/[\t\n]/g, "")
.trim();
releaseDate = null;
chapterUrl = $(this).find("a").attr("href");
chapterUrl = chapterUrl.replace(`${baseUrl}/${novelUrl}/`, "");
if (volumeName.includes("Volume")) {
chapterName = volumeName + " " + chapterName;
}
const chapter = {
chapterName,
releaseDate,
chapterUrl,
};
novelChapters.push(chapter);
});
});
novel.novelChapters = novelChapters;
res.json(novel);
};
const chapterScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const volumeUrl = req.params.volumeUrl;
let optionalUrl;
if (volumeUrl) {
optionalUrl = volumeUrl;
} else {
optionalUrl = "";
}
const url = `${baseUrl}/${novelUrl}/${chapterUrl}/${optionalUrl}`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
$(".block-title > h1").find("a").remove();
const chapterName = $(".block-title > h1").text().replace(" - ", "");
$(".desc")
.find("hr")
.each(function (result) {
$(this).remove();
});
$(".alert").remove();
$(".hidden").remove();
let chapterText = $(".desc").html();
chapterText = parseHtml(chapterText).replace(
/\n\nSponsored Content\n\n|If audio player doesn't work, press Stop then Play button again/g,
""
);
let nextChapter = null;
if ($("a.next.next-link").length) {
nextChapter = $("a.next.next-link")
.attr("href")
.replace(`${baseUrl}/${novelUrl}/`, "");
}
let prevChapter = null;
if ($("a.prev.prev-link").length) {
prevChapter = $("a.prev.prev-link")
.attr("href")
.replace(`${baseUrl}/${novelUrl}/`, "");
}
chapterUrl = chapterUrl + "/" + optionalUrl;
const chapter = {
extensionId: 2,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
request.post(
{ url: searchUrl, form: { keyword: searchTerm, search: 1 } },
(err, response, body) => {
$ = cheerio.load(body);
let novels = [];
$(".top-novel-block").each(function (result) {
const novelName = $(this)
.find(".top-novel-header > h2 > a")
.text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this)
.find(".top-novel-header > h2 > a")
.attr("href")
.replace(`${baseUrl}/`, "");
novelUrl = novelUrl + "/";
const novel = {
extensionId: 2,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
res.json(novels);
}
);
};
module.exports = readLightNovelScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
};
Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

@@ -1,11 +1,9 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { htmlToText } = require("html-to-text");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://m.readlightnovel.cc/";
const novelsScraper = async (req, res) => {
const popularNovels = async (page) => {
let totalPages = 1;
const result = await fetch(baseUrl);
const body = await result.text();
@@ -20,7 +18,7 @@ const novelsScraper = async (req, res) => {
let novelUrl = $(this).find("a").attr("href").slice(1);
const novel = {
extensionId: 19,
sourceId: 19,
novelName,
novelCover,
novelUrl,
@@ -29,11 +27,10 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}${novelUrl}/`;
const result = await fetch(url);
@@ -43,26 +40,26 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 19;
novel.sourceId = 19;
novel.sourceName = "ReadLightNovel.cc";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $(".book-name").text();
novel.novelCover = $("div.book-img > img").attr("src");
novel["Genre(s)"] = $("div.book-catalog > span.txt").text();
novel.genre = $("div.book-catalog > span.txt").text();
novel.Status = $("div.book-state > span.txt").text();
novel.status = $("div.book-state > span.txt").text();
novel["Author(s)"] = $("div.author > span.name").text();
novel.author = $("div.author > span.name").text();
novelSummary = $("div.content > p.desc").html();
novel.novelSummary = htmlToText(novelSummary);
novelSummary = $("div.content > p.desc").text();
novel.summary = novelSummary.trim();
let novelChapters = [];
@@ -78,15 +75,12 @@ const novelScraper = async (req, res) => {
});
});
novel.novelChapters = novelChapters;
novel.chapters = novelChapters;
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}${chapterUrl}`;
const result = await fetch(url);
@@ -96,39 +90,18 @@ const chapterScraper = async (req, res) => {
const chapterName = $("h1.chapter-title").text();
let chapterText = $("div.chapter-entity").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($("a.next").length) {
nextChapter = $("a.next").attr("href").slice(1);
}
let prevChapter = null;
if ($("a.prev").length) {
prevChapter = $("a.prev").attr("href").slice(1);
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
const chapter = {
extensionId: 19,
sourceId: 19,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = `${baseUrl}search/${searchTerm}/1`;
const result = await fetch(url);
@@ -147,7 +120,7 @@ const searchScraper = async (req, res) => {
let novelUrl = $(this).find("a").attr("href").slice(1);
const novel = {
extensionId: 19,
sourceId: 19,
novelName,
novelCover,
novelUrl,
@@ -156,12 +129,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = wuxiaWorldCoScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const readLightNovelCcScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default readLightNovelCcScraper;
@@ -1,14 +0,0 @@
const express = require("express");
const ReadLightNovelCc = require("./ReadLightNovelCcScraper");
const router = express.Router();
router.get("/novels/", ReadLightNovelCc.novelsScraper);
router.get("/novel/:novelUrl", ReadLightNovelCc.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", ReadLightNovelCc.chapterScraper);
router.get("/search/", ReadLightNovelCc.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

@@ -1,11 +1,10 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://readnovelfull.com";
const novelsScraper = async (req, res) => {
const url = `${baseUrl}/most-popular-novel`;
const popularNovels = async (page) => {
let totalPages = 61;
const url = `${baseUrl}/most-popular-novel?page=${page}`;
const result = await fetch(url);
const body = await result.text();
@@ -26,7 +25,7 @@ const novelsScraper = async (req, res) => {
const novelCover = $(this).find("img").attr("src");
const novel = {
extensionId: 4,
sourceId: 4,
novelUrl,
novelName,
novelCover,
@@ -35,12 +34,11 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}/${novelUrl}.html`;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}/${novelUrl.slice(0, -1)}.html`;
const result = await fetch(url);
const body = await result.text();
@@ -49,37 +47,37 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 4;
novel.sourceId = 4;
novel.sourceName = "ReadNovelFull";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = novelUrl + "/";
novel.novelUrl = novelUrl;
novel.novelName = $("div.book > img").attr("alt");
novel.novelCover = $("div.book > img").attr("src");
novel.novelSummary = $("div.desc-text").text();
novel.summary = $("div.desc-text").text().trim();
novel["Author(s)"] = $("li > h3")
novel.author = $("li > h3")
.filter(function () {
return $(this).text().trim() === "Author:";
})
.siblings()
.text();
novel["Genre(s)"] = $("li")
novel.genre = $("li")
.filter(function () {
return $(this).find("h3").text().trim() === "Genre:";
})
.text()
.replace("Genre:", "");
novel["Artist(s)"] = null;
novel.artist = null;
novel.Status = $("li > h3")
novel.status = $("li > h3")
.filter(function () {
return $(this).text().trim() === "Status:";
})
@@ -105,7 +103,7 @@ const novelScraper = async (req, res) => {
let chapterName = $(this).find("a").attr("title");
let releaseDate = null;
let chapterUrl = $(this).find("a").attr("href");
chapterUrl = chapterUrl.replace(`/${novelUrl}/`, "");
chapterUrl = chapterUrl.replace(`/${novelUrl}`, "");
novelChapters.push({
chapterName,
@@ -116,16 +114,13 @@ const novelScraper = async (req, res) => {
return novelChapters;
};
novel.novelChapters = await getChapters(novelId);
novel.chapters = await getChapters(novelId);
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl.replace(".html/", "");
let chapterUrl = req.params.chapterUrl;
const url = `${baseUrl}/${novelUrl}/${chapterUrl}`;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}/${novelUrl}${chapterUrl}`;
const result = await fetch(url);
const body = await result.text();
@@ -134,37 +129,18 @@ const chapterScraper = async (req, res) => {
const chapterName = $(".chr-title").attr("title");
let chapterText = $("#chr-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($("a#next_chap").attr("href")) {
nextChapter = $("a#next_chap")
.attr("href")
.replace(`/${novelUrl}/`, "");
}
let prevChapter = null;
if ($("a#prev_chap").attr("href")) {
prevChapter = $("a#prev_chap")
.attr("href")
.replace(`/${novelUrl}/`, "");
}
const chapter = {
extensionId: 4,
sourceId: 4,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const searchUrl = `https://readnovelfull.com/search?keyword=`;
const url = `${searchUrl}${searchTerm}`;
@@ -188,7 +164,7 @@ const searchScraper = async (req, res) => {
const novelCover = $(this).find("img").attr("src");
const novel = {
extensionId: 4,
sourceId: 4,
novelUrl,
novelName,
novelCover,
@@ -197,12 +173,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = readNovelFullScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const readNovelFullScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default readNovelFullScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const readNovelFullScraper = require("./ReadNovelFullScraper");
const router = express.Router();
router.get("/novels/", readNovelFullScraper.novelsScraper);
router.get("/novel/:novelUrl", readNovelFullScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", readNovelFullScraper.chapterScraper);
router.get("/search/", readNovelFullScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

+193
View File
@@ -0,0 +1,193 @@
import QueryString from "qs";
import cheerio from "react-native-cheerio";
const sourceId = 68;
const sourceName = "Readwn.com";
const baseUrl = "https://www.readwn.com/";
const popularNovels = async (page) => {
let url = `${baseUrl}list/all/all-onclick-${page - 1}.html`;
const totalPages = 281;
const headers = new Headers({
"user-agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36",
});
const result = await fetch(url, { method: "GET", headers });
const body = await result.text();
console.log(body);
$ = cheerio.load(body);
let novels = [];
$("li.novel-item").each(function () {
const novelName = $(this).find("h4").text();
const novelUrl = $(this).find("a").attr("href").split("/").pop();
const novelCover =
baseUrl + $(this).find(".novel-cover > img").attr("data-src");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { novels, totalPages };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}novel/${novelUrl}`;
const headers = new Headers({
"user-agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36",
});
const result = await fetch(url, { method: "GET", headers });
const body = await result.text();
$ = cheerio.load(body);
let novel = {
sourceId,
sourceName,
url,
novelUrl,
};
novel.novelUrl = novelUrl;
novel.novelName = $("h1.novel-title").text();
novel.novelCover = baseUrl + $("figure.cover > img").attr("data-src");
novel.summary = $("p.description").text().trim();
novel.genre = "";
$("div.categories > ul > li").each(function () {
novel.genre += $(this).text().trim() + ",";
});
$("div.header-stats > span").each(function () {
if ($(this).find("small").text() === "Status") {
novel.status = $(this).find("strong").text();
}
});
novel.genre = novel.genre.slice(0, -1);
novel.author = $("span[itemprop=author]").text();
let novelChapters = [];
const novelId = novelUrl.split("/").pop().replace(".html", "");
const latestChapterNumber = $(".header-stats")
.find("span > strong")
.first()
.text()
.trim();
for (let i = 1; i <= latestChapterNumber; i++) {
const chapterName = `Chapter ${i}`;
const chapterUrl = `${novelId}_${i}`;
const releaseDate = null;
const chapter = { chapterName, releaseDate, chapterUrl };
novelChapters.push(chapter);
}
novel.chapters = novelChapters;
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}novel/${chapterUrl}.html`;
const headers = new Headers({
"user-agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36",
});
const result = await fetch(url, { method: "GET", headers });
const body = await result.text();
$ = cheerio.load(body);
const chapterName = $(".titles > h2").text();
let chapterText = $(".chapter-content").html();
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const searchUrl = "https://www.readwn.com/e/search/index.php";
const result = await fetch(searchUrl, {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Referer: "https://www.readwn.com/search.html",
Origin: "https://www.readwn.com",
"user-agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36",
},
method: "POST",
body: QueryString.stringify({
show: "title",
tempid: 1,
tbname: "news",
keyboard: searchTerm,
}),
});
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$("li.novel-item").each(function () {
const novelName = $(this).find("h4").text();
const novelCover = baseUrl + $(this).find("img").attr("src");
const novelUrl = $(this).find("a").attr("href").split("/").pop();
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const ReadwnScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default ReadwnScraper;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

+160
View File
@@ -0,0 +1,160 @@
import cheerio from "react-native-cheerio";
import { Status } from "../helpers/constants";
const baseUrl = "https://reaperscans.com";
const sourceId = 67;
const sourceName = "ReaperScans";
const popularNovels = async (page) => {
let url = `${baseUrl}/all-series/novels/`;
let totalPages = 1;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".page-item-detail").each(function (result) {
const novelName = $(this).find(".item-summary h3").text().trim();
const novelCover = $(this).find(".img-responsive").attr("data-src");
let novelUrl = $(this).find("div > a").attr("href");
novelUrl = novelUrl.replace(`${baseUrl}/`, "");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}/${novelUrl}`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = { sourceId, url, sourceName };
$(".post-title > h3 > span").remove();
novel.novelUrl = novelUrl;
novel.novelName = $(".post-title > h1").text().trim();
novel.novelCover = $(".summary_image > a > img").attr("data-src");
$(".post-content_item").each(function () {
const detailName = $(this).find(".summary-heading > h5").text().trim();
const detail = $(this).find(".summary-content").text().trim();
switch (detailName) {
case "Genre(s)":
novel.genre = detail.replace(/[\t\n]/g, ",");
break;
case "Author(s)":
novel.author = detail;
break;
case "Status":
novel.status = detail.includes("OnGoing")
? Status.ONGOING
: Status.COMPLETED;
break;
}
});
$(".description-summary > div.summary__content").find("em").remove();
$(".premium-block").remove();
novel.summary = $("div.summary__content").text().trim();
let novelChapters = [];
$(".wp-manga-chapter").each(function (result) {
$("i").remove();
const chapterName = $(this).find("a").text().trim();
const releaseDate = null;
const chapterUrl = $(this).find("a").attr("href").replace(url, "");
const chapter = { chapterName, releaseDate, chapterUrl };
novelChapters.push(chapter);
});
novel.chapters = novelChapters.reverse();
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}/${novelUrl}/${chapterUrl}`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
const chapterName = $("#chapter-heading").text();
let chapterText = $(".reading-content").html();
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".c-tabs-item__content").each(function (result) {
const novelName = $(this).find(".post-title > h3").text().trim();
const novelCover = $(this).find("div > div > a > img").attr("data-src");
let novelUrl = $(this).find("div > div > a").attr("href");
novelUrl = novelUrl.replace(`${baseUrl}/`, "");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const ReaperScansScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default ReaperScansScraper;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

@@ -1,12 +1,13 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { htmlToText } = require("html-to-text");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
import { parseMadaraDate } from "../helpers/parseDate";
import { Status } from "../helpers/constants";
const baseUrl = "https://www.royalroad.com/";
const novelsScraper = async (req, res) => {
let url = baseUrl + "fictions/best-rated?page=1";
const popularNovels = async (page) => {
const totalPages = 1846;
let url = baseUrl + "fictions/best-rated?page=" + page;
const result = await fetch(url);
const body = await result.text();
@@ -15,17 +16,21 @@ const novelsScraper = async (req, res) => {
let novels = [];
$("div.fiction-list-item.row").each(function (result) {
$("div.fiction-list-item.row").each(function () {
const novelName = $(this).find("h2.fiction-title").text().trim();
const novelCover = $(this).find("img").attr("src");
let novelCover = $(this).find("img").attr("src");
if (novelCover === "/Content/Images/nocover-new-min.png") {
novelCover =
"https://github.com/LNReader/lnreader-sources/blob/main/src/coverNotAvailable.jpg?raw=true";
}
let novelUrl = $(this)
.find("h2.fiction-title > a")
.attr("href")
.replace("/fiction/", "");
const novel = {
extensionId: 34,
sourceId: 34,
novelName,
novelCover,
novelUrl,
@@ -34,13 +39,11 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelId = req.params.novelId;
const novelUrl = req.params.novelUrl;
const url = baseUrl + "fiction/" + +novelId + "/" + novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
const url = baseUrl + "fiction/" + novelUrl;
const result = await fetch(url);
const body = await result.text();
@@ -49,48 +52,56 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 34;
novel.sourceId = 34;
novel.sourceName = "Royal Road";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = novelUrl;
novelName = $("h1").text();
novel.novelName = novelName;
novel["Author(s)"] = $("h1").next().text().replace("by ", "").trim();
novel.novelCover = $("img.thumbnail").attr("src");
let novelCover = $("img.thumbnail").attr("src");
novel.novelSummary = $("div.description").text().trim();
if (novelCover === "/Content/Images/nocover-new-min.png") {
novelCover =
"https://github.com/LNReader/lnreader-sources/blob/main/src/coverNotAvailable.jpg?raw=true";
}
novel["Genre(s)"] = $("span.tags").text().trim().replace(/\n\s+/g, ",");
novel.Status = $(
"div.fiction-info > div.portlet > .col-md-8 > .margin-bottom-10 > span"
)
.first()
.next()
.text()
.trim();
novel.novelCover = novelCover;
novel.summary = $("div.description").text().trim();
novel.author = $("h1").next().text().replace("by ", "").trim();
novel.genre = $("span.tags").text().trim().replace(/\n\s+/g, ",");
novel.status =
$(
"div.fiction-info > div.portlet > .col-md-8 > .margin-bottom-10 > span"
)
.first()
.next()
.text()
.trim() === "ONGOING"
? Status.ONGOING
: Status.COMPLETED;
let novelChapters = [];
$("table#chapters > tbody")
.find("tr")
.each(function (result) {
.each(function () {
const chapterName = $(this).find("td").first().text().trim();
const releaseDate = $(this).find("td").first().next().text().trim();
let releaseDate = $(this).find("td").first().next().text().trim();
releaseDate = releaseDate && parseMadaraDate(releaseDate);
const chapterUrl = $(this)
.find("td")
.first()
.find("a")
.attr("href")
.replace(
"/fiction/" + +novelId + "/" + novelUrl + "/chapter/",
""
);
.replace("/fiction/" + novelUrl + "/chapter/", "");
novelChapters.push({
chapterName,
@@ -99,18 +110,13 @@ const novelScraper = async (req, res) => {
});
});
novel.novelChapters = novelChapters;
novel.chapters = novelChapters;
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const url = `${baseUrl}fiction/${req.params.novelId}/${novelUrl}/chapter/${req.params.chapterId}/${req.params.chapterUrl}`;
console.log(url);
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}fiction/${novelUrl}/chapter/${chapterUrl}`;
const result = await fetch(url);
const body = await result.text();
@@ -120,31 +126,21 @@ const chapterScraper = async (req, res) => {
let chapterName = $("div.chapter-content").find("strong").text();
let chapterText = $("div.chapter-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
let prevChapter = null;
const chapter = {
extensionId: 34,
sourceId: 34,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = baseUrl + "fictions/search?title=" + searchTerm;
console.log(url);
const result = await fetch(url);
const body = await result.text();
@@ -152,7 +148,7 @@ const searchScraper = async (req, res) => {
let novels = [];
$("div.fiction-list-item.row").each(function (result) {
$("div.fiction-list-item.row").each(function () {
const novelName = $(this).find("h2.fiction-title").text().trim();
let novelCover = $(this).find("img").attr("src");
@@ -166,7 +162,7 @@ const searchScraper = async (req, res) => {
.replace("/fiction/", "");
const novel = {
extensionId: 34,
sourceId: 34,
novelName,
novelCover,
novelUrl,
@@ -175,12 +171,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = RoyalRoadScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const RoyalRoadScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default RoyalRoadScraper;
-17
View File
@@ -1,17 +0,0 @@
const express = require("express");
const RoyalRoadScraper = require("./RoyalRoadScraper");
const router = express.Router();
router.get("/novels/", RoyalRoadScraper.novelsScraper);
router.get("/novel/:novelId/:novelUrl", RoyalRoadScraper.novelScraper);
router.get(
"/novel/:novelId/:novelUrl/:chapterId/:chapterUrl",
RoyalRoadScraper.chapterScraper
);
router.get("/search/", RoyalRoadScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

@@ -1,13 +1,10 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { htmlToText } = require("html-to-text");
const { parseHtml } = require("../../helper");
const FormData = require("form-data");
import cheerio from "react-native-cheerio";
const baseUrl = "https://www.scribblehub.com/";
const novelsScraper = async (req, res) => {
let url = baseUrl + "series-ranking/?sort=1&order=4&pg=1";
const popularNovels = async (page) => {
const totalPages = 326;
let url = baseUrl + "series-ranking/?sort=1&order=4&pg=" + page;
const result = await fetch(url);
const body = await result.text();
@@ -25,7 +22,7 @@ const novelsScraper = async (req, res) => {
novelUrl = novelUrl[4] + "-" + novelUrl[5];
const novel = {
extensionId: 35,
sourceId: 35,
novelName,
novelCover,
novelUrl,
@@ -34,11 +31,10 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
const url = baseUrl + "read/" + novelUrl;
const result = await fetch(url);
@@ -48,11 +44,11 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 35;
novel.sourceId = 35;
novel.sourceName = "Scribble Hub";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = novelUrl;
@@ -60,19 +56,23 @@ const novelScraper = async (req, res) => {
novel.novelCover = $("div.fic_image > img").attr("src");
novel.novelSummary = $("div.wi_fic_desc").text();
novel.summary = $("div.wi_fic_desc").text();
novel["Genre(s)"] = "";
novel.genre = "";
$("span.wi_fic_genre")
.find("span")
.each(function (res) {
novel["Genre(s)"] += $(this).text() + ",";
novel.genre += $(this).text() + ",";
});
if (novel["Genre(s)"]) {
novel["Genre(s)"] = novel["Genre(s)"].slice(0, -1);
if (novel.genre) {
novel.genre = novel.genre.slice(0, -1);
}
novel["Author(s)"] = $("span.auth_name_fic").text();
novel.status = $("span.rnd_stats").next().text().includes("Ongoing")
? "Ongoing"
: "Completed";
novel.author = $("span.auth_name_fic").text();
let formData = new FormData();
formData.append("action", "wi_getreleases_pagination");
@@ -106,15 +106,12 @@ const novelScraper = async (req, res) => {
});
});
novel.novelChapters = novelChapters.reverse();
novel.chapters = novelChapters.reverse();
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = `${baseUrl}read/${novelUrl}/chapter/${chapterUrl}`;
const result = await fetch(url);
@@ -125,27 +122,18 @@ const chapterScraper = async (req, res) => {
let chapterName = $("div.chapter-title").text();
let chapterText = $("div.chp_raw").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
let prevChapter = null;
const chapter = {
extensionId: 35,
sourceId: 35,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url =
"https://www.scribblehub.com/?s=" +
searchTerm +
@@ -167,7 +155,7 @@ const searchScraper = async (req, res) => {
novelUrl = novelUrl[4] + "-" + novelUrl[5];
const novel = {
extensionId: 35,
sourceId: 35,
novelName,
novelCover,
novelUrl,
@@ -175,12 +163,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = vipNovelScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const ScribbleHubScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default ScribbleHubScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const ScribbleHubScraper = require("./ScribbleHubScraper");
const router = express.Router();
router.get("/novels/", ScribbleHubScraper.novelsScraper);
router.get("/novel/:novelUrl", ScribbleHubScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", ScribbleHubScraper.chapterScraper);
router.get("/search/", ScribbleHubScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

@@ -1,11 +1,15 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
var FormData = require("form-data");
const { htmlToText } = require("html-to-text");
import cheerio from "react-native-cheerio";
const baseUrl = "http://www.tapread.com";
const novelsScraper = async (req, res) => {
let headers = new Headers({
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
});
const popularNovels = async (page) => {
let totalPages = 0;
const result = await fetch(baseUrl);
const body = await result.text();
@@ -17,10 +21,9 @@ const novelsScraper = async (req, res) => {
const novelName = $(this).find(".book-name").text();
const novelCover = "http:" + $(this).find("img").attr("src");
let novelUrl = $(this).attr("data-id");
novelUrl += "/";
const novel = {
extensionId: 17,
sourceId: 17,
novelName,
novelCover,
novelUrl,
@@ -29,13 +32,14 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}/book/detail/${novelUrl}`;
console.log(url);
const result = await fetch(url);
const body = await result.text();
@@ -43,26 +47,25 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 17;
novel.sourceId = 17;
novel.sourceName = "TapRead";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $(".book-name").text();
novel.novelCover = "http:" + $("div.book-img > img").attr("src");
novel["Genre(s)"] = $("div.book-catalog > span.txt").text();
novel.genre = $("div.book-catalog > span.txt").text();
novel.Status = $("div.book-state > span.txt").text();
novel.status = $("div.book-state > span.txt").text();
novel["Author(s)"] = $("div.author > span.name").text();
novel.author = $("div.author > span.name").text();
novelSummary = $("div.content > p.desc").html();
novel.novelSummary = htmlToText(novelSummary);
novel.summary = $("div.content > p.desc").text();
const getChapters = async (novelId) => {
const chapterListUrl = "http://www.tapread.com/ajax/book/contents";
@@ -98,15 +101,12 @@ const novelScraper = async (req, res) => {
return novelChapters;
};
novel.novelChapters = await getChapters(novelUrl);
novel.chapters = await getChapters(novelUrl);
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
let formData = new FormData();
formData.append("bookId", novelUrl);
formData.append("chapterId", chapterUrl);
@@ -120,30 +120,20 @@ const chapterScraper = async (req, res) => {
const body = await result.json();
const chapterName = body.result.chapterName;
const chapterText = htmlToText(body.result.content);
const nextChapter =
body.result.nextChapterId === 0
? null
: body.result.nextChapterId.toString();
const prevChapter = body.result.preChapterId.toString();
novelUrl += "/";
const chapterText = body.result.content;
const chapter = {
extensionId: 17,
sourceId: 17,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
let formData = new FormData();
formData.append("storyType", 1);
formData.append("pageNo", 1);
@@ -162,21 +152,23 @@ const searchScraper = async (req, res) => {
body.result.storyList.map((novel) => {
const novelName = novel.storyName.replace(
'<font color="#FFCE2E">Demon</font>',
/<font color="#FFCE2E">|<\/font>/g,
""
);
const novelUrl = novel.storyId + "/";
const novelUrl = novel.storyId;
const novelCover = "http://static.tapread.com" + novel.coverUrl;
novels.push({ extensionId: 17, novelName, novelCover, novelUrl });
novels.push({ sourceId: 17, novelName, novelCover, novelUrl });
});
res.json(novels);
return novels;
};
module.exports = tapReadScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const tapReadScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default tapReadScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const tapReadScraper = require("./TapReadScraper");
const router = express.Router();
router.get("/novels/", tapReadScraper.novelsScraper);
router.get("/novel/:novelUrl", tapReadScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", tapReadScraper.chapterScraper);
router.get("/search/", tapReadScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

+156
View File
@@ -0,0 +1,156 @@
import cheerio from "react-native-cheerio";
const sourceId = 76;
const sourceName = "TravisTranslations";
const baseUrl = "https://travistranslations.com/";
const popularNovels = async (page) => {
let url = baseUrl + "all-series/";
if (page > 1) {
url += `page/${page}/`;
}
const totalPages = 19;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".group").each(function () {
const novelName = $(this).find("h3").text();
const novelCover = "https://" + $(this).find("img").attr("data-src");
const novelUrl = $(this).find(" a").attr("href");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { novels, totalPages };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = novelUrl;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = { sourceId, sourceName, url, novelUrl };
novel.novelName = $("h1").text().trim();
novel.novelCover = "https://" + $("img.object-cover").attr("data-src");
novel.summary = $("div[property=description]").text().trim();
novel.genre = "";
$("div.flex.flex-col.mt-3.text-center > ul > li").each(function () {
novel.genre +=
$(this)
.text()
.replace(/[\t\n]/g, "") + ",";
});
$("div.header-stats > span").each(function () {
if ($(this).find("small").text() === "Status") {
novel.status = $(this).find("strong").text();
}
});
novel.genre = novel.genre.slice(0, -1);
novel.author = $(".author > a > span").text();
let novelChapters = [];
$(".tab_content > ul.grid")
.find("li")
.each(function () {
const chapterName = $(this).find("span").first().text().trim();
const releaseDate = null;
const chapterUrl = $(this).find("a").attr("href");
novelChapters.push({ chapterName, releaseDate, chapterUrl });
});
novel.chapters = novelChapters;
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const result = await fetch(chapterUrl);
let body = await result.text();
$ = cheerio.load(body);
const chapterId = $("input[name=id]").attr("value");
const url =
"https://travistranslations.com/wp-json/wp/v2/posts/" + chapterId;
const data = await fetch(url);
body = await data.json();
let chapterName = body.title.rendered;
let chapterText = body.content.rendered;
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
let url = baseUrl + "all-series/?search=" + searchTerm;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$(".group").each(function () {
const novelName = $(this).find("h3").text();
const novelCover = "https://" + $(this).find("img").attr("data-src");
const novelUrl = $(this).find(" a").attr("href");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const TravisTranslationsScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default TravisTranslationsScraper;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

@@ -1,12 +1,10 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { htmlToText } = require("html-to-text");
const { parseHtml } = require("../../helper");
import cheerio from "react-native-cheerio";
const baseUrl = "https://vipnovel.com/";
const novelsScraper = async (req, res) => {
let url = baseUrl;
const popularNovels = async (page) => {
let totalPages = 89;
let url = `${baseUrl}vipnovel/page/${page}/?m_orderby=rating`;
const result = await fetch(url);
const body = await result.text();
@@ -23,7 +21,7 @@ const novelsScraper = async (req, res) => {
novelUrl = novelUrl.replace(`${baseUrl}vipnovel/`, "");
const novel = {
extensionId: 10,
sourceId: 10,
novelName,
novelCover,
novelUrl,
@@ -32,12 +30,13 @@ const novelsScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return { totalPages, novels };
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = `${baseUrl}vipnovel/${novelUrl}/`;
const parseNovelAndChapters = async (novelUrl) => {
const url = `${baseUrl}vipnovel/${novelUrl}`;
console.log(url);
const result = await fetch(url);
const body = await result.text();
@@ -46,13 +45,13 @@ const novelScraper = async (req, res) => {
let novel = {};
novel.extensionId = 10;
novel.sourceId = 10;
novel.sourceName = "VipNovel";
novel.sourceUrl = url;
novel.url = url;
novel.novelUrl = `${novelUrl}/`;
novel.novelUrl = novelUrl;
novel.novelName = $(".post-title > h3")
.text()
@@ -60,7 +59,6 @@ const novelScraper = async (req, res) => {
.trim();
novel.novelCover = $(".summary_image > a > img").attr("src");
$(".post-content_item").each(function (result) {
detailName = $(this)
.find(".summary-heading > h5")
@@ -73,12 +71,26 @@ const novelScraper = async (req, res) => {
.replace(/[\t\n]/g, "")
.trim();
novel[detailName] = detail;
switch (detailName) {
case "Genre(s)":
novel.genre = detail.trim().replace(/[\t\n]/g, ",");
break;
case "Author(s)":
novel.author = detail.trim();
break;
case "Artist(s)":
novel.status = detail.trim();
break;
}
});
let novelSummary = $(".description-summary > div.summary__content").html();
$(".summary__content > p").first().remove();
novel.novelSummary = htmlToText(novelSummary);
let novelSummary = $(".description-summary > div.summary__content")
.text()
.replace("Synopsis", "");
novel.summary = novelSummary.replace(/[\t\n]/g, "");
let novelChapters = [];
@@ -99,19 +111,20 @@ const novelScraper = async (req, res) => {
const chapter = { chapterName, releaseDate, chapterUrl };
console.log(chapterUrl);
novelChapters.push(chapter);
});
novel.novelChapters = novelChapters.reverse();
novel.chapters = novelChapters.reverse();
res.json(novel);
return novel;
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const parseChapter = async (novelUrl, chapterUrl) => {
const url = baseUrl + "vipnovel/" + novelUrl + chapterUrl;
const url = `${baseUrl}vipnovel/${novelUrl}/${chapterUrl}`;
console.log(url);
const result = await fetch(url);
const body = await result.text();
@@ -125,45 +138,18 @@ const chapterScraper = async (req, res) => {
}
let chapterText = $(".text-left").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($(".nav-next").length) {
nextChapter = $(".nav-next")
.find("a")
.attr("href")
.replace(baseUrl + "vipnovel/" + novelUrl + "/", "");
}
let prevChapter = null;
if ($(".nav-previous").length) {
prevChapter = $(".nav-previous")
.find("a")
.attr("href")
.replace(baseUrl + "vipnovel/" + novelUrl + "/", "");
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
const chapter = {
extensionId: 10,
sourceId: 10,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
return chapter;
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const searchNovels = async (searchTerm) => {
const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`;
const result = await fetch(url);
@@ -181,7 +167,7 @@ const searchScraper = async (req, res) => {
novelUrl = novelUrl.replace(`${baseUrl}vipnovel/`, "");
const novel = {
extensionId: 10,
sourceId: 10,
novelName,
novelCover,
novelUrl,
@@ -190,12 +176,14 @@ const searchScraper = async (req, res) => {
novels.push(novel);
});
res.json(novels);
return novels;
};
module.exports = vipNovelScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
const vipNovelScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default vipNovelScraper;
-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const vipNovelScraper = require("./VipNovelScraper");
const router = express.Router();
router.get("/novels/", vipNovelScraper.novelsScraper);
router.get("/novel/:novelUrl", vipNovelScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", vipNovelScraper.chapterScraper);
router.get("/search/", vipNovelScraper.searchScraper);
module.exports = router;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

+177
View File
@@ -0,0 +1,177 @@
import cheerio from "react-native-cheerio";
import { Status } from "../helpers/constants";
import NovelUpdatesScraper from "./novelupdates";
const sourceId = 62;
const sourceName = "WLNUpdates";
const baseUrl = "https://www.wlnupdates.com/";
let headers = new Headers({
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
});
const popularNovels = async (page) => {
const totalPages = 100;
let url = `${baseUrl}highest-rated/` + page;
const result = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
const $ = cheerio.load(body);
const novels = [];
$("table").find("tr").first().remove();
$("tr").each(function (res) {
const novelCover =
"https://github.com/LNReader/lnreader-sources/blob/main/src/coverNotAvailable.jpg?raw=true";
const novelName = $(this).find("td > a").text();
const novelUrl =
"https://www.wlnupdates.com" + $(this).find("td > a").attr("href");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return { totalPages, novels };
};
const parseNovelAndChapters = async (novelUrl) => {
const url = novelUrl;
const result = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
$ = cheerio.load(body);
let novel = {
sourceId,
sourceName,
url,
novelUrl,
};
novel.novelName = $("h2").text();
novel.novelCover =
"https://github.com/LNReader/lnreader-sources/blob/main/src/coverNotAvailable.jpg?raw=true";
novel.author = $(".multiitem#author")
.text()
.trim()
.replace(/[\t\n]/g, "");
novel.genre = $(".multiitem#genre")
.text()
.trim()
.replace(/[\t\n]/g, "");
novel.status = Status.UNKNOWN;
let summary = $("#description").text().trim();
novel.summary = summary;
let novelChapters = [];
$("#release-entry").each(function () {
let chapterName;
if ($(this).find("td.numeric").length > 1) {
chapterName =
"Volume " +
$(this).find(" td:nth-child(3)").text().trim() +
" Chapter " +
$(this).find(" td:nth-child(4)").text().trim();
} else if ($(this).find("td.numeric").length > 0) {
chapterName = "Chapter " + $(this).find("td.numeric").text().trim();
} else {
chapterName = $(this).find("td.postfix").text().trim();
}
const releaseDate = $(this).find(".release-entry-cell").text().trim();
const chapterUrl = $(this).find("td:nth-child(1) > a").attr("href");
novelChapters.push({ chapterName, releaseDate, chapterUrl });
});
novel.chapters = novelChapters.reverse();
return novel;
};
const parseChapter = async (novelUrl, chapterUrl) => {
const chapterName = "";
const chapterText = (
await NovelUpdatesScraper.parseChapter(novelUrl, chapterUrl)
).chapterText;
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
};
return chapter;
};
const searchNovels = async (searchTerm) => {
const url = baseUrl + "search?title=" + searchTerm;
const res = await fetch(url, {
method: "GET",
headers: headers,
});
const body = await res.text();
$ = cheerio.load(body);
let novels = [];
$("tr").each(function (res) {
const novelCover =
"https://github.com/LNReader/lnreader-sources/blob/main/src/coverNotAvailable.jpg?raw=true";
const novelName = $(this).find("td > a").text();
const novelUrl =
"https://www.wlnupdates.com" + $(this).find("td > a").attr("href");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
return novels;
};
const WLNUpdatesScraper = {
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
};
export default WLNUpdatesScraper;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

-14
View File
@@ -1,14 +0,0 @@
const express = require("express");
const WNMTLScraper = require("./WNMTLScraper");
const router = express.Router();
router.get("/novels/", WNMTLScraper.novelsScraper);
router.get("/novel/:novelUrl", WNMTLScraper.novelScraper);
router.get("/novel/:novelUrl/:chapterUrl", WNMTLScraper.chapterScraper);
router.get("/search/", WNMTLScraper.searchScraper);
module.exports = router;
-201
View File
@@ -1,201 +0,0 @@
const cheerio = require("cheerio");
const fetch = require("node-fetch");
const { htmlToText } = require("html-to-text");
const { parseHtml } = require("../../helper");
const baseUrl = "https://www.wnmtl.org/";
const sourceName = "WNMTL";
const sourceId = 77;
const novelsScraper = async (req, res) => {
let url = baseUrl + "explore";
console.log(url);
const result = await fetch(
"https://www.wnmtl.org/book/2308-warlock-apprentice"
);
const body = await result.text();
// $ = cheerio.load(body);
// let novels = [];
// $(".card").each(function () {
// const novelName = $(this).find(".book-name").text();
// const novelCover = $(this).find("img").attr("src");
// const novelUrl = $(this).find("a").attr("href");
// const novel = {
// sourceId,
// novelName,
// novelCover,
// novelUrl,
// };
// novels.push(novel);
// });
res.json({ novels: body });
};
const novelScraper = async (req, res) => {
const novelUrl = req.params.novelUrl;
const url = novelUrl;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novel = { sourceId, sourceName, url, novelUrl };
novel.novelName = $("#thumbnail > img").text();
novel.novelCover = $("#thumbnail > img").attr("src");
let novelSummary = $("div#Description").html();
novel.novelSummary = htmlToText(novelSummary);
novel["Genre(s)"] = $("div#Genre")
.text()
.replace(/Genre:|\s/g, "");
novel.Status = $("div#Status")
.text()
.replace(/Status:|\s/g, "");
novel["Author(s)"] = $("div#Publisher")
.text()
.replace(/Publisher:|\s/g, "");
// novel['Genre(s)'] = $("div#Genre").
let novelChapters = [];
let chapterUrlPrefix = $("tbody > tr")
.first()
.next()
.find("td > a")
.text()
.split(" ");
chapterUrlPrefix.pop();
chapterUrlPrefix = chapterUrlPrefix.join("-").toLowerCase();
const latestChapter = $("tbody > tr")
.first()
.next()
.find("td > a")
.text()
.replace(/^\D+/g, "");
for (let i = 1; i <= latestChapter; i++) {
const chapterName = "Chapter " + i;
const releaseDate = null;
const chapterUrl = chapterUrlPrefix + "-" + i + "/";
const chapter = {
chapterName,
releaseDate,
chapterUrl,
};
novelChapters.push(chapter);
}
novel.novelChapters = novelChapters;
res.json(novel);
};
const chapterScraper = async (req, res) => {
let novelUrl = req.params.novelUrl;
let chapterUrl = req.params.chapterUrl;
const url = `${baseUrl}mtl/${novelUrl}/${chapterUrl}`;
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let chapterName = $(".entry-title").text();
let chapterText = $(".entry-content").html();
chapterText = parseHtml(chapterText);
let nextChapter = null;
if ($(".nav-next").find("a").length) {
nextChapter = $(".nav-next")
.find("a")
.attr("href")
.replace(baseUrl + "mtl/" + novelUrl + "/", "");
}
let prevChapter = null;
if ($(".nav-previous").find("a").length) {
prevChapter = $(".nav-previous")
.find("a")
.attr("href")
.replace(baseUrl + "mtl/" + novelUrl + "/", "");
}
novelUrl = novelUrl + "/";
chapterUrl = chapterUrl + "/";
const chapter = {
sourceId,
novelUrl,
chapterUrl,
chapterName,
chapterText,
nextChapter,
prevChapter,
};
res.json(chapter);
};
const searchScraper = async (req, res) => {
const searchTerm = req.query.s;
const url = baseUrl + "?s=" + searchTerm + "&post_type=novel";
const result = await fetch(url);
const body = await result.text();
$ = cheerio.load(body);
let novels = [];
$("article.blog-article").each(function (result) {
const novelName = $(this).find("h5 > a").text();
const novelCover = $(this).find("img").attr("src");
let novelUrl = $(this).find("h5 > a").attr("href");
novelUrl = novelUrl.replace(baseUrl + "novel/", "");
const novel = {
sourceId,
novelName,
novelCover,
novelUrl,
};
novels.push(novel);
});
res.json(novels);
};
module.exports = WNMTLScraper = {
novelsScraper,
novelScraper,
chapterScraper,
searchScraper,
};

Some files were not shown because too many files have changed in this diff Show More