Springboot+JPA下實現簡易爬蟲--爬取豆瓣電視劇數據


Springboot+JPA下實現簡易爬蟲--爬取豆瓣電視劇數據


  前言:今天聽到產品那邊討論一些需求,好像其中一點是用戶要求我們爬蟲,在網頁上抓取一些數據然后存到我們公司數據庫中,眾所周知,爬蟲的實現對於python語言可是專家,而對於我們使用的Java語言,我也不確定可不可以,趁着無事,上網參考了下資料,自己也寫了些demo,所幸爬取數據成功了,由於我使用的基礎demo項目是自己搭建的springboot+jpa的項目,因此也會在這個基礎上進行爬蟲的實現,文章會貼出具體的步驟以及重要的代碼,至於項目的搭建就不介紹了,我的完整代碼會同步至gitHub,大家可以參考使用,當然也可以使用自己的springboot項目。

gitHub地址:https://github.com/Slience-zae/mail-demo.git

1.材料准備

1.1首先打開豆瓣的網頁,同時F12打開控制台

 

 1.2 在控制台中找到接口url,請求頭信息,以及相應數據格式和字段

 

 

 

 

 

 在網頁上准備的材料這些就可以了,接下來,該動手撰寫代碼了。

2.代碼實現步驟

2.1 數據庫創建表格

CREATE TABLE `subjects` ( `id` varchar(255) NOT NULL COMMENT 'id', `title` varchar(255) DEFAULT NULL COMMENT '標題', `rate` decimal(10,2) DEFAULT NULL COMMENT '豆瓣評分', `url` varchar(255) DEFAULT NULL COMMENT '觀影地址', `playable` tinyint(4) DEFAULT NULL COMMENT '是否可以觀看:0是 1否', `cover` varchar(255) DEFAULT NULL COMMENT '封面圖片地址', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

通過相應數據可以得知共有九個字段,但是我們主要保存的是數據主要信息,其中cover_x,cover_y,is_new對於我們來說沒有什么意義,可以不保存到數據庫,因此略過。

2.2 hibernate逆向生成實體

選中右鍵點擊,選擇Generate persistence Mapping,再選擇By Database Schema,選中數據庫的表,再選擇生成實體的包位置,最后點擊ok就能生成到指定位置了,生成后我們再加以修改一下實體,大體是這個樣子。

import lombok.Data; import javax.persistence.*; import java.math.BigDecimal; @Data @Entity @Table(name = "subjects") public class Subjects { @Id private String id;//id
    private String title;//標題
    private BigDecimal rate;//豆瓣評分
    private String url;//觀影地址
    private Boolean playable;//是否能夠觀看
    private String cover;//封面圖片URL
 @Transient private Integer cover_x; @Transient private Integer cover_y; @Transient private Boolean is_new; }

在此說明一下,之所以將cover_x,cover_y,is_new三個字段也添加進實體了,是為了防止接下來json數組轉化List<Subjects>時發生異常,我已經在這三個字段上加了@Transient注解,因此三個字段不會映射數據庫。

2.3 編寫向指定網址抓取json數據的工具類

import org.springframework.boot.configurationprocessor.json.JSONObject; import org.springframework.stereotype.Component; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; @Component public class GetJson { public JSONObject getHttpJson(String url){ try { URL realUrl = new URL(url); HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection(); //設置HTTP的請求頭(參考材料准備截圖的請求頭信息)
            connection.setRequestProperty("Accept", "*/*");//設置瀏覽器可以接收的媒體類型
            connection.setRequestProperty("Connection", "keep-alive");//網頁打開,建立連接
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3928.4 Safari/537.36");//客戶端使用的操作系統和瀏覽器的名稱和版本 // 建立實際的連接
 connection.connect(); //請求成功
            if (connection.getResponseCode() == 200) { InputStream is = connection.getInputStream(); //創建字節數組輸出流對象
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); //10MB的緩存
                byte[] buffer = new byte[10485760]; int len = 0; while ((len = is.read(buffer))!= -1) { byteArrayOutputStream.write(buffer, 0, len); } String jsonString = byteArrayOutputStream.toString(); byteArrayOutputStream.close(); is.close(); //轉換成json數據返回
                return new JSONObject(jsonString); } } catch (Exception e) { e.printStackTrace(); } return null; } }

