1
0

feat: 增加爬虫案例

This commit is contained in:
2025-11-01 10:11:36 +08:00
parent ccd0767194
commit 77cbf36524
6 changed files with 291 additions and 2 deletions

20
pom.xml
View File

@@ -21,6 +21,7 @@
<hutool.version>5.8.39</hutool.version> <hutool.version>5.8.39</hutool.version>
<liteflow.version>2.15.0</liteflow.version> <liteflow.version>2.15.0</liteflow.version>
<selenium.version>4.38.1</selenium.version>
</properties> </properties>
<dependencies> <dependencies>
@@ -44,15 +45,26 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId> <artifactId>hutool-all</artifactId>
<version>${hutool.version}</version> <version>${hutool.version}</version>
</dependency> </dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-ai</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.yomahub</groupId> <groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId> <artifactId>liteflow-spring-boot-starter</artifactId>
<version>${liteflow.version}</version> <version>${liteflow.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
@@ -82,6 +94,12 @@
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-dependencies-bom</artifactId>
<version>${selenium.version}</version>
<type>pom</type>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@@ -41,6 +41,7 @@ public class Book extends SimpleEntity {
@Column(nullable = false) @Column(nullable = false)
private String name; private String name;
private String author; private String author;
@Column(columnDefinition = "text")
private String description; private String description;
private String source; private String source;
@ElementCollection(fetch = FetchType.EAGER) @ElementCollection(fetch = FetchType.EAGER)

View File

@@ -40,7 +40,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
public class Chapter extends SimpleEntity { public class Chapter extends SimpleEntity {
@Column(nullable = false) @Column(nullable = false)
private Double sequence; private Double sequence;
@Column(nullable = false)
private String name; private String name;
private String description; private String description;

View File

@@ -0,0 +1,13 @@
package com.lanyuanxiaoyao.bookstore.service;
import org.springframework.stereotype.Service;
/**
* 书籍下载
*
* @author lanyuanxiaoyao
* @version 20251031
*/
@Service
public class CrawlerService {
}

View File

@@ -0,0 +1,99 @@
package com.lanyuanxiaoyao.bookstore;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions;
/**
* @author lanyuanxiaoyao
* @version 20251031
*/
@Slf4j
public class BookCrawlerTest {
public static void main(String[] args) throws IOException {
ChromeDriver driver = null;
try {
driver = new ChromeDriver(
new ChromeDriverService.Builder()
.usingDriverExecutable(new File("/Users/lanyuanxiaoyao/Downloads/chromium/134/macOS-1345775/chromedriver"))
.build(),
new ChromeOptions()
.setBinary(new File("/Users/lanyuanxiaoyao/Downloads/chromium/134/macOS-1345775/Chromium.app/Contents/MacOS/Chromium"))
.addArguments(
// 允许不安全的域名
"--allow-insecure-localhost",
// 禁用GPU渲染headLess 模式用不上
"--disable-gpu",
// 禁用音频输出
"--disable-audio-output",
// 禁用错误页自动重新刷新
"--disable-auto-reload",
// 禁用默认应用加载
"--disable-default-apps",
// 禁用浏览器扩展
"--disable-extensions",
// 禁用日志
"--disable-logging",
// 禁用通知
"--disable-notifications",
// 禁用远程字体
"--disable-remote-fonts",
// 禁用弹出窗口
"--disable-popup-blocking",
// 禁用同步
"--disable-sync",
// 禁用沙盒
"--no-sandbox",
// 禁用声音
"--mute-audio",
// 禁止图片显示
"blink-settings=imagesEnabled=false"
)
);
var articleUrl = "https://www.alicesw.com/novel/33927.html";
driver.get(articleUrl);
var contextUrl = driver.findElement(By.xpath("//div[@class='book_newchap']//a[contains(text(),'查看所有章节')]")).getDomProperty("href");
if (StrUtil.isBlank(contextUrl)) {
throw new RuntimeException("获取目录页链接失败");
}
driver.get(contextUrl);
var chapterItems = driver.findElements(By.cssSelector("ul.mulu_list > li > a"))
.stream()
.map(element -> element.getDomProperty("href"))
.toList();
for (var index = 0; index < chapterItems.size(); index++) {
var chapterUrl = chapterItems.get(index);
if (StrUtil.isBlank(chapterUrl)) {
throw new RuntimeException("获取章节链接失败: " + chapterUrl);
}
driver.get(chapterUrl);
var text = driver.findElement(By.cssSelector(".read-content")).getText();
log.info(text);
var title = driver.getTitle();
if (StrUtil.isBlank(title)) {
title = String.valueOf(index);
}
var filename = StrUtil.format("{}.txt", title.replaceAll("\\s", "_"));
var targetFile = Path.of("out", filename);
Files.deleteIfExists(targetFile);
Files.createFile(targetFile);
Files.writeString(targetFile, text);
ThreadUtil.safeSleep(5000);
}
} finally {
if (driver != null) {
driver.close();
}
}
}
}

View File

@@ -0,0 +1,159 @@
package com.lanyuanxiaoyao.bookstore;
import cn.hutool.ai.AIUtil;
import cn.hutool.ai.ModelName;
import cn.hutool.ai.core.AIConfigBuilder;
import java.io.IOException;
import lombok.extern.slf4j.Slf4j;
/**
* 更新章节
*
* @author lanyuanxiaoyao
* @version 20251031
*/
@Slf4j
public class UpdateIntoDatabase {
public static void main(String[] args) throws IOException {
/*var chapters = new ArrayList<Chapter>();
Files.list(Path.of("out"))
.sorted(Comparator.comparing(path -> FileUtil.lastModifiedTime(path.toFile())))
.forEach(path -> {
try {
chapters.add(new Chapter(
path.getFileName().toString(),
Files.readString(path)
));
} catch (IOException e) {
throw new RuntimeException(e);
}
});
for (var chapter : chapters) {
log.info("name: {}", chapter.title());
}*/
var response = AIUtil.chat(
new AIConfigBuilder(ModelName.OPENAI.getValue())
.setApiUrl("http://127.0.0.1:30000")
.setApiKey("*XMySqV%>hR&v>>g*NwCs3tpQ5FVMFEF2VHVTj<MYQd$&@$sY7CgqNyea4giJi4")
.setModel("")
.setTimout(1000 * 60 * 5)
.build(),
"""
丹枫的视线垂下,脸颊渐红。
衣裳从微粉的肩上滑落,丰腴袅娜的娇躯顿时暴露在空气中。丰满圆润的乳峰顶上,两颗深粉色的乳尖渐渐勃起,凝脂般的肌肤在光线下泛起些许象牙般的光泽。
两条白臂时而遮住平坦的小腹,时而在胸前与腰侧间徘徊,一副局促模样。
与玉霜坦诚相见并不足以令她这般羞耻,只是一想到两人接下来要做的事情,本就被花雾影响的身躯更加火热,一道热血直冲脑门难以散去,为脖颈与耳朵也添了一抹赤色。
玉霜伸手拉开腰间的系带,褶衣与裳柔顺丝滑地与身躯分离,将光滑的美背与丰满的臀肉暴露在了身后丹枫的眼离。
她的身躯曲线格外柔美,是令丹枫为之羡慕的完美比例,饱满挺拔 的乳峰顶点缀着两朵粉红樱兔,紧致纤细的腰肢上隐约可见肌肉的线条,高高翘起的臀肉顶端泛着细腻的光泽,缝隙深处的馥郁之中正渗出些许体液。
面对飞星的身体,她的娇躯自然发情,在花雾的影响下,快速流动的血液令雪颊泛起一层淡淡的胭脂色,但她的神情仍然像往常一样清冷淡漠,只有眼里闪烁着柔软的担忧。
此次飞星对秋音君使用能力之后,在极其疲惫的状态下仍然强行将效果延长,此时受到的反噬也要比之前更为剧烈。
强烈的欲望使得飞星无法入眠,却也发不出声音,更没有动弹的力气。
他的眼睛微微睁着,脑海中一片混沌,但又保留了些许意识,令他能清醒地承受这份折磨。
她是第一次见到飞星这种状态,哪怕身体已经准备好了,内心也无法安心地享受鱼水之欢。
此刻他这般虚弱,又需要排解欲望,那便只能由她们来主动了。
丹枫走到床边,看着他这模样也自然心疼起来,俯下身子,取出块洁净的丝布擦了擦他脸上的汗水。
两人一起上了床。
丹枫侧身跪坐着,将双腿垫在飞星的头下,俯下身去轻吻他的嘴唇。
她伸出舌头,反复舔舐着他的嘴唇,而后轻柔地滑入他的口中,将嘴里含着的丹药与仙露缓缓渡给他。
仙露与丹药入喉,丹枫身上淡淡的香甜气息随之飘入飞星的鼻腔,飞星的眼珠微微颤动。
“很快就没事了~”
耳边响起她那慈爱而宠溺的传音。
“啵嗞~嗞~”
她用舌头包裹住他的舌尖,轻轻吮吸起来,与他对视着,桃眸泛着水光,荡漾着对他的怜爱。一只手捧着他的脸颊,一只手柔柔地抚摸他的脑袋,还从储物空间中取出一块南海冰霜,飘浮在床边为他降温。
玉霜将飞星的双腿分开,趴在他的双腿间,解开了他的衣裳,坚硬的龙身上青筋暴起,龙头昂首向上。
纤纤玉指将两鬓的发丝拂到耳后,她伸手握住一弹一弹颤动着的阳物,随后俯下头去——
飞星只感到下体进入了一个极为湿润且温暖的腔中,与阴穴不同,那腔中有一抹更为柔软且灵活的东西,从深处传来了一阵阵吸力,龙头顿时感到一抹酥爽的快感。
只见玉霜一手扶着飞星的大腿根部,一手握在龙根处,将飞星的阳物吞入口中。
为了容纳他的阳物,她那一张樱桃小嘴张得极大,双颊随之凹缩了一些,舌根咽喉处则因此鼓起。
身为修仙者,与她们一样,飞星的下身也没有异味。玉霜嗅着他的淡淡体味,双唇用力紧缩,避免牙齿碰到那敏感的龙头,将阳根连同唾液一同吞吐着,发出啧嗞啧嗞的水声。
虽然她的动作还不熟练,但是此刻被花雾所影响的飞星的身体极为敏感,阵阵快感从下身传来,只十几息后,他的身躯便紧绷起来。
玉霜见状,大幅度吞吐几下,而后猛地埋下头去,使阳根插至自己的喉咙深处。
只见飞星的腰臀不受控制地颤抖几下,一道道精液随之灌入玉霜的食道,径直落入她的腹中。
“嗯~”
她闷哼一声,呼吸受阻,眉头微微蹙起,感受着喉咙里的阳根不断抽动。
不知是不是丹药已经生效了,飞星的意识清晰了不少,努力将嘴角扬起,朝面前的丹枫微微一笑。
丹枫见状,脸上也随之泛起一抹笑容来,又在他额前一吻。
待飞星高潮完后,玉霜才将阳物吐出,把头靠在飞星的腿根,伸手扶着阳物贴在自己的脸颊上,看向飞星问道:
“好些了吗?”
“嗯……”飞星轻嗯一声,但似乎还是没有说话的力气,也无法有其他动作。
覆盖他全身肌肤的赤红并未褪去,阳物也依旧坚挺,看来只一次是完全不够的。
玉霜侧过去头去,朝龙身亲了一下。
“啵~”
她将人中贴在阳物下方,温热的鼻息打在龙头上,阳物轻轻一颤,从龙口淌出一些残余的元精。
她伸出舌头,舔过龙口,将残精卷入口中,而后樱唇一张,轻轻吮吸着龙头。
丹枫俯下身去,将头埋在他的胸口,伸出舌头舔弄起他的乳首,同时捧着自己的乳峰,将自己那颗勃起许久的乳尖递到了飞星的嘴边。
飞星自然张口将嫣红的樱桃含入口中,与丹枫一同舔舐着对方的乳头。
玉霜将舌尖抵在龙口处不停舔舐,亲吻几下后,又伸长舌头在龙根与春袋的交界处滑动着向上舔去,直至抵住龙口处的系带,而后再度将龙根吞入口中,伴随脑袋的前后摆动吞吐起来。
“咕嗞~卟嗞~”
阵阵快感再度袭来,飞星的呼吸很快又重了起来。
丹枫感受到他的头部正在迅速升温,坐起身来,将南海冰霜垫到了他的脑下,随后也来到了他的下身。
玉霜看了她一眼,将阳物吐出。
唾液从她的唇角落下,显得有些魅惑。
她来到飞星上身,将位置让给丹枫,而后从储物空间中取出些仙露滴在掌心上,伸手在飞星的胸口涂抹起来。
丹枫接替了玉霜的位置,俯下头去,将飞星的春袋含入口中,轻柔地吮吸几下后,再吐出,舌尖紧紧贴着龙身,在龙根与龙口间不停上下滑动。
而后,她伸出双手食指,落在龙口两旁,轻轻按下,向两边掰开,露出一点泛着光泽的嫩肉来,舌尖深入龙口内的敏感之中如细小的游鱼般抖动着舔舐起来。
“嗯……”飞星微微一颤。
丹枫见状用玉指箍住冠沟,在龙头处大幅度上下舔动起来。
玉霜俯下身来,将两团乳峰靠近飞星的脸部,用柔软的乳肉包裹着飞星的双颊。
阵阵快感令飞星低吟不断,他的身躯渐渐紧绷,丹枫抬眼看着飞星的神情,双手一同捏在阳物根部,将阳物没入口中吞吐起来,口中的香舌紧紧缠绕着龙头,与箍紧的嘴唇一同刺激着龙头。
强烈的快感下,飞星的精关失守,伴随下身的阵阵抽动,道道元精爆发在丹枫的口中。
“咕嘟~咕嘟~”
她不停将元精吞下,伴随缓慢的起身,阳根也从她口中缓缓退出。
她的红唇紧紧箍着阳根,脖颈后仰,龙头渐渐从她嘴中退出,而后在即将离开红唇的时候,她将舌尖抵到唇口的龙口上,紧紧吸住阳物的顶端,用力吮吸着,仿佛要将最后一点元精也榨出来。
“嗞嗞哫~嗞哫~啧嗞~~”
“嗯……!”
飞星闷哼一声,眉头皱起,下身刚刚才高潮过后下身本就敏感无比,此刻似乎又有什么东西正不受控制地要涌出来。
只见丹枫伸手握住他的阳根,一边撸动着,一边将龙头重新塞入口中,快速吮吸起来。
玉霜抱着他的脑袋,将乳尖塞入他的口中,轻声说道:“射出来吧~”
飞星一阵颤抖,只感到下身几乎要融化,而后又是一股元精涌出——
丹枫张大了檀口,伸着舌头接着,元精大多射入了她的口中,一部分打在她的脸上,还有一部分落在她那丰满的乳肉上。
“呼……呼……”
飞星喘着粗气,阳物仍然坚挺。
在花雾的影响下,丹枫与玉霜的双颊也已潮红。
丹枫伸手拂过脸颊上的元精塞入口中,同时坐起身来,横跨在飞星的双腿上。
两瓣阴唇已开,粉嫩的穴肉间已经流下了一道道阴液,她喘着气,眸中流露出几丝难耐的爱欲。
“师姐,那我先——”
她伸手握着飞星的阳物,对准了自己的穴口,俯下腰去——
阳物挤开湿润紧致的穴肉,深入腔穴,抵在了胞宫口上。
“啊~”
她仰头低吟一声,感受到下身的充实,满足地长舒一口气。
只见她的腰身缓缓前后摇动起来,丰满的乳肉开始晃荡,口中的娇吟渐渐频繁。
“啊~嗯~”
玉霜盯着两人的交合处,眉头不自觉地蹙起,轻咬着下唇,眼中流露出几丝羡慕,腔穴一缩,便淌出了一道阴液。
飞星看着她,手指微微一动。
玉霜明白他的意思,轻声道:
“你的体力还没恢复,不用勉强。”
飞星想了想,张开嘴,伸出了舌头。
玉霜脸颊欲红,低声道:
“明明你都这样了,我还……”
她说着,起身横跨在飞星的脖颈处,将已经泛滥的粉嫩下阴凑到了飞星的下颌处。
她羞声道:
“但我实在也有点忍不住了……”
飞星朝她微微一笑,伸出舌头舔上她的下阴。
“啊~~”
……
此刻的屋外。
日洒青石,风动翠枝。
广刹看向庭院中的试剑石,心中有些怀念。
院里一片安宁,整座福栖殿都安静无比。
她一间间屋子巡视过来,并未感知到任何动静。
只剩下最后一间了。
她看向那间屋子。
是玉霜师姐的屋子。
广刹来到门前,神色微微一变。
她感知到里面有人,但是却没听到任何声音。
隔音禁制?
可师姐这个时候不应该在落尘溪吗?
她眉头皱起,犹豫片刻后,伸手一推,破门而入——
……
—————
上述是小说一个章节的内容需要你为章节拟2句金庸武侠风格的七言绝句作为章节标题标题在精确概括章节内容外也需要充满文学性、浪漫性直接输出标题文字除了标题外严禁输出任何无关的文字禁止输出任何markdown格式
"""
);
log.info("response: {}", response);
}
public record Chapter(String title, String content) {
}
}