aaaaaaaaa

This commit is contained in:
dengqn 2025-09-26 10:56:18 +08:00
parent b80852e7a0
commit f6cedc1a37
8 changed files with 137 additions and 17 deletions

View File

@ -1,6 +1,8 @@
package com.dengqn.app.lingyinapi.apis; package com.dengqn.app.lingyinapi.apis;
import com.dengqn.app.lingyinapi.beans.SeedListItem; import com.dengqn.app.lingyinapi.beans.SeedListItem;
import com.dengqn.app.lingyinapi.beans.api.Page;
import com.dengqn.app.lingyinapi.beans.api.Resp;
import com.dengqn.app.lingyinapi.config.CookieConfig; import com.dengqn.app.lingyinapi.config.CookieConfig;
import com.dengqn.app.lingyinapi.html.HtmlTool; import com.dengqn.app.lingyinapi.html.HtmlTool;
import com.dengqn.app.lingyinapi.http.HttpTool; import com.dengqn.app.lingyinapi.http.HttpTool;
@ -40,20 +42,27 @@ public class Seed {
} }
@GetMapping("/list") @GetMapping("/list")
public ResponseEntity<List<SeedListItem>> getSeedPage( public ResponseEntity<Resp<Page<SeedListItem>>> getSeedPage(
@RequestParam(required = false, defaultValue = "0", name = "inclbookmarked") String inclbookmarked, @RequestParam(required = false, defaultValue = "0", name = "inclbookmarked") String inclbookmarked,
@RequestParam(required = false, defaultValue = "1", name = "incldead") String incldead, @RequestParam(required = false, defaultValue = "1", name = "incldead") String incldead,
@RequestParam(required = false, defaultValue = "0", name = "spstate") String spstate, @RequestParam(required = false, defaultValue = "0", name = "spstate") String spstate,
@RequestParam(required = false, defaultValue = "1", name = "page") String page @RequestParam(required = false, defaultValue = "0", name = "page") String page,
@RequestParam(required = false, defaultValue = "50", name = "size") String size,
@RequestParam(required = false, defaultValue = "", name = "search") String search
) throws IOException { ) throws IOException {
String url = "https://pt.soulvoice.club/special.php?inclbookmarked=%s&incldead=%s&spstate=%s&page=%s&search=%s"
String url = "https://pt.soulvoice.club/special.php?inclbookmarked=%s&incldead=%s&spstate=%s&page=%s" .formatted(inclbookmarked, incldead, spstate, page, search);
.formatted(inclbookmarked, incldead, spstate, page);
String html = HttpTool.getHTML(url, okHttpClient); String html = HttpTool.getHTML(url, okHttpClient);
log.info("html:{}", html); log.info("html:{}", html);
Document doc = Jsoup.parse(html); Document doc = Jsoup.parse(html);
List<SeedListItem> listItem = HtmlTool.getSeedListItem(doc); List<SeedListItem> listItem = HtmlTool.getSeedListItem(doc);
return ResponseEntity.ok(listItem); return ResponseEntity.ok(
Resp.ok(Page.<SeedListItem>builder()
.page(Integer.valueOf(page))
.size(Integer.valueOf(size))
.total(HtmlTool.getPageTotal(doc))
.list(listItem)
.build()));
} }

View File

@ -5,7 +5,11 @@ package com.dengqn.app.lingyinapi.beans;
* @author dengqn * @author dengqn
* @since 2025/9/25 18:22 * @since 2025/9/25 18:22
*/ */
public record SeedListItem(String seedCover, String seedName, String seedUrl, boolean isFree, boolean isHitAndRun, public record SeedListItem(String seedCover,
String seedName,
String seedUrl,
String seedDesc,
boolean isFree, boolean isHitAndRun,
String downloadUrl, String time, String size, String seeders, String views, String downloadUrl, String time, String size, String seeders, String views,
boolean isAnonymous) { boolean isAnonymous) {
} }

View File

