一、任务:

旨在通过使用java爬虫,提取网络中的各种商品信息,并收集的商品信息建立统一数据模型存储数据,通过数据模型描述商品的基本属性。如spu,sku,商品描述,价格等信息,同时需要剔除非必要信息,做到精准分析。根据所获取的信息提供商品展示页面,通过搜索,得到商品数据信息。抓取商品数据,建立统一数据模型,模型的可扩展性,商品数据展示。

目的:该项目有利于简单理解java的爬虫过程,spring boot简单的项目调试,调用,映射方式,数据库连接,帮助理解的前后端交互原理。

二、类及数据的设计

2.1项目的开发环境

2.2系统功能结构设计

该程序主要通过调用webmagic使用爬虫功能爬取数据,建立数据模型,利用MySQL存储数据。查询调用数据库内容,模型的可扩展性,通过html/css提供web页面展示。

2.2.1数据爬取,数据模型建立

WebMagic:

WebMagic的结构分为Downloader、PageProcessor、Scheduler、Pipeline四大组件,并由Spider将它们彼此组织起来。

1)Downloader:负责从互联网上下载页面,以便后续处理。WebMagic默认使用了Apache HttpClient作为下载工具。

2)PageProcessor:负责解析页面,抽取有用信息,以及发现新的链接。WebMagic使用Jsoup作为HTML解析工具,并基于其开发了解析XPath的工具Xsoup。在这四个组件中,PageProcessor对于每个站点每个页面都不一样,是需要使用者定制的部分。

3)Scheduler:负责管理待抓取的URL,以及一些去重的工作。WebMagic默认提供了JDK的内存队列来管理URL,并用集合来进行去重。也支持使用Redis进行分布式管理。除非项目有一些特殊的分布式需求,否则无需自己定制Scheduler。

4)Pipeline:负责抽取结果的处理,包括计算、持久化到文件、数据库等。WebMagic默认提供了“输出到控制台”和“保存到文件”两种结果处理方案。Pipeline定义了结果保存的方式,如果你要保存到指定数据库,则需要编写对应的Pipeline。对于一类需求一般只需编写一个Pipeline。

Selenium:

Selenium是一个Web的自动化测试工具,可以根据我们的指令,使用代码控制浏览器,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生,支持主流的浏览器

该程序使用Downloader、PageProcessor、Pipeline,Spider组件进行爬虫,建立数据模型。通过selenium对谷歌无头浏览器进行自动化操作。

1、定时任务

在springboot工程中使用定时器。在工程中创建一个普通的类,添加注解@Component,

在定义方法上使用@Scheduled注解标注,配置定期执行时间,在spring boot工程的引导类上添加@EnableScheduling注解。

2、设置代理

使用代理服务器发起请求,防止反爬策略封ip

代理服务器流程:

爬虫服务器 -> 代理服务器 -> 目标服务器

目标服务器 -> 代理服务器 -> 爬虫服务器 ->解析数据

可用的免费代理:

免费私密代理 - 米扑代理

http://www.xiladaili.com/gaoni/

3、使用selenium+无头浏览器抓取数据

通过Maven添加Selenium依赖。Selenium是一个前端的测试框架,通过Selenium使用代码控制浏览器。

无头浏览器:没有界面的浏览器,解析js。得到一些默认不到的数据。用于各类测试场景,在任何给定页面上可采取的频繁重复的操作,反复测试。

4、使用浏览器渲染,抓取京东商城的数据并保存

1)PageProcess解析html

1. 判断是列表页面还是详细页面

2. 如果是列表页面

a、解析列表中的商品数据,去sku和spu,封装成一个对象,传递给pipeline

b、解析商品的链接地址,把地址添加到访问队列中

c、翻页处理,设置固定url:Enterprise Cybersecurity Solutions, Services & Training | Proofpoint US 添加一个附件:当前请求的url

3. 如果是详细页面

a、解析商品的详细信息

