diff --git a/README.md b/README.md index a0c6bab..b676c51 100644 --- a/README.md +++ b/README.md @@ -40,8 +40,8 @@ Sources for [LNReader](https://github.com/rajarsheechatterjee/lnreader) | https://www.lunarletters.com/ | :heavy_check_mark: | | https://sleepytranslations.com/ | :heavy_check_mark: | | https://freenovel.me/ | :heavy_check_mark: | -| "https://1stkissnovel.love/" | :heavy_check_mark: | -| "https://daonovel.com/" | :heavy_check_mark: | +| https://1stkissnovel.love/ | :heavy_check_mark: | +| https://daonovel.com/ | :heavy_check_mark: | | https://syosetu.com | :heavy_check_mark: | | https://tunovelaligera.com/ | :heavy_check_mark: | | https://www.skynovels.net/ | :heavy_check_mark: | diff --git a/index.js b/index.js index 919df9d..1354fc2 100755 --- a/index.js +++ b/index.js @@ -46,6 +46,7 @@ app.use("/api/33/", require("./src/en/novelpassion/NovelPassion")); app.use("/api/34/", require("./src/en/royalroad/RoyalRoad")); app.use("/api/35/", require("./src/en/scribblehub/ScribbleHub")); app.use("/api/37/", require("./src/en/lnmtl/LNMTL")); +app.use("/api/48/", require("./src/en/wuxiablog/WuxiaBlog")); // Spanish app.use("/api/23/", require("./src/es/tunovelaligera/Tunovelaligera")); diff --git a/src/en/vipnovel/VipNovelScraper.js b/src/en/vipnovel/VipNovelScraper.js index 09511be..853a52b 100644 --- a/src/en/vipnovel/VipNovelScraper.js +++ b/src/en/vipnovel/VipNovelScraper.js @@ -76,8 +76,6 @@ const novelScraper = async (req, res) => { novel[detailName] = detail; }); - // $(".description-summary > div.summary__content").find("em").remove(); - let novelSummary = $(".description-summary > div.summary__content").html(); novel.novelSummary = htmlToText(novelSummary); diff --git a/src/en/wuxiablog/WuxiaBlog.js b/src/en/wuxiablog/WuxiaBlog.js new file mode 100644 index 0000000..b1fd895 --- /dev/null +++ b/src/en/wuxiablog/WuxiaBlog.js @@ -0,0 +1,17 @@ +const express = require("express"); +const wuxiaBlogScraper = require("./WuxiaBlogScraper"); + +const router = express.Router(); + +router.get("/novels/", wuxiaBlogScraper.novelsScraper); + +router.get("/novel/:novelUrl", wuxiaBlogScraper.novelScraper); + +router.get( + "/novel/:novelUrl/:chapterId/:chapterUrl", + wuxiaBlogScraper.chapterScraper +); + +router.get("/search/", wuxiaBlogScraper.searchScraper); + +module.exports = router; diff --git a/src/en/wuxiablog/WuxiaBlogScraper.js b/src/en/wuxiablog/WuxiaBlogScraper.js new file mode 100644 index 0000000..ef0248a --- /dev/null +++ b/src/en/wuxiablog/WuxiaBlogScraper.js @@ -0,0 +1,197 @@ +const cheerio = require("cheerio"); +const fetch = require("node-fetch"); +const { parseHtml } = require("../../helper"); + +const extensionId = 48; + +const sourceName = "Wuxia.Blog"; + +const baseUrl = "https://www.wuxia.blog/"; + +const novelsScraper = async (req, res) => { + let url = `${baseUrl}/listNovels`; + + const result = await fetch(url); + const body = await result.text(); + + $ = cheerio.load(body); + + let novels = []; + + $("div.panel-body > table") + .find("tr") + .each(function () { + const novelName = $(this).find("td.novel").text(); + + if (novelName) { + const novelId = $(this).find("td:nth-child(1)").text(); + + const novelCover = baseUrl + "/data/image/" + novelId + ".jpg"; + + let novelUrl = $(this) + .find("td.novel > a") + .attr("href") + .replace("/novel/", ""); + + const novel = { + extensionId, + 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 = { + extensionId, + sourceName, + sourceUrl: url, + novelUrl, + }; + + novel.novelName = $( + "body > div.container-fluid.text-center > div.row.content > div.col-sm-8.text-left > div:nth-child(6) > div.panel-heading.clearfix > h4" + ).text(); + + novel.novelCover = $('img[itemprop="image"]').attr("src"); + + novel["Author(s)"] = $( + "div.col-md-6 > div > div:nth-child(2) > div > div:nth-child(2) > a" + ).text(); + + novel["Genre(s)"] = $( + "div.row > div.col-md-6 > div > a:nth-child(4)" + ).text(); + + novel.novelSummary = $('div[itemprop="description"]') + .find("p") + .text() + .trim(); + + let novelChapters = []; + + $("table#chplist > #chapters > tr").each(function () { + const chapterName = $(this).find("a").text(); + + const releaseDate = $(this) + .find("td:nth-child(2)") + .text() + .replace(/-/g, "/"); + + const chapterUrl = $(this).find("a").attr("href").replace(url, ""); + + const chapter = { + chapterName, + releaseDate, + chapterUrl, + }; + + novelChapters.push(chapter); + }); + + novel.novelChapters = novelChapters.reverse(); + + res.json(novel); +}; + +const chapterScraper = async (req, res) => { + let novelUrl = req.params.novelUrl; + let chapterId = req.params.chapterId; + let chapterUrl = req.params.chapterUrl; + + const url = `${baseUrl}novel/${novelUrl}/${chapterId}/${chapterUrl}`; + console.log(url); + + const result = await fetch(url); + const body = await result.text(); + + $ = cheerio.load(body); + + let chapterName = $("div.panel-body.article").find("h4").text(); + + $("ul.pager").remove(); + + let chapterText = $("div.panel-body.article") + .html() + .replace(/(.*?)<\/span>/g, ""); + + chapterText = parseHtml(chapterText); + + let nextChapter = null; + let prevChapter = null; + + const chapter = { + extensionId, + novelUrl, + chapterUrl, + chapterName, + chapterText, + nextChapter, + prevChapter, + }; + + res.json(chapter); +}; + +const searchScraper = async (req, res) => { + const searchTerm = req.query.s; + + const url = `${baseUrl}?search=${searchTerm}`; + + console.log(url); + + const result = await fetch(url); + const body = await result.text(); + + $ = cheerio.load(body); + + let novels = []; + + $("#table") + .find("tr") + .each(function () { + const novelName = $(this).find("a").text().trim(); + + if (novelName) { + const novelCover = $(this).find("img").attr("src"); + + let novelUrl = $(this) + .find("a") + .attr("href") + .replace(baseUrl + "novel/", ""); + + const novel = { + extensionId, + novelName, + novelCover, + novelUrl, + }; + + novels.push(novel); + } + }); + + res.json(novels); +}; + +module.exports = vipNovelScraper = { + novelsScraper, + novelScraper, + chapterScraper, + searchScraper, +}; diff --git a/src/en/wuxiablog/icon.png b/src/en/wuxiablog/icon.png new file mode 100644 index 0000000..150cc43 Binary files /dev/null and b/src/en/wuxiablog/icon.png differ