@ -0,0 +1,29 @@
package com.dengqn.app.lingyinapi.beans.api;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* 分页
*
* @author dengqn
* @since 2025/9/26 10:28
*/
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class Page<T> implements Serializable {
@Serial
private static final long serialVersionUID = 7287992347791111742L;
private Integer page;
private Integer size;
private Integer total;
private List<T> list;
}

View File

@ -0,0 +1,55 @@
package com.dengqn.app.lingyinapi.beans.api;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
*
* @author dengqn
* @since 2025/9/26 10:19
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Resp<T> implements Serializable {
@Serial
private static final long serialVersionUID = 3854320483518994111L;
private Integer code;
private String msg;
private T data;
public static <T> Resp<T> ok(T data) {
return ok("ok", data);
}
public static <T> Resp<T> ok(String msg, T data) {
return Resp.<T>builder()
.code(10000)
.msg(msg)
.data(data)
.build();
}
public static <T> Resp<T> error(String msg) {
return Resp.<T>builder()
.code(10001)
.msg(msg)
.build();
}
public static <T> Resp<T> error(Integer code, String msg) {
return Resp.<T>builder()
.code(code)
.msg(msg)
.build();
}
}

View File

@ -18,17 +18,15 @@ import java.util.Objects;
@Slf4j @Slf4j
public class HtmlTool { public class HtmlTool {
public static List<SeedListItem> getSeedListItem(Document doc) { public static List<SeedListItem> getSeedListItem(Document doc) {
List<SeedListItem> items = new ArrayList<>();
Element torrents; Element torrents;
try { try {
torrents = doc.getElementsByClass("torrents").getFirst(); torrents = doc.getElementsByClass("torrents").getFirst();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.info("搜不到东西:{}", e.getMessage());
return new ArrayList<>(); return new ArrayList<>();
} }
return torrents.select("tr").stream().skip(1) return torrents.select("tr").parallelStream().skip(1)
.map(tr -> { .map(tr -> {
try { try {
/** /**
@ -39,6 +37,7 @@ public class HtmlTool {
String seedCover = seedNames.get(0).getElementsByTag("img").first().attr("data-src"); String seedCover = seedNames.get(0).getElementsByTag("img").first().attr("data-src");
String seedName = seedNames.get(1).getElementsByTag("a").first().attr("title"); String seedName = seedNames.get(1).getElementsByTag("a").first().attr("title");
String seedUrl = seedNames.get(1).getElementsByTag("a").first().attr("href"); String seedUrl = seedNames.get(1).getElementsByTag("a").first().attr("href");
String seedDesc = seedNames.text().replaceFirst(seedName, "");
boolean isFree = seedNames.get(1).getElementsByClass("pro_free").size() > 0; boolean isFree = seedNames.get(1).getElementsByClass("pro_free").size() > 0;
boolean isHitAndRun = seedNames.get(1).getElementsByClass("hitandrun").size() > 0; boolean isHitAndRun = seedNames.get(1).getElementsByClass("hitandrun").size() > 0;
String downloadUrl = seedNames.get(3).getElementsByTag("a").first().attr("href"); String downloadUrl = seedNames.get(3).getElementsByTag("a").first().attr("href");
@ -54,12 +53,27 @@ public class HtmlTool {
String views = tds.get(7).getElementsByTag("b") == null || tds.get(7).getElementsByTag("b").size() == 0 ? "0" : tds.get(7).getElementsByTag("b").first().text().trim(); String views = tds.get(7).getElementsByTag("b") == null || tds.get(7).getElementsByTag("b").size() == 0 ? "0" : tds.get(7).getElementsByTag("b").first().text().trim();
boolean isAnonymous = tds.get(8).text().trim().contains("匿名"); boolean isAnonymous = tds.get(8).text().trim().contains("匿名");
return new SeedListItem(seedCover, seedName, seedUrl, seedDesc, isFree, isHitAndRun, downloadUrl, time, size, seeders, views, isAnonymous);
return new SeedListItem(seedCover, seedName, seedUrl, isFree, isHitAndRun, downloadUrl, time, size, seeders, views, isAnonymous);
} catch (Exception e) { } catch (Exception e) {
log.error("解析报错跳过:" + e.getMessage()); log.error("解析报错跳过:" + e.getMessage());
return null; return null;
} }
}).filter(Objects::nonNull).toList(); }).filter(Objects::nonNull).toList();
} }
public static Integer getPageTotal(Document document) {
Elements paginationEl = document.getElementsByClass("nexus-pagination");
if (paginationEl == null) return 0;
Elements pages = paginationEl.first().getElementsByTag("a");
if (pages == null || pages.size() == 0) return 0;
Element lastA = pages.last();
String text = lastA.text();
if ("".equalsIgnoreCase(text.trim())) return 0;
return Integer.valueOf(text.trim()
.replaceAll("\"", "")
.replaceAll(" ", "")
.split("-")[1]);
}
} }

View File

@ -20,6 +20,7 @@ public class HttpTool {
try { try {
Response response = okHttpClient.newCall(new Request.Builder() Response response = okHttpClient.newCall(new Request.Builder()
.url(url) .url(url)
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36")
.method("GET", null) .method("GET", null)
.build()) .build())
.execute(); .execute();

View File

@ -580,7 +580,8 @@
</tbody> </tbody>
</table> </table>
</form> </form>
<p align="center" class='nexus-pagination'><a href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=0"><b <p align="center" class='nexus-pagination'>
<a href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=0"><b
title="Alt+Pageup">&lt;&lt;&nbsp;上一页</b></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a title="Alt+Pageup">&lt;&lt;&nbsp;上一页</b></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a
href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=2"><b href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=2"><b
title="Alt+Pagedown">下一页&nbsp;&gt;&gt;</b></a><br/><a title="Alt+Pagedown">下一页&nbsp;&gt;&gt;</b></a><br/><a
@ -590,7 +591,8 @@
href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=3"><b>151&nbsp;-&nbsp;200</b></a> | ... | <a href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=3"><b>151&nbsp;-&nbsp;200</b></a> | ... | <a
href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=561"><b>28051&nbsp;-&nbsp;28100</b></a> | <a href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=561"><b>28051&nbsp;-&nbsp;28100</b></a> | <a
href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=562"><b>28101&nbsp;-&nbsp;28150</b></a> | <a href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=562"><b>28101&nbsp;-&nbsp;28150</b></a> | <a
href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=563"><b>28151&nbsp;-&nbsp;28164</b></a></p> href="?inclbookmarked=0&amp;incldead=1&amp;spstate=0&amp;page=563"><b>28151&nbsp;-&nbsp;28164</b></a>
</p>
<table class="torrents" cellspacing="0" cellpadding="5" width="100%"> <table class="torrents" cellspacing="0" cellpadding="5" width="100%">
<tr> <tr>
<td class="colhead" style="padding: 0px">类型</td> <td class="colhead" style="padding: 0px">类型</td>

View File

@ -17,13 +17,19 @@ import java.util.List;
public class HttpToolTest { public class HttpToolTest {
@Test @Test
public void testGetHtml() throws IOException { public void testGetSeedList() throws IOException {
String htmlData = new String(this.getClass().getResourceAsStream("/test-seed-list-page.html").readAllBytes()); String htmlData = new String(this.getClass().getResourceAsStream("/test-seed-list-page.html").readAllBytes());
// log.info("htmlData: {}", htmlData);
Document parse = Jsoup.parse(htmlData); Document parse = Jsoup.parse(htmlData);
List<SeedListItem> listItem = HtmlTool.getSeedListItem(parse); List<SeedListItem> listItem = HtmlTool.getSeedListItem(parse);
for (SeedListItem seedListItem : listItem) { for (SeedListItem seedListItem : listItem) {
log.info("item-->{}", seedListItem); log.info("item-->{}", seedListItem);
} }
} }
@Test
public void testGetSeedTotal() throws IOException {
String htmlData = new String(this.getClass().getResourceAsStream("/test-seed-list-page.html").readAllBytes());
Document parse = Jsoup.parse(htmlData);
Integer pageTotal = HtmlTool.getPageTotal(parse);
}
} }