java初级项目 小说_webmagic项目实战(爬小说网站)

news/2024/5/13 15:40:46/文章来源:https://blog.csdn.net/weixin_42514432/article/details/115085322

正常发货正版包邮java从入门到软件

68.9元

包邮

(需用券)

去购买 >

74971ad7354243642bc8489d504c07c1.png

项目背景

小说网站优书网(http://yousuu.com/bookstore/)提供的小说查询功能不是很强大,很多高级查询功能都没有,比如想要查询出评分在8.0以上并且标签包含‘仙侠’、字数超过100万字的小说列表,查询结果按评分倒序排序。为了解决这个痛点,我们把所有小说数据(包含小说名称、评分、简介、作者等信息)爬到本地来,然后导入elasticsearch中,最后就可以构建出任何我们想要的查询了。

bVbyfCV?w=1012&h=869

bVbyfCW?w=1020&h=605

项目实战

实现分析

观察上面两张截图,可以看到列表页除了简介信息,其他信息都有;所以我们的实现思路就是从列表页提取出小说名称、作者、字数、评分、状态、标签等信息,从详情页提取出简介信息。

代码实现

通过文章《webmagic核心设计和运行机制分析》,我们已经知道在使用WebMagic框架时,因为每个页面的不同,所以必须要我们自己定制处理逻辑的组件是PageProcessor(解析html,提取目标数据)和Pipeline(持久化目标数据)。

1. Spider:程序入口,爬虫启动类

@Component

public class YousuuTask {

private static final String SITE_CODE = "yousuu";

private static final String URL = "http://www.yousuu.com/bookstore/?type&tag&countWord&status&update&sort&page=";

public void doTask() {

MySpider mySpider = MySpider.create(new YousuuProcessor());

mySpider.setDownloader(new MyDownloader(SITE_CODE));

mySpider.setScheduler(new RedisScheduler(SITE_CODE));

mySpider.addPipeline(new YousuuPipeline());

mySpider.thread(10);

int totalPage = 8187;

// 添加起始url

for(int i=1; i<=totalPage; i++) {

Request request = new Request(URL + i);

// 在Request额外信息中设置页面类型

request.putExtra(YousuuProcessor.TYPE, YousuuProcessor.LIST_TYPE);

mySpider.addRequest(request);

}

mySpider.run();

}

}

2. PageProcessor:解析html,提取目标数据

public class YousuuProcessor implements PageProcessor {

private Site site = Site.me().setRetryTimes(0).setSleepTime(2000).setTimeOut(60000);

public static final String TYPE = "type";

public static final String LIST_TYPE = "list";

public static final String DETL_TYPE = "detl";

@Override

public void process(Page page) {

// 从Request额外信息中取出页面类型,然后分别处理

String type = page.getRequest().getExtra(TYPE).toString();

switch (type) {

case LIST_TYPE:

processList(page);

break;

case DETL_TYPE:

processDetl(page);

break;

default:

break;

}

}

/**

* 处理列表页

* @param page

*/

private void processList(Page page) {

Html html = page.getHtml();

List bookInfoNodes = html.xpath("//div[@class=\"book-info\"]").nodes();

List novelList = new ArrayList<>();

for(Selectable node : bookInfoNodes) {

String novelName = node.xpath("/div/a/text()").toString();

String novelUrl = node.xpath("/div/a/@href").toString();

String id = novelUrl.substring(novelUrl.lastIndexOf("/") + 1);

// 将详情页url添加到调度器

Request detlRequest = new Request("http://www.yousuu.com/book/" + id);

detlRequest.putExtra(TYPE, DETL_TYPE);

page.addTargetRequest(detlRequest);

// 子节点下标值从1开始

String author = node.xpath("/div/p[1]/router-link/text()").toString();

String wordNum = node.xpath("/div/p[1]/span[1]/text()").toString();

String lastUpdateTime = node.xpath("/div/p[1]/span[2]/text()").toString();

String status = node.xpath("/div/p[1]/span[3]/text()").toString();

String scoreStr = node.xpath("/div/p[2]/text()").toString();

scoreStr = scoreStr.substring("综合评分:".length());

String[] split = scoreStr.split("\\(");

Double score = Double.valueOf(split[0]);

String scorePersonNumStr = split[1].substring(0, split[1].length() - 2);

Integer scorePersonNum = Integer.valueOf(scorePersonNumStr);

List tagNodes = node.xpath("/div/p[4]/label").nodes();

StringBuffer tagBuff = new StringBuffer();

for(Selectable tagNode : tagNodes) {

String tag = tagNode.xpath("/label/text()").toString();

tagBuff.append(tag + ",");

}

String tags = null;

if(tagBuff.length() > 0) {

tags = tagBuff.substring(0, tagBuff.length()-1);

}

Novel novel = new Novel();

novel.setId(Long.valueOf(id));

novel.setName(novelName);

novel.setAuthor(author);

novel.setWordNum(NumberUtil.getDoubleNumber(wordNum));

novel.setLastUpdateTime(lastUpdateTime);

novel.setStatus(status);

novel.setScore(score);

novel.setScorePersonNum(scorePersonNum);

novel.setTags(tags);

novelList.add(novel);

}

page.putField("novelList", novelList);

}

/**

* 处理详情页

* @param page

*/

private void processDetl(Page page) {

Html html = page.getHtml();

List nodes = html.xpath("//body/*[1]").nodes();

String script = nodes.get(1).toString();

int pos1 = script.indexOf("introduction");

int pos2 = script.indexOf("countWord");

String intro = script.substring(pos1+15, pos2-3);

String url = page.getRequest().getUrl();

String id = url.substring(url.lastIndexOf("/") + 1);

NovelDTO novelDTO = new NovelDTO(Long.valueOf(id), intro);

page.putField("novelDTO", novelDTO);

}

@Override

public Site getSite() {

site.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3");

site.addHeader("Accept-Encoding", "gzip, deflate");

site.addHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");

site.addHeader("Cache-Control", "max-age=0");

site.addHeader("Connection", "keep-alive");

site.addHeader("Cookie", "Hm_lvt_42e120beff2c918501a12c0d39a4e067=1566530194,1566819135,1566819342,1566963215; Hm_lpvt_42e120beff2c918501a12c0d39a4e067=1566963215");

site.addHeader("Host", "www.yousuu.com");

site.addHeader("Upgrade-Insecure-Requests", "1");

site.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36");

return site;

}

}

说明:通过Request额外信息传递类型值type,来区分从Scheduler中拉取出来的URL对应页面类型,然后分别解析处理。

3. Pipeline: 持久化目标数据

/**

* 持久化小说数据

*/

public class YousuuPipeline implements Pipeline {

private NovelMapper novelMapper = SpringContextUtil.getBean(NovelMapper.class);

@Override

public void process(ResultItems resultItems, Task task) {

//从列表页提取出除小说简介以外的所有信息,批量插入

Object novelListObj = resultItems.get("novelList");

if(null != novelListObj) {

List novelList = (List) novelListObj;

if(CollectionUtils.isNotEmpty(novelList)) {

novelMapper.batchInsert(novelList);

}

}

//从详情页提取出小说简介信息,更新

Object novelDTOObj = resultItems.get("novelDTO");

if(null != novelDTOObj) {

NovelDTO novelDTO = (NovelDTO) novelDTOObj;

Novel novel = new Novel();

BeanUtils.copyProperties(novelDTO, novel);

novelMapper.updateByPrimaryKeySelective(novel);

}

}

}

4. 实体类

@Data

public class Novel implements Serializable {

/**

* 小说id,自增

*/

@Id

private Long id;

/**

* 小说名称

*/

private String name;

/**

* 小说作者

*/

private String author;

/**

* 小说字数(万字)

*/

private Double wordNum;

/**

* 小说状态

*/

private String status;

/**

* 小说评分

*/

private Double score;

/**

* 评分人数

*/

private Integer scorePersonNum;

/**

* 最后更新时间

*/

private String lastUpdateTime;

/**

* 小说标签,以逗号,分割

*/

private String tags;

/**

* 小说简介

*/

private String intro;

}

5. 测试程序

@RunWith(SpringRunner.class)

@SpringBootTest

public class SpiderApplicationTests {

@Autowired

YousuuTask yousuuTask;

@Test

public void test() {

yousuuTask.doTask();

}

}

运行结果

bVbyfC3?w=1283&h=513

构建查询

最后将数据库表中保存的小说数据导入到es中(程序源码地址会在本文最后给出),编写DSL构建出我们需要的查询。

bVbyfYG?w=1692&h=874

源代码地址

spider:https://github.com/xiawq87/sp...

es:https://github.com/xiawq87/no...

原文链接:https://segmentfault.com/a/1190000020518561

java 11官方入门(第8版)教材

79.84元

包邮

(需用券)

去购买 >

f0f3f55624fb396b1764d42d6df88864.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_769779.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站服务器空间域名绑定,服务器空间怎么绑定域名

服务器空间怎么绑定域名 内容精选换一换一个网卡只能绑定一个EIP。您需要多个EIP时&#xff0c;可以将EIP绑定到扩展网卡&#xff0c;但扩展网卡绑定EIP以后&#xff0c;需要在裸金属服务器内根据实际网络情况做相应的操作&#xff0c;例如&#xff1a;增加策略路由或者命名空间…

数万网站仍在使用有已知漏洞的老旧 JavaScript 库

美国东北大学研究人员在对超过 133000 个网站分析时发现&#xff0c;有超过 37% 的站点仍在使用至少包含一个已知公开漏洞的 JavaScript 库。研究人员早在 2014年进行研究时就曾提醒&#xff0c;应当注意由于在浏览器中加载老旧版本的 JavaScript 库&#xff08;如 jQuery、Ang…

Firefox 55不会将用户位置提供给非https网站

在2017年8月&#xff0c;Mozilla将发布Firefox 55。一个值得注意的变化是那些不安全的网站将无法获取用户的地理位置数据&#xff0c;这些信息将只发送到HTTPS和加密的WebSocket连接&#xff0c;这一举动是浏览器制造商推动网站采用更安全协议的另一个步骤。 根据Mozilla在五个…

资深程序员总结了9个java学习需要收藏的网站!

第一个&#xff1a;JavaSED这是1个很大的资源类型的网站&#xff0c;涉及了很多Java代码案例。这个网站也可以查看很多Java API类源代码&#xff0c;值得收藏&#xff01;第二个&#xff1a;Code Project这篇文章分享之前我还是要推荐下我自己的JAVA群&#xff1a;452180294 &a…

seo说_百度指数看世间沉浮_如何快速排名-互点快速排名_揭秘!如何快速提高网站权重...

一看标题相信可能很多人就会说标题档、忽悠人的&#xff0c;因为网站优化没有捷径。的确&#xff0c;小麦也说过做推广优化没有快速的方法&#xff0c;想要排名就得脚踏实地。不过最近小麦公司不少客户都会问到我们能快速提高网站权重么&#xff0c;小麦今天来给大家好好解释下…

一个完整网站的代码_网站无法访问的链接要怎样处理才符合SEO优化规章

如何编写一个完整的SEO解决方案?首先,我们需要知道SEO解决方案对于优化的速度影响非常重要,如果网站是用优秀的SEO解决方案建立的&#xff0c;之后&#xff0c;按照这个方案一步一步地实行&#xff0c;必要时加以修正&#xff0c;通常会在预料之内达到效果&#xff0c;远远超出…

SEO实战干货:利用老域名打造新站快速收录排名!

当SEO变成人云亦云的时候&#xff0c;那么你对SEO永远只会趋之若鹜。在卢松松平台投稿过数篇关于SEO的文章&#xff0c;不少朋友都说写的都是软文&#xff0c;关于这个话题我只想说一句&#xff0c;因为你没有做过&#xff0c;所以你认为是软文&#xff0c;如果每一篇文章都能够…

阿里云域名+老薛主机 搭建个人博客网站 小结

本人将之前写在自己网站的搭建网站过程的文章&#xff0c;搬过来了&#xff0c;要问为啥&#xff0c;因为精力有限&#xff0c;没有时间在自己的网站上折腾^...^ 虽然之前截的图片不能看了&#xff0c;但是不影响你照着本人的博客&#xff0c;自己独立搭建网站。 【声明】 欢迎…

网站复制图片保存自己服务器,WordPress将复制别的网站的文章里的图片自动保存到自己的服务器...

WordPress将复制别的网站的文章里的图片自动保存到自己的服务器王超 2020-10-29 插件使用 1,509 次我们都知道一个网站上的内容尽量的去做原创&#xff0c;这样对SEO优化是有好处的&#xff0c;但是有时我们没有太多精力原创或者由于其他原因&#xff0c;需要从其他的网站上复制…

途牛网站的用的什么服务器,途牛网某服务器配置不当致泄露数G源码和数G数据...

途牛网因某处配置不当&#xff0c;存在未授权访问&#xff0c;导致泄露数十G代码和数十G数据库泄露。声明&#xff1a;下载这些内容只是为了验证漏洞&#xff0c;以及看是否有更加高危的漏洞。无奈&#xff0c;量太大&#xff0c;没有精力在继续深入下去。在提交漏洞完成后&…

网站和数据库放在两个服务器,网站和数据库放在两个服务器

网站和数据库放在两个服务器 内容精选换一换PHPWind(简称&#xff1a;PW)是一个基于PHP和MySQL的开源社区程序&#xff0c;是国内较受欢迎的论坛之一。轻架构&#xff0c;高效易开发&#xff0c;使用户可快速搭建并轻松管理。本文档指导用户使用华为云市场镜像“PHPWind 论坛社…

【收藏】这么多WEB组件(CSS),攒一个网站够了吧?

1 表单(form)相关 1.1 输入框(input) 一个简单的输入框样式&#xff0c;简捷又不夸张。需要约30行的CSS代码。 演示程序 1.2 单选多选框(checkbox,radio) 浏览器内置的checkbox及radio样式效果太差&#xff0c;本例展示了一个简单大方的单选多选框样式。需要约25行的CSS代码&am…

搭建个人网站--域名解析(DNS)

一、DNS&#xff08;域名系统&#xff09;的定义 Domain NameSystem&#xff0c;简称DNS&#xff0c;因特网上作为域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使用户更方便的访问互联网&#xff0c;而不用去记住能够被机器直接读取的IP数串。通过主机名&#xff…

搭建个人网站--搭建网站

一、环境搭建&#xff08;windows10&#xff09; 1、node.js的介绍与安装 &#xff08;1&#xff09;介绍&#xff1a;Nodejs &#xff08;2&#xff09;安装&#xff1a;node.js安装教程 2、Git 的介绍与安装 &#xff08;1&#xff09;GitHub 使用教程 <精华帖> …

通过域名访问网站的原理过程

一、域名解析图二、常识 1、IP地址是直接能访问网站的&#xff0c;之所以用域名访问原因如下&#xff1a; &#xff08;1&#xff09;但是IP地址不好记&#xff1b; &#xff08;2&#xff09;IP地址是一堆数字对用户不友好&#xff1b; &#xff08;3&#xff09;正常情况下对…

程序员应该访问的最佳网站中文版

程序员应该访问的最佳网站中文版原版 原文链接 :https://github.com/tuteng/Best-websites-a-programmer-should-visit-zh/blob/master/README.md 一些对程序员有用的网站 在学习CS的时候有一些你必须知道的有用的站点来获取通知为了你的技术储备和学习新知识。这里是一个你…

微软正式发布Azure Storage上的静态网站

微软正式宣布了Azure Storage上的静态网站&#xff0c;提供了从托管在Azure Storage上的HTML、CSS和JavaScript文件提供内容的能力。静态网站包含内容固定的Web页面&#xff0c;同时仍然允许利用JavaScript等客户端代码来创建丰富的用户体验。 有了这个新功能&#xff0c;继用于…

网站配置SSL证书实现HTTPS加密访问方式过程

如今我们越来越多的网站会使用SSL证书配置HTTPS网址。因为如果我们不配置的话在浏览器会直接提示不安全网站&#xff0c;这些说实话确实有点强制&#xff0c;因为有些项目不需要用到HTTPS&#xff0c;但是迫于浏览器的强制我们也只能纷纷去使用SSL证书。还好如今免费证书比较多…

滑天下之大稽,某博客网站竟然借鉴视频网站的设计风格来做首页

故西施病心而颦其里&#xff0c;其里之丑人见而美之&#xff0c;归亦捧心而矉其里。其里之富人见之&#xff0c;坚闭门而不出&#xff1b;贫人见之&#xff0c;挈妻子而去之走。彼知颦美&#xff0c;而不知颦之所以美 本篇文章不是实锤CSDN抄袭Bilibili的设计风格 单纯吐槽一个…

vue-i18n中英文或者多语言切换的网站在vue项目中的合理布局结构

使用很简单&#xff0c;官网地址&#xff1a;http://kazupon.github.io/vue-i18n/zh/ npm install vue-i18n --save 新建一个文件夹。及其文件。如下图 index.js文件 import Vue from vue; import VueI18n from vue-i18n; // import { isInLanguage } from /utils/validate;…