java抓取网页数据(java爬虫简单理解java的爬虫项目调试任务)
优采云 发布时间: 2022-02-24 22:15java抓取网页数据(java爬虫简单理解java的爬虫项目调试任务)
一、任务:
其目的是利用java爬虫提取网络中的各种商品信息,并建立统一的数据模型来存储采集到的商品信息中的数据,并通过数据模型描述商品的基本属性。如spu、sku、产品描述、价格等信息,需要剔除不必要的信息才能达到准确分析。根据获取的信息提供产品展示页面,通过搜索获取产品数据信息。采集产品数据,建立统一的数据模型,模型可扩展,展示产品数据。
目的:本项目有利于简单了解java的爬虫流程,简单的项目调试,调用,映射方法,spring boot的数据库连接,前后端交互的原理,帮助理解。
二、类与数据设计2.1项目开发环境
2.2 系统功能结构设计
程序主要使用爬虫功能通过调用webmagic来爬取数据,建立数据模型,使用MySQL存储数据。查询调用数据库内容,模型的扩展性,通过html/css提供网页展示。
2.2.1数据爬取,数据模型建立
网络魔术:
WebMagic 的结构分为四大组件:Downloader、PageProcessor、Scheduler 和 Pipeline,它们由 Spider 组织。
1)Downloader:负责从互联网上下载页面进行后续处理。WebMagic 默认使用 Apache HttpClient 作为下载工具。
2)PageProcessor:负责解析页面,提取有用信息,发现新链接。WebMagic 使用 Jsoup 作为 HTML 解析工具,并在其基础上开发了 Xsoup,一个解析 XPath 的工具。这四个组件中,PageProcessor对于每个站点的每个页面都是不同的,是需要用户自定义的部分。
3)Scheduler:负责管理要爬取的URL,以及一些去重工作。WebMagic 默认提供 JDK 的内存队列来管理 URL,并使用集合进行去重。还支持使用 Redis 进行分布式管理。除非项目有一些特殊的分布式需求,否则不需要自己定制Scheduler。
4)Pipeline:负责提取结果的处理,包括计算、持久化到文件、数据库等。WebMagic默认提供两种结果处理方案:“输出到控制台”和“保存到文件”。Pipeline 定义了保存结果的方式。如果要保存到指定的数据库,需要编写相应的Pipeline。通常,对于一类需求,只需要编写一个 Pipeline。
硒:
Selenium 是一个用于 Web 的自动化测试工具。它可以根据我们的指令用代码控制浏览器,让浏览器自动加载页面,获取需要的数据,甚至对页面进行截图,或者判断网站上的某些动作是否发生。, 支持主流浏览器
该程序使用 Downloader、PageProcessor、Pipeline 和 Spider 组件来爬取和构建数据模型。使用 selenium 自动化 Google 的无头浏览器。
1、计划任务
在 springboot 项目中使用计时器。在项目中创建一个普通类,添加注解@Component,
在定义方法上使用@Scheduled注解,配置定时执行时间,在spring boot项目的boot类上添加@EnableScheduling注解。
2、设置代理
使用代理服务器发起请求,防止反爬策略阻塞ip
代理服务器进程:
爬虫服务器 -> 代理服务器 -> 目标服务器
目标服务器->代理服务器->爬虫服务器->解析数据
提供免费代理:
免费私人代理 - 米扑代理
3、使用selenium+headless浏览器抓取数据
通过 Maven 添加 Selenium 依赖项。Selenium 是一个前端测试框架,通过 Selenium 使用代码来控制浏览器。
无头浏览器:没有界面的浏览器,解析js。获取一些默认情况下不可用的数据。用于各种测试场景,可以在任何给定页面上执行的频繁重复操作,重复测试。
4、使用浏览器渲染,抓取京东商城的数据并保存
1)PageProcess 解析 html
2)下载器下载页面
3)管道保存到数据库
5、模型可扩展性
2.2.2?SpringBoot+Ajax+MyBatis查询操作数据库
发展秩序
实体层:存放实体类,其属性值与数据库值一致,实现setter和getter方法。
Dao层:即mapper层,对数据库进行持久化操作。他的方法基本上是对数据库操作进行增删改查。作为接口,只有方法名,具体实现在mapper.xml中实现。
服务层:业务层,存储业务逻辑处理,不直接对数据库进行操作,有接口和接口实现类,提供控制器层调用方法。
控制器层:控制层,导入服务层,调用你的服务方法,控制器通过接受前端的参数进行业务操作,返回指定的路径或数据表。
选择ajax的原因是爬虫操作数据量大,变化多。AJAX 可以提供一种无需重新加载整个网页即可更新部分网页的技术。AJAX 是一种用于创建快速和动态网页的技术。AJAX 可以通过在后台与服务器交换少量数据来异步更新网页。这意味着可以在不重新加载整个页面的情况下更新页面的某些部分。
相反,选择 MyBatis,因为 MyBatis 可以使用简单的 XML 或注释进行配置,并将原语、映射接口和 POJO 映射到数据库记录。消除了大部分 JDBC 代码以及手动设置参数和检索结果。同时,基于 MyBatis 的灵活特性,不会对应用程序或数据库的现有设计造成任何影响。SQL采用XML编写,与程序代码完全分离,降低了耦合度,为程序的可扩展性提供了基础。
?三、部分代码3.1个爬虫部分
@Override
public 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 并交给pipeline
List nodes = html.$("ul.gl-warp.clearfix > li").nodes();
List itemList = new ArrayList();
for (Selectable node : nodes) {
// 拿到sku和spu
String 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// 获取id
public 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获取id
public 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 getAll(){
List list = itemService.findItemAll();
return list;
}
@GetMapping("/getAllJson") // 通过title获取id
public String getAllJson(){
List list = itemService.findItemAll();
Gson gson = new Gson();
return gson.toJson(list);
}
}
3.3前端设计
Title
$(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='idtitle'
$("#tabletest").append(''+tr+'')
//方法中传入的参数data为后台获取的数据
for(i in data) //data指的是数组,i为数组的索引
{
var tr;
tr=''+data[i].id+''+''+data[i].title +''
$("#tabletest").append(''+tr+'')
}
}
});
}
.center{
margin: auto;
text-align:center;
font-size: 24px;
width: 60%;
background: lightblue;
}
<p id="test">Springboot整合MyBatis通过ajax查询MySQL数据库数据</b>
显示所有数据
查询
</p>
四、程序运行、测试与分析4.1程序运行
4.2 总结分析在使用java程序时,要注意jdk版本和jdk对应的数据库版本。使用数据库操作时,要注意数据库与idea的连接应用中url、用户名、密码的格式。注意传入数据文件路径的相对绝对路径。学会调试,逐步了解一个项目的流程,排除错误。在调试程序时,要深思熟虑,寻找解决办法,一一排除出错的原因。了解各种注解 API 的作用可以帮助您优化代码。对于种类繁多的技术,需要根据需求选择合适的、高效的、可扩展的技术。通过节目,我们对前后端的工作方式有了更深入的了解,对springboot的工作原理有了更深入的了解。4.3改进4.3.1对于爬虫:
4.3.2.前端太丑太简单