龙空技术网

使用HttpClient+Jsoup实现网络爬虫抓取京东商品数据信息

Java机械师 331

前言:

眼前各位老铁们对“java抓取数据”都比较讲究,我们都想要知道一些“java抓取数据”的相关知识。那么小编同时在网摘上搜集了一些对于“java抓取数据””的相关资讯,希望朋友们能喜欢,看官们快快来学习一下吧!

添加依赖

        <!--SpringMVC-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <!--SpringData Jpa-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-jpa</artifactId>        </dependency>        <!--MySQL连接包-->        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>5.1.49</version>        </dependency>        <!-- HttpClient -->        <dependency>            <groupId>org.apache.httpcomponents</groupId>            <artifactId>httpclient</artifactId>        </dependency>        <!--Jsoup-->        <dependency>            <groupId>org.jsoup</groupId>            <artifactId>jsoup</artifactId>             <version>1.15.2</version>        </dependency>         <!--lombok-->        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>复制代码
配置application.properties
# MySQL配置spring.datasource.driverClassName=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8spring.datasource.username=rootspring.datasource.password=123456# JPA配置spring.jpa.database=MySQLspring.jpa.show-sql=truespring.jpa.generate-ddl=truespring.jpa.hibernate.ddl-auto=updatespring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy复制代码
POJO
@Entity@Table(name = "item")@Datapublic 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 String shop;    //创建时间    private Date created;    //更新时间    private Date updated;}复制代码
Dao
public interface ItemDao extends JpaRepository<Item,Long> {}复制代码
Service
public interface ItemService {    /**     * 保存商品     *     * @param item     */    void save(Item item);    /**     * 删除所有商品     */    void deleteAll();}@Servicepublic class ItemServiceImpl implements ItemService {    @Autowired    private ItemDao itemDao;    @Override    @Transactional    public void save(Item item) {        this.itemDao.save(item);    }    @Override    public void deleteAll() {        this.itemDao.deleteAll();    }}复制代码
封装HttpClient
@Componentpublic class HttpUtils {    private static final String FILEPATH = "D:\\demo\\";    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.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");        //设置请求信息        httpGet.setConfig(this.getConfig());        CloseableHttpResponse response = null;        try {            //使用HttpClient发起请求,获取响应            response = httpClient.execute(httpGet);            //解析响应,返回结果            if (response.getStatusLine().getStatusCode() == 200) {                //判断响应体Entity是否不为空,如果不为空就可以使用EntityUtils                if (response.getEntity() != null) {                    String content = EntityUtils.toString(response.getEntity(), "utf8");                    return content;                }            }        } 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() + extName;                    //声明OutPutStream                    OutputStream outputStream = new FileOutputStream(new File(FILEPATH + 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 "";    }    /**     * 设置请求信息     *     * @return     */    private RequestConfig getConfig() {        RequestConfig config = RequestConfig.custom()                //创建连接的最长时间                .setConnectTimeout(1000)                // 获取连接的最长时间                .setConnectionRequestTimeout(500)                //数据传输的最长时间                .setSocketTimeout(10000)                .build();        return config;    }}复制代码
SPU与SKU

SPU

SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。

属性值、特性相同的商品就可以称为一个SPU。

如:某型号某配置某颜色的笔记本电脑就对应一个SPU,它有多种配置,或者多种颜色

SKU

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

如:某型号的笔记本电脑有多种配置,8G+512G笔记本电脑就是一个SKU。

爬取分析

爬取笔记本电脑搜索页面。进行分页操作,得到分页请求地址:

所有商品由一个class=J_goodsList的div包裹。div中则是由ul标签包裹的li标签,每一个li标签对应一个商品信息。

li标签包含的需要的商品信息

爬取逻辑

@Componentpublic class ItemTask {    @Autowired    private HttpUtils httpUtils;    @Autowired    private ItemService itemService;    /**     * 使用定时任务抓取最新数据     *     * @throws Exception     */    @Scheduled(fixedDelay = 50 * 1000)    public void itemTask() throws Exception {    	// 每次执行前请客数据        itemService.deleteAll();                //声明需要解析的初始地址        String url = ";;        // 按照页面对搜索结果进行遍历解析,注意页面是奇数        for (int i = 1; i < 10; i = i + 2) {            String html = httpUtils.doGetHtml(url + i);            // 解析页面,获取商品数据并存储            this.parse(html);        }        System.out.println("商品数据抓取完成!");    }    /**     * 解析页面,获取商品数据并存储     *     * @param html     * @throws Exception     */    private void parse(String html) {        // 解析html获取Document        Document doc = Jsoup.parse(html);        // 获取spu信息        Elements spuEles = doc.select("div#J_goodsList > ul > li");        // 循环列表中的SPU信息        for (int i = 0; i < spuEles.size(); i++) {            Element element = spuEles.get(i);            //获取spu            String strSpu = element.attr("data-spu");            if (strSpu == null || strSpu.equals("")) {                continue;            }            long spu = Long.parseLong(strSpu);            //获取sku            long sku = Long.parseLong(element.attr("data-sku"));            Item item = new Item();            //设置商品的spu            item.setSpu(spu);            //设置商品的sku            item.setSku(sku);            //获取商品的详情的url            String itemUrl = "; + sku + ".html";            item.setUrl(itemUrl);            // 获取商品的图片            String picUrl = "https:" + element.select("div.p-img").select("a").select("img").attr("data-lazy-img");            String picName = this.httpUtils.doGetImage(picUrl);            item.setPic(picName);            //获取商品的价格            String strPrice = element.select("div.p-price").select("i").text();            item.setPrice(Double.parseDouble(strPrice));            //获取商品的标题            String title = element.select("div.p-name").select("a").attr("title");            item.setTitle(title);            // 店铺名称            String shopName = element.select("div.p-shop a").text();            item.setShop(shopName);            item.setCreated(new Date());            item.setUpdated(item.getCreated());            //保存商品数据到数据库中            this.itemService.save(item);        }    }}复制代码
配置启动类
@SpringBootApplication// 开启定时任务@EnableSchedulingpublic class Application {    public static void main(String[] args) {        SpringApplication.run(Application.class, args);    }}复制代码
执行测试

启动项目,执行测试。查看数据库与本地下载照片。

标签: #java抓取数据