b、把详细信息封装成一个商品对象

c、传递给pipeline

2)Downloader下载页面

1. 抓取列表页面

a、访问url

b、页面滚动到最下方

c、从浏览器中取html

d、需要把结构封装成Page对象

2. 如果是详情页面

a、直接访问url

b、取html,封装成Page,返回

3. 如果是翻页处理

a、从Request对象中取附件,翻页之前的url

b、访问url

c、点击翻页按钮,翻到第二页

d、让页面滚到最下方,加载30条数据

e、把去浏览器渲染的html结果封装成Page对象返回

3)Pipeline保存到数据库

创建数据库表,创建对应的属性

5、模型的可扩展性

基于springboot的控制反转,类与类之间没有很强的耦合性,具有很好的“特性:“高内聚、低耦合”实例化的操作交给Spring 的bean工厂,通过xml配置文件去记录。所以模型具有很强的可扩展性。只需在Item中添加属性,并添加对应的浏览器操作。

2.2.2 SpringBoot+Ajax+MyBatis查询操作数据库

开发顺序

后端SpringBoot+MyBatis, 前端Ajax+jQuery+CSS+HTML,通过爬虫操作得到数据,根据数据对于后端接口数据设计和使用,前端数据请求和响应填充界面的过程,数据库采用MySQL 8.0.26,用于学习掌握前后端开发的关键技术和开发架构。

随着 Spring Boot 越来越流行,MyBatis 也开发了一套基于 Spring Boot 模式的 starter:mybatis-spring-boot-starter。

entity层:存放的是实体类,属性值与数据库值保持一致,实现 setter 和 getter 方法。

dao层:即 mapper层,对数据库进行持久化操作,他的方法使针对数据库操作的,基本上用的就是增删改查。作为接口,只有方法名,具体实现在mapper.xml中实现。

service层:业务层,存放业务逻辑处理,不直接对数据库进行操作,有接口和接口实现类,提供 controller 层调用方法。

controller层:控制层,导入 service层,调用你service方法,controller通过接受前端传来的参数进行业务操作,在返回一个制定的路径或数据表。

选择ajax原因是基于爬虫操作数据量大,变化多,AJAX能提供在无需重新加载整个网页的情况下,能够更新部分网页的技术。AJAX 是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

而选择MyBatis,因为MyBatis可以使用简单的XML或注释进行配置,并将图元,映射接口和 POJO映射到数据库记录。消除了大部分JDBC代码以及参数的手动设置和结果检索。同时基于MyBatis灵活特性,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,更加为程序的可拓展性提供基础。

、部分代码

3.1爬虫部分