注意一點,設置連接對象的請求頭信息的時候,要將我們在豆瓣上拿到的那幾個參數設置成一樣的,防止抓取數據失敗,具體那幾個參數是什么,已經在代碼注釋上加以說明了。

2.4 完整業務代碼糅合實現

(1).在application.properties配置文件中加入以下代碼

#豆瓣網址
douban_url= https://movie.douban.com/j/search_subjects

(2) dao層加入類

import com.maven.maildemo.entity.Subjects; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.CrudRepository; public interface SubjectsDao extends CrudRepository<Subjects, String>, JpaSpecificationExecutor<Subjects> { }

(3) service,serviceImpl,controller層代碼

import com.maven.maildemo.entity.Subjects; import java.util.List; public interface SubjectsService { /** * 在豆瓣網頁上抓取電視劇信息保存並返回 * @author zae * @param pageNumber 頁碼 */ List<Subjects> getAndSaveSubjectsList(Integer pageNumber) throws Exception; }

 

import com.alibaba.fastjson.JSON; import com.maven.maildemo.dao.SubjectsDao; import com.maven.maildemo.entity.Subjects; import com.maven.maildemo.service.SubjectsService; import com.maven.maildemo.utils.GetJson; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.configurationprocessor.json.JSONArray; import org.springframework.boot.configurationprocessor.json.JSONObject; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @Slf4j @Service @Transactional public class SubjectsServiceImpl implements SubjectsService { @Value("${douban_url}") private String doubanUrl; @Autowired private GetJson getJson; private final String DOUBAN_PARM = "?type=tv&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start="; @Autowired private SubjectsDao subjectsDao; @Override public List<Subjects> getAndSaveSubjectsList(Integer pageNumber) throws Exception { if(pageNumber>=0 && pageNumber <= 10000){ String address = doubanUrl+DOUBAN_PARM+pageNumber; //獲取json對象數據
            JSONObject httpJson = getJson.getHttpJson(address); if(httpJson != null){ //取出json數據數組
                JSONArray subjectsArray = httpJson.getJSONArray("subjects"); if(subjectsArray!=null){ //將json數組轉化為List
                        List<Subjects> subjectsList = JSON.parseArray(subjectsArray.toString(),Subjects.class); for(Subjects subjects:subjectsList){ //爬出數據后,保存在數據庫中
 subjectsDao.save(subjects); } return subjectsList; }else{ return new ArrayList<>(); } }else{ return new ArrayList<>(); } } return new ArrayList<>(); } }

 

import com.alibaba.fastjson.JSON; import com.maven.maildemo.entity.Subjects; import com.maven.maildemo.service.SubjectsService; import io.swagger.annotations.Api; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @RequestMapping("subjects") @Api(description = "豆瓣") public class SubjectsController { @Autowired private SubjectsService subjectsService; /** * 在豆瓣網頁上抓取電視劇信息保存並返回 * @param pageNumber 頁碼 * @author zae * @return
     */ @GetMapping(value = "/getAndSaveSubjectsList") String getAndSaveSubjectsList(@RequestParam Integer pageNumber){ try { List<Subjects> subjectsList = subjectsService.getAndSaveSubjectsList(pageNumber); return subjectsList==null?null: JSON.toJSONString(subjectsList); } catch (Exception e) { return "爬取數據信息發生異常"+e.getMessage(); } } }

業務代碼沒啥復雜的,基本上都加注釋了,看一下就好了。

3.測試

啟動項目,打開swaager,找到剛剛寫的接口,輸入參數點擊進行測試。

 

 此時不出意外應該是執行成功了,打開數據庫,看一下庫里有沒有我們爬下來的數據。

 

 發現庫里有值,說明我們已經成功的將數據爬下來了。不僅僅豆瓣如此,其他網頁數據也是類似的實現。

本人java爬蟲學習借鑒博客:https://blog.csdn.net/qwe86314/article/details/91450098  博主是使用的mybatis結合實現,而我的是結合springboot+jpa的項目使用的。

如有問題,多多評論指教,文章編寫不易,期待您的推薦和贊,

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM