需求分析

首先访问京东,搜索手机,分析页面,我们抓取以下商品数据:

商品图片、价格、标题、商品详情页

SPU和SKU

除了以上四个属性以外,我们发现上图中的苹果手机有四种产品,我们应该每一种都要抓取。那么这里就必须要了解spu和sku的概念。

SPU = Standard Product Unit (标准产品单位)

SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。通俗点讲,属性值、特性相同的商品就可以称为一个SPU。

例如上图中的苹果手机就是SPU,包括红色、深灰色、金色、银色

SKU=stock keeping unit(库存量单位)

SKU即库存进出计量的单位, 可以是以件、盒、托盘等为单位。SKU是物理上不可分割的最小存货单元。在使用时要根据不同业态,不同管理模式来处理。在服装、鞋类商品中使用最多最普遍。

例如上图中的苹果手机有几个款式,红色苹果手机,就是一个sku

查看页面的源码也可以看出区别

开发准备

数据库表分析

根据需求分析,我们创建的表如下:

CREATE TABLE `jd_item` (

`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',

`spu` bigint(15) DEFAULT NULL COMMENT '商品集合id',

`sku` bigint(15) DEFAULT NULL COMMENT '商品最小品类单元id',

`title` varchar(100) DEFAULT NULL COMMENT '商品标题',

`price` bigint(10) DEFAULT NULL COMMENT '商品价格',

`pic` varchar(200) DEFAULT NULL COMMENT '商品图片',

`url` varchar(200) DEFAULT NULL COMMENT '商品详情地址',

`created` datetime DEFAULT NULL COMMENT '创建时间',

`updated` datetime DEFAULT NULL COMMENT '更新时间',

PRIMARY KEY (`id`),

KEY `sku` (`sku`) USING BTREE

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='京东商品表';

添加依赖

使用Spring Boot+Spring Data JPA和定时任务进行开发,

需要创建Maven工程并添加以下依赖

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.0.2.RELEASE

cn.itcast.crawler

itcast-crawler-jd

1.0-SNAPSHOT

org.springframework.boot

spring-boot-starter-web

org.springframework.boot

spring-boot-starter-data-jpa

mysql

mysql-connector-java

org.apache.httpcomponents

httpclient

org.jsoup

jsoup

1.10.3

org.apache.commons

commons-lang3

添加配置文件

加入application.properties配置文件

#DB Configuration:

spring.datasource.driverClassName=com.mysql.jdbc.Driver

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/crawler

spring.datasource.username=root

spring.datasource.password=root

#JPA Configuration:

spring.jpa.database=MySQL

spring.jpa.show-sql=true

代码实现

编写pojo

根据数据库表,编写pojo

@Entity

@Table(name = "jd_item")

public class Item {

//主键

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

//标准产品单位(商品集合)

private Long spu;

//库存量单位(最小品类单元)

private Long sku;

//商品标题

private String title;

//商品价格

private Double price;

//商品图片

private String pic;

//商品详情地址

private String url;

//创建时间

private Date created;

//更新时间

private Date updated;

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

public Long getSpu() {

return spu;

}

public void setSpu(Long spu) {

this.spu = spu;

}

public Long getSku() {

return sku;

}

public void setSku(Long sku) {

this.sku = sku;

}

public String getTitle() {

return title;

}

public void setTitle(String title) {

this.title = title;

}

public Double getPrice() {

return price;

}

public void setPrice(Double price) {

this.price = price;

}

public String getPic() {

return pic;

}

public void setPic(String pic) {

this.pic = pic;

}

public String getUrl() {

return url;

}

public void setUrl(String url) {

this.url = url;

}

public Date getCreated() {

return created;

}

public void setCreated(Date created) {

this.created = created;

}

public Date getUpdated() {

return updated;

}

public void setUpdated(Date updated) {

this.updated = updated;

}

}

编写dao层

public interface ItemDao extends JpaRepository {

}

编写service服务层

ItemService接口如下:

public interface ItemService {

/**

* 保存商品

* @param item

*/

public void save(Item item);

/**

* 根据条件查询商品

* @param item

* @return

*/

public List findAll(Item item);

}

ItemServiceImpl 实现类如下:

@Service

public class ItemServiceImpl implements ItemService {

@Autowired

private ItemDao itemDao;

@Override

@Transactional

public void save(Item item) {

this.itemDao.save(item);

}

@Override

public List findAll(Item item) {

//声明查询条件

Example example = Example.of(item);

//根据查询条件进行查询数据

List list = this.itemDao.findAll(example);

return list;

}

}

编写HttpUtils

@Component

public class HttpUtils {

private PoolingHttpClientConnectionManager cm;

public HttpUtils() {

this.cm = new PoolingHttpClientConnectionManager();

//设置最大连接数

this.cm.setMaxTotal(100);

//设置每个主机的最大连接数

this.cm.setDefaultMaxPerRoute(10);

}

/**

* 根据请求地址下载页面数据

*

* @param url

* @return 页面数据

*/

public String doGetHtml(String url) {

//获取HttpClient对象

CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(this.cm).build();

//创建httpGet请求对象,设置url地址

HttpGet httpGet = new HttpGet(url);

//设置请求信息

httpGet.setConfig(this.getConfig());

CloseableHttpResponse response = null;

try {

//使用HttpClient发起请求,获取响应

response = httpClient.execute(httpGet);

//解析响应,返回结果

if (response.getStatusLine().getStatusCode() == 200) {

//判断响应体Entity是否不为空,如果不为空就可以使用EntityUtils

if (response.getEntity() != null) {

return EntityUtils.toString(response.getEntity(), "utf8");

}

}

} catch (IOException e) {

e.printStackTrace();

} finally {

//关闭response

if (response != null) {

try {

response.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

//返回空串

return "";

}

/**

* 下载图片

*

* @param url

* @return 图片名称

*/

public String doGetImage(String url) {

//获取HttpClient对象

CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(this.cm).build();

//创建httpGet请求对象,设置url地址

HttpGet httpGet = new HttpGet(url);

//设置请求信息

httpGet.setConfig(this.getConfig());

CloseableHttpResponse response = null;

try {

//使用HttpClient发起请求,获取响应

response = httpClient.execute(httpGet);

//解析响应,返回结果

if (response.getStatusLine().getStatusCode() == 200) {

//判断响应体Entity是否不为空

if (response.getEntity() != null) {

//下载图片

//获取图片的后缀

String extName = url.substring(url.lastIndexOf("."));

//创建图片名,重命名图片

String picName = UUID.randomUUID().toString() + extName;

//下载图片

//声明OutPutStream

OutputStream outputStream = new FileOutputStream(new File("C:\\Users\\86152\\Desktop\\image\\" +

picName));

response.getEntity().writeTo(outputStream);

//返回图片名称

return picName;

}

}

} catch (IOException e) {

e.printStackTrace();

} finally {

//关闭response

if (response != null) {

try {

response.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

//如果下载失败,返回空串

return "";

}

//设置请求信息

private RequestConfig getConfig() {

RequestConfig config = RequestConfig.custom()

.setConnectTimeout(1000) //创建连接的最长时间

.setConnectionRequestTimeout(500) // 获取连接的最长时间

.setSocketTimeout(10000) //数据传输的最长时间

.build();

return config;

}

}

编写ItemTask

@Component

public class ItemTask {

@Autowired

private HttpUtils httpUtils;

@Autowired

private ItemService itemService;

private static final ObjectMapper MAPPER = new ObjectMapper();

//当下载任务完成后,间隔多长时间进行下一次的任务。

@Scheduled(fixedDelay = 100 * 1000)

public void itemTask() throws Exception {

//声明需要解析的初始地址

String url = "https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq" +

"=%E6%89%8B%E6%9C%BA&cid2=653&cid3=655&s=113&click=0&page=";

//按照页面对手机的搜索结果进行遍历解析

for (int i = 1; i < 10; i = i + 2) {

String html = httpUtils.doGetHtml(url + i);

//解析页面,获取商品数据并存储

this.parse(html);

}

System.out.println("数据抓取完成!");

}

//解析页面,获取商品数据并存储

private void parse(String html) throws Exception {

//解析html获取Document

Document doc = Jsoup.parse(html);

//获取spu信息

Elements spuEles = doc.select("div#J_goodsList > ul > li");

for (Element spuEle : spuEles) {

//获取spu

long spu;

if("".equals(spuEle.attr("data-spu"))){

spu = 0L;

}else{

spu = Long.parseLong(spuEle.attr("data-spu"));

}

//获取sku信息

Elements skuEles = spuEle.select("li.gl-item");

for (Element skuEle : skuEles) {

//获取sku

long sku = Long.parseLong(skuEle.select("[data-sku]").attr("data-sku"));

//根据sku查询商品数据

Item item = new Item();

item.setSku(sku);

List list = this.itemService.findAll(item);

if(list.size()>0) {

//如果商品存在,就进行下一个循环,该商品不保存,因为已存在

continue;

}

//设置商品的spu

item.setSpu(spu);

//获取商品的详情的url

String itemUrl = "https://item.jd.com/" + sku + ".html";

item.setUrl(itemUrl);

//获取商品的图片

String picUrl ="https:"+ skuEle.select("img[data-img]").first().attr("src");

String picName = this.httpUtils.doGetImage(picUrl);

item.setPic(picName);

//获取商品的价格

String priceJson = skuEle.select(".p-price > strong > i").first().text();

double price = Double.parseDouble(priceJson);

item.setPrice(price);

//获取商品的标题

String title = skuEle.select(".p-name > a > em").first().text();

item.setTitle(title);

item.setCreated(new Date());

item.setUpdated(item.getCreated());

//保存商品数据到数据库中

this.itemService.save(item);

}

}

}

}

编写启动类

@SpringBootApplication

//使用定时任务,需要先开启定时任务,需要添加注解

@EnableScheduling

public class Application {

public static void main(String[] args) {

SpringApplication.run(Application.class, args);

}

}

结果如下:

java 爬虫 获取京东_Java爬虫爬取京东相关推荐

  1. python爬虫可以爬取哪些有用的东西_Python爬虫系列(十三) 用selenium爬取京东商品...

    这篇文章,我们将通过 selenium 模拟用户使用浏览器的行为,爬取京东商品信息,还是先放上最终的效果图: 1.网页分析 (1)初步分析 原本博主打算写一个能够爬取所有商品信息的爬虫,可是在分析过程 ...

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

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

  3. 【爬虫】用Selenium+PyQuery爬取京东商城

    文章目录 前言 1. 项目预览 2. 库的引入 3. 爬取流程 4. 驱动浏览器搜索关键字 4. 1页面分析 4.2 驱动浏览器代码 5. 解析页面 5.1 页面分析 5.2 页面解析代码 6. 保存 ...

  4. python京东商品_Python爬取京东的商品分类与链接

    前言 本文主要的知识点是使用Python的BeautifulSoup进行多层的遍历. 如图所示.只是一个简单的哈,不是爬取里面的隐藏的东西. 示例代码 from bs4 import Beautifu ...

  5. 爬虫实战:Requests+BeautifulSoup 爬取京东内衣信息并导入表格(python)

    准备工作 假如我们想把京东内衣类商品的信息全部保存到本地,通过手工复制粘贴将是一项非常庞大的工程,此时,可以用python爬虫实现. 第一步:分析网页地址 起始网页地址 起始网页地址 https:// ...

  6. 爬虫实战:使用Selenium爬取京东宝贝信息

    有些页面数据是采用Ajax获取的,但是这些Ajax接口参数比较复杂,可能会加入加密秘钥.对于这种页面,最方便的方法是通过selenium.可以用Selenium来模拟浏览器操作,抓取京东商品信息. 网 ...

  7. php 爬京东商品详情,爬取京东商品信息的实例 —— Golang

    安装 1.安装 jd-spider $ go get github.com/matchseller/jd-spider 2.在你的项目中导入包: import ( "github.com/m ...

  8. go爬虫和python爬虫哪个好_python 爬虫实战项目--爬取京东商品信息(价格、优惠、排名、好评率等)-Go语言中文社区...

    利用splash爬取京东商品信息 一.环境 window7 python3.5 pycharm scrapy scrapy-splash MySQL 二.简介 为了体验scrapy-splash 的动 ...

  9. 爬虫练习一,爬取京东图片

    爬虫入门小项目,爬取京东的图片.还不会处理动态加载,只是简单的爬取图片和名称. #-*- coding: utf-8 -*- from urllib import request from urlli ...

  10. 爬虫实战(二) 用Python爬取网易云歌单

    最近,博主喜欢上了听歌,但是又苦于找不到好音乐,于是就打算到网易云的歌单中逛逛 本着 "用技术改变生活" 的想法,于是便想着写一个爬虫爬取网易云的歌单,并按播放量自动进行排序 这篇 ...

最新文章

  1. python好找工作吗2017-记2017年年底,几次Python后端面试
  2. 【采用】风控体系的一般架构
  3. Git clone之后你的硬盘上究竟发生了什么?
  4. selenium fluentwait java实例
  5. 学习Vim 全图解释
  6. docker之基础命令相关操作上
  7. Linux下编译安装LAMP并分离为多台服务器
  8. iOS autoreleasePool 深入理解
  9. 使用QUARKUS开发JSON REST 服务
  10. 中国大陆身份证正则表达式(严格验证省份和日期)
  11. Ubuntu搭建FTP服务器
  12. python爬取北京政务公开惠民地图信息
  13. 量表:现代医学体系的“工具箱”
  14. nandflash oob解析
  15. vscode+CRA+TypeScript+eslint+prettier+stylelint+husky+lint-staged完整版配置
  16. 【转载】太厉害了,终于有人能把TCP/IP 协议讲的明明白白了
  17. Android 启动“无启动图标的 apk“
  18. 高通MDM9628芯片数据参考
  19. vim快捷键(一)查找与替换
  20. 雅百特拟对外投资加码光伏主业

热门文章

  1. Brocade 300 FC交换机收集诊断日志
  2. CF - E95(div2) -- B. Negative Prefixes【贪心】
  3. 【数据挖掘面经】腾讯+百度+华为(均拿到sp offer)--转
  4. 托管与非托管数据转换方法之C#设计笔记(十三)
  5. MySQL数据库开发
  6. AUGUSTUS安装 基因训练、预测软件
  7. 使用MAKER进行基因注释(高级篇之AUGUSTUS模型训练)
  8. fluent meshing导入二维网格
  9. ASEMI整流二极管1N4007参数,1N4007规格,1N4007厂家
  10. 虚拟机无法远程连接阿里云服务器的解决办法