@Overridepublic void process(Page page) {String level = page.getRequest().getExtra("level").toString();switch (level){case "list":parseList(page);break;case "detail":praseDetail(page);break;}/*** 解析详情页** @param page*/private void praseDetail(Page page) {Html html = page.getHtml();String title = html.$("div.master .p-name").xpath("///allText()").get();String priceStr = html.$("div.summary-price-wrap .p-price span.price").xpath("///allText()").get();String pic = "https:"+html.$("#spec-img").xpath("///@src").get();String url = "https:"+html.$("div.master .p-name a").xpath("///@href").get();String sku = html.$("a.notice.J-notify-sale").xpath("///@data-sku").get();Item item = new Item();item.setTitle(title);item.setPic(pic);item.setPrice(Float.valueOf(priceStr));item.setUrl(url);item.setUpdated(new Date());item.setSku(StringUtils.isNotBlank(sku)?Long.valueOf(sku) : null);// 单条数据塞入page.putField("item", item);}/*** 解析列表页* @param page*/private void parseList(Page page) {Html html = page.getHtml();// 这里拿到sku 和 spu 并交给pipelineList<Selectable> nodes = html.$("ul.gl-warp.clearfix > li").nodes();List<Item> itemList = new ArrayList<>();for (Selectable node : nodes) {// 拿到sku和spuString sku = node.$("li").xpath("///@data-sku").get();String spu = node.$("li").xpath("///@data-spu").get();String href = "https:" + node.$("div.p-img a").xpath("///@href").get();Item item = new Item();item.setSku(Long.valueOf(sku));item.setSpu(StringUtils.isNotBlank(spu) ? Long.valueOf(spu) : 0);item.setCreated(new Date());itemList.add(item);// 同时还需要把链接加到详情页 加到队列Request request = new Request(href);request.putExtra("level", "detail");request.putExtra("pageNum", page.getRequest().getExtra("pageNum"));request.putExtra("detailUrl", href);page.addTargetRequest(request);}// 以集合的方式存入page.putField("itemList", itemList);// 同时还要去做分页String pageNum = page.getRequest().getExtra("pageNum").toString();if ("1".equals(pageNum)){Request request = new Request("https://nextpage.com");request.putExtra("level", "page"); // 标识去分页request.putExtra("pageNum", (Integer.valueOf(pageNum) + 1) + "");// 页码要+1 接下来要的是第二页// 添加到队列page.addTargetRequest(request);}

3.2 spring boot查询操作数据库

Control控制层:@RestController//返回rest服务类型的数据格式@RequestMapping("/Jd")//数据接口controller怎么被调用public class ItemController {//调用一些方法得到返回值,把服务层作为对象@Autowired//自动注入,生成实例private ItemService itemService;//好封装@GetMapping("/getJd")//路径如果是Jd下的getJd,会获得前端传来的参数‘id',获得值,把id值传到findById方法中public String getItem(@Param("id")Integer id){Item item = itemService.findById(id);return item.getTitle();}@GetMapping("/getId") // 通过title// 获取idpublic Integer getId(@Param("Message") String title){Item item = itemService.findByTitle(title);return item.getId();}@GetMapping("/getOne") // 通过title// 获取id,一条数据记录public Item getAll(@Param("id") Integer id){Item item = itemService.findById(id);return item;}@GetMapping("/getJson") // 通过title获取idpublic String getJson(@Param("id") Integer id) {Item item = itemService.findById(id);Gson gson = new Gson();return gson.toJson(item);}@GetMapping("/getAll") // 通过title获取id,获得多条数据public List<Item> getAll(){List<Item> list = itemService.findItemAll();return list;}@GetMapping("/getAllJson") // 通过title获取idpublic String getAllJson(){List<Item> list = itemService.findItemAll();Gson gson = new Gson();return gson.toJson(list);}
}

3.3前端设计

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" type="text/css"href="https://cdn.bootcss.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css">
<script type="text/javascript"src="https://cdn.bootcss.com/jquery/1.4.0/jquery.js"></script>
<script>
$(document).ready(function(){
$("#btn1").click(function(){
test1();
});$("#btn2").click(function(){
$.test2();
});
});
//data为数组
function test1(){
//alert("Text1: " + $("#test").text());
$.ajax({
url:'/msg/getAllJson',//访问后台接口,用get,后台返回json
type:'get',
dataType:'json',
success:function(data){
$("#tabletest").find('tr').remove();
tr='<td>id</td><td>title</td>'
$("#tabletest").append('<tr>'+tr+'</tr>')
//方法中传入的参数data为后台获取的数据
for(i in data) //data指的是数组,i为数组的索引
{
var tr;
tr='<td>'+data[i].id+'</td>'+'<td>'+data[i].title +'</td>'
$("#tabletest").append('<tr>'+tr+'</tr>')
}
}
});
}
</script>
<style type="text/css">
.center{
margin: auto;
text-align:center;
font-size: 24px;
width: 60%;
background: lightblue;
}
</style>
</head>
<body>
<div class="center">
<p id="test">Springboot整合MyBatis通过ajax查询MySQL数据库数据</b></p>
<button id="btn1">显示所有数据</button>
<button id="btn2">查询</button>
<input id="id" name="id" type="text" placeholder="请输入id值"/>
<br>
<table class="table table-bordered" id='tabletest'>
</table>
</div>
</body>
</html>

四、程序运行、测试与分析

4.1程序运行

4.2总结分析

  1. 在使用java程序应注意jdk版本问题,以及jdk对应的数据库版本。
  2. 在使用数据库操作时,应注意数据库与idea连接application中的url,username,password格式问题。
  3. 应注意传入数据文件路径相对绝对路径问题。
  4. 学习通过debug,逐步了解一个项目的进程,排除错误。
  5. 在调试程序中,应该带着思考搜索解决方式,逐一排除造成错误的原因。
  6. 了解各种注释API作用,有助于优化代码。
  7. 对于繁多的技术,需要从需求出发,合理选择合适,高效,可拓展的技术。
  8. 通过程序更加深入了解前后端工作方式,更加理解springboot的工作原理。

4.3改进方案

4.3.1对于爬虫:

首先可以通过更高效的框架加快爬虫速度,实现更加灵活的定制化爬取。其次,可以通过优化算法,对于一些爬取失败或数据获取失败的记录进行汇总,在页面反馈成功完整数据,通过网页分析算法过滤主题无关的链接。

交互问题是一个需要解决的问题,爬取会页面涉及到用户信息输入,验证码处理,随着各类花样繁多的验证码的出现,爬虫遇到这种情况会很难处理。

Javascript 解析问题,目前大多数网页属于动态网页,网页中大多数有用的数据都是通过ajax/fetch动态获取后然后再由js填充到网页,单纯的html静态页面中有用的数据很少。让后台脚本去做javascript操作会很麻烦,不仅需要清楚的理解原网页代码逻辑也会让代码显得很臃肿。

ip解析问题,尽管在本程序使用代理ip,但这仍然是爬虫会遇到的最致命问题。网站防火墙会对某个ip在某段时间内请求的次数做限制,如果超过上限则拒绝请求。后台爬取时机器和ip有限,很容易达到上线而导致请求被拒绝。目前主要的应对方案是使用代理,这样一来ip的数量就会多一些,但代理ip依然有限。

4.3.2.前端太丑,过于简陋

Java爬虫爬取京东商城相关推荐

  1. 利用python爬虫爬取京东商城商品图片

    笔者曾经用python第三方库requests来爬取京东商城的商品页内容,经过解析之后发现只爬到了商品页一半的图片.(这篇文章我们以爬取智能手机图片为例) 当鼠标没有向下滑时,此时查看源代码的话,就会 ...

  2. python爬虫完整实例-python爬虫实战之爬取京东商城实例教程

    前言 本文主要介绍的是利用python爬取京东商城的方法,文中介绍的非常详细,下面话不多说了,来看看详细的介绍吧. 主要工具 scrapy BeautifulSoup requests 分析步骤 1. ...

  3. 爬虫python的爬取步骤-python爬虫实战之爬取京东商城实例教程

    前言 本文主要介绍的是利用python爬取京东商城的方法,文中介绍的非常详细,下面话不多说了,来看看详细的介绍吧. 主要工具 scrapy BeautifulSoup requests 分析步骤 1. ...

  4. python爬虫爬图片教程_python爬虫实战之爬取京东商城实例教程

    前言 本文主要介绍的是利用python爬取京东商城的方法,文中介绍的非常详细,下面话不多说了,来看看详细的介绍吧. 主要工具 scrapy BeautifulSoup requests 分析步骤 1. ...

  5. python 爬网站 实例_python爬虫实战:之爬取京东商城实例教程!(含源代码)

    前言: 本文主要介绍的是利用python爬取京东商城的方法,文中介绍的非常详细,下面话不多说了,来看看详细的介绍吧. 主要工具 scrapy BeautifulSoup requests 分析步骤 1 ...

  6. python爬京东联盟_python爬虫框架scrapy实战之爬取京东商城进阶篇

    前言 之前的一篇文章已经讲过怎样获取链接,怎样获得参数了,详情请看python爬取京东商城普通篇,本文将详细介绍利用python爬虫框架scrapy如何爬取京东商城,下面话不多说了,来看看详细的介绍吧 ...

  7. 爬虫利器Pyppeteer的介绍和使用 爬取京东商城书籍信息

    提起 selenium 想必大家都不陌生,作为一款知名的 Web 自动化测试框架,selenium 支持多款主流浏览器,提供了功能丰富的API 接口,经常被我们用作爬虫工具来使用.但是 seleniu ...

  8. 爬虫利器Pyppeteer的介绍和使用 爬取京东商城书籍信息!

    提起 selenium 想必大家都不陌生,作为一款知名的 Web 自动化测试框架,selenium 支持多款主流浏览器,提供了功能丰富的API 接口,经常被我们用作爬虫工具来使用.但是 seleniu ...

  9. python爬虫爬取教程_python爬虫实战之爬取京东商城实例教程

    前言 本文主要介绍的是利用python爬取京东商城的方法,文中介绍的非常详细,下面话不多说了,来看看详细的介绍吧. 主要工具 scrapy BeautifulSoup requests 分析步骤 1. ...

  10. Java爬虫爬取 天猫 淘宝 京东 搜索页和 商品详情

    Java爬虫爬取 天猫 淘宝 京东 搜索页和 商品详情 先识别商品url,区分平台提取商品编号,再根据平台带着商品编号爬取数据. 1.导包 <!-- 爬虫相关Jar包依赖 --><d ...

最新文章

  1. SCVMM2012 SP1 添加VMware vCenter服务器
  2. 吃完降压药多久能睡觉 降压药什么时候吃好
  3. Python图像处理库:PIL中Image,ImageDraw等基本模块介绍
  4. PHP CURL 使用代理访问服务器
  5. 台式电脑键盘按键错乱_收藏篇:电脑键盘上的每个按键的作用和命令你都会用么...
  6. python 矩阵库_NumPy 矩阵库(Matrix)
  7. 合并两个有序链表,合并后依然有序(C语言)
  8. sbt笔记二 Running
  9. android+噪音测试,关于噪音测试App的选择与使用
  10. python如何加载图片_python如何导入图片
  11. 湖北省土壤有机质空间分布数据
  12. 济南 天然气 暖气 物业费 水费 电费价格
  13. 程序员出身的史玉柱,曾写了50万行代码,他的编程水平怎样?
  14. 服务交付服务规范十要素
  15. ABB机器人ProgramEditor(程序编辑器)调试菜单详解
  16. 儿童手表运动轨迹和路径追踪_如何将智能手表或健身追踪器用作静音闹钟
  17. 防火墙Deny记录实时检测
  18. js兼容安卓和IOS的复制文本到剪切板,已做浏览器兼容处理,勿需插件
  19. 牛客网sql练习题解(12-21)
  20. C/C++编程工具及实用小软件推荐_dvlinker的博客-CSDN博客_编写c++的软件

热门文章

  1. 基于DDPG的智能交通灯控制算法
  2. Eucalyptus云平台搭建
  3. 异步FIFO设计与实现及相关问题
  4. c语言c9考试软件下载,二级c语言考试系统-无忧考吧二级c语言考试系统下载 v2018.09官方版--pc6下载站...
  5. 通过ICE轻松部署WES7镜像
  6. lede固件_开源路由器固件OPENWRT/LEDE出现远程代码执行漏洞请尽快升级
  7. Flutter 实现 仿Android原生启动模式SingleTask
  8. 分段三次hermite插值python
  9. exe模拟器android版,安卓exe模拟器
  10. 计算机自带扫雷游戏玩不了,Win7 32位系统扫雷游戏打不开如何解决【图文教程】...