日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java爬虫实践

發布時間:2023/12/14 java 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java爬虫实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java_spider_實戰

源碼及資料點這里!!!

爬蟲的執行流程: 1) 確定首頁url 2) 發送請求, 獲取數據 3) 解析數據 4) 保存數據
爬蟲的三大核心模塊:
1發送請求獲取數據 : httpClient
* 1)獲取httpClient對象:
* 2) 創建請求方式的對象
* 3) 設置請求參數, 請求頭
* 4) 發送請求, 獲取響應對象
* 5) 獲取數據:
* 6) 釋放資源
2解析數據 : Jsoup
* 常見方法 :
* static parse(String html) ; 根據html字符串轉換成document對象
* select(“選擇器”) ; 根據選擇器獲取對應的元素
* text()/html() ; 獲取指定元素的內容體中數據
* attr(String name) ; 根據屬性的名稱獲取屬性的值
3保存數據 :

0. 梳理整個爬蟲的流程

0.1 163娛樂爬蟲的流程

0.2 騰訊娛樂爬蟲的流程

1.1 準備工作 :

  • 1)創建項目 : gossip-spider-news (maven jar工程)

[外鏈圖片轉存失敗(img-zvL8ETKt-1563093902027)(assets/1557621834394.png)]

  • 2)添加pom依賴:
<dependencies><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.4</version></dependency><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.10.3</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>4.2.4.RELEASE</version></dependency><dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version>0.9.1.2</version></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.1</version></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.9.0</version></dependency></dependencies>
  • 3)加入工具類:

[外鏈圖片轉存失敗(img-wkct0RYO-1563093902031)(assets/1557623438827.png)]

1.2 確定首頁url

[外鏈圖片轉存失敗(img-5PjuFk4c-1563093902031)(assets/1557624105019.png)]

結論: 新聞數據, 不是通過同步請求, 獲取到, 而是通過異步請求, 悄悄獲取的

如何獲取異步請求的url :

首頁的url : https://ent.163.com/special/000380VU/newsdata_index.js?callback=data_callback 分頁的url : https://ent.163.com/special/000380VU/newsdata_index_02.js?callback=data_callback

1.3 發送請求, 獲取數據

public class News163Spider {public static void main(String[] args ) throws Exception{//1. 確定首頁url:String indexUrl = "https://ent.163.com/special/000380VU/newsdata_index.js?callback=data_callback";//2. 發送請求, 獲取數據// 此處獲取的json的數據, 并不是一個非標準的jsonString jsonStr = HttpClientUtils.doGet(indexUrl);jsonStr = splitJson(jsonStr);System.out.println(jsonStr);//3. 解析數據(json) :/*** 1) json格式一共有幾種: 二種 一般復合格式認為是前二種的擴展格式* 一種: [value1,value2,value3 ....] ---數組格式* 二種: {key1:value1,key2:value2}* 三種: {key1:[value1,value2]}* 四種: [{},{}]** 2) 如何區分一個json的格式是一個對象呢, 還是一個數組呢?* 查看最外層的符號即可, 如果是[] 那就是數組, 如果{}那就是對象* [{key,[{key,value}]}] : 轉回對應的類型* List<Map<String,List<Map<String,String>>>>** 3) json格式本質上就是一個字符串: 在js 和 java中表示的類型有所不同的:* js java* [] 數組 數組/List/set* {} 對象 javaBean對象/Map** js中如何定義一個對象: var persion = {username:'張三'}; persion.username*/}// 將非標準的json轉換為標準的json字符串private static String splitJson(String jsonStr) {int firstIndex = jsonStr.indexOf("(");int lastIndex = jsonStr.lastIndexOf(")");return jsonStr.substring(firstIndex+1,lastIndex);} }

1.4 解析數據(json)

  • 解析新聞的列表頁:
// 解析json的方法private static void parseJson(String jsonStr) {//3.1 將json字符串轉換成 指定的對象Gson gson = new Gson();List<Map<String, Object>> newsList = gson.fromJson(jsonStr, List.class);// 3.2 遍歷整個新聞的結合, 獲取每一個新聞的對象for (Map<String, Object> newsObj : newsList) {// 新聞 : 標題, 時間,來源 , 內容 , 新聞編輯 , 新聞的url//3.2.1 獲取新聞的url , 需要根據url, 獲取詳情頁中新聞數據String docUrl = (String) newsObj.get("docurl");// 過濾掉一些不是新聞數據的urlif(docUrl.contains("photoview")){continue;}if(docUrl.contains("v.163.com")){continue;}//System.out.println(docUrl);//3.2.2 獲取新聞詳情頁的數據parseNewsItem(docUrl);}}
  • 創建news類(pojo):
// 新聞對象 public class News {private String id;private String title;private String time;private String source;private String content;private String editor;private String docurl;// 省略 get... set... 方法 }
  • 解析新聞的詳情頁的內容:
// 根據url 解析新聞詳情頁:private static News parseNewsItem(String docUrl) throws Exception {// 3.3.1 發送請求, 獲取新聞詳情頁數據String html = HttpClientUtils.doGet(docUrl);//3.3.2 解析新聞詳情頁:Document document = Jsoup.parse(html);//3.3.2.1 : 解析新聞的標題:News news = new News();Elements h1El = document.select("#epContentLeft h1");String title = h1El.text();news.setTitle(title);//3.3.2.2 : 解析新聞的時間:Elements timeAndSourceEl = document.select(".post_time_source");String timeAndSource = timeAndSourceEl.text();String[] split = timeAndSource.split(" 來源: ");// 請各位一定一定一定要復制, 否則會切割失敗news.setTime(split[0]);//3.3.2.3 : 解析新聞的來源:news.setSource(split[1]);//3.3.2.4 : 解析新聞的正文:Elements ps = document.select("#endText p");String content = ps.text();news.setContent(content);//3.3.2.5 : 解析新聞的編輯:Elements spanEl = document.select(".ep-editor");// 責任編輯:陳少杰_b6952String editor = spanEl.text();// 一定要接收返回值, 否則白寫了editor = editor.substring(editor.indexOf(":")+1,editor.lastIndexOf("_"));news.setEditor(editor);//3.3.2.6 : 解析新聞的url:news.setDocurl(docUrl);//3.3.2.7: idlong id = idWorker.nextId();news.setId(id+"");return news;}

1.5 保存數據

  • 準備工作: 創建對應的庫 和 對應的表
create databases gossip; use gossip; SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS `news`; CREATE TABLE `news` (`id` varchar(20) NOT NULL,`title` varchar(50) DEFAULT NULL,`time` varchar(50) DEFAULT NULL,`source` varchar(50) DEFAULT NULL,`content` TEXT,`editor` varchar(50) DEFAULT NULL,`docurl` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  • 1)創建一個NewsDao類:
package com.itheima.spider.dao;import com.itheima.spider.pojo.News; import com.mchange.v2.c3p0.ComboPooledDataSource; import org.springframework.jdbc.core.JdbcTemplate;import java.beans.PropertyVetoException;public class NewsDao extends JdbcTemplate {public NewsDao() {ComboPooledDataSource dataSource = new ComboPooledDataSource();try {dataSource.setDriverClass("com.mysql.jdbc.Driver");dataSource.setJdbcUrl("jdbc:mysql:///gossip"); // 需要更改為自己的數據庫名稱dataSource.setUser("root");dataSource.setPassword("root"); // 需要更改為自己的mysql的密碼} catch (PropertyVetoException e) {e.printStackTrace();}super.setDataSource(dataSource);}// 保存數據的方法public void saveNews(News news) {String[] params = {news.getId(), news.getTitle(), news.getTime(), news.getSource(), news.getContent(), news.getEditor(), news.getDocurl()};update("INSERT INTO news VALUES (?,?,?,?,?,?,?)", params);} }
  • 2)在news163Spider類中, 執行保存即可

    • 在成員位置創建dao對象

    [外鏈圖片轉存失敗(img-i3Eqox0a-1563093902031)(assets/1557633998099.png)]

    • 在parseJson方法中添加一下內容

    [外鏈圖片轉存失敗(img-Y7Cn3KOr-1563093902031)(assets/1557634046293.png)]

如果將創建dao的代碼放置到了方法中, 后續可能會出現這個異常信息:

[外鏈圖片轉存失敗(img-iH44cMAk-1563093902034)(assets/1557633247460.png)]

錯誤異常原因: 太多的連接,超過mysql的最大連接數了由于創建了太多的連接池了, 每一次創建一個連接池就會初始化一些連接創建了多次Dao對象, 每創建一次dao, 執行一下dao中構造方法, 構造方法中創建連接池對象

1.6 分頁獲取數據

// 執行分頁的方法public static void page(String indexUrl) throws Exception{String page = "02";while(true) {//1. 發送請求獲取數據// 此處獲取的json的數據, 并不是一個非標準的jsonString jsonStr = HttpClientUtils.doGet(indexUrl);if(jsonStr==null){System.out.println("數據獲取完成");break;}jsonStr = splitJson(jsonStr);//2. 解析數據, 3 保存數據parseJson(jsonStr);//4. 獲取下一頁的urlindexUrl = "https://ent.163.com/special/000380VU/newsdata_index_" + page + ".js?callback=data_callback";//5. page ++int pageNum = Integer.parseInt(page);pageNum++;if(pageNum <10){page = "0"+pageNum;}else{page = pageNum+"";}}}

1.7 去重操作

[外鏈圖片轉存失敗(img-VBK124xP-1563093902034)(assets/1557634429779.png)]

[外鏈圖片轉存失敗(img-rS2aGC8J-1563093902035)(assets/1557635122858.png)]

清空數據的時候, 一定要注意: 除了清空mysql中數據外, 還的清空redis中的數據

[外鏈圖片轉存失敗(img-4JZLuLjH-1563093902035)(assets/1557635191819.png)]

1.8 獲取整個網易新聞中所有的娛樂信息

明星欄目首頁url: https://ent.163.com/special/000380VU/newsdata_star.js?callback=data_callback 明星欄目分頁url: https://ent.163.com/special/000380VU/newsdata_star_02.js?callback=data_callback電影欄目首頁url: https://ent.163.com/special/000380VU/newsdata_movie.js?callback=data_callback 電影欄目分頁url : https://ent.163.com/special/000380VU/newsdata_movie_02.js?callback=data_callback電視劇欄目首頁url: https://ent.163.com/special/000380VU/newsdata_tv.js?callback=data_callback 電視劇欄目分頁url: https://ent.163.com/special/000380VU/newsdata_tv_02.js?callback=data_callback綜藝欄目首頁url: https://ent.163.com/special/000380VU/newsdata_show.js?callback=data_callback 綜藝欄目分頁url: https://ent.163.com/special/000380VU/newsdata_show_02.js?callback=data_callback音樂欄目首頁url: https://ent.163.com/special/000380VU/newsdata_music.js?callback=data_callback 音樂欄目分頁url: https://ent.163.com/special/000380VU/newsdata_music_02.js?callback=data_callback
  • 1)在main方法中, 將所有的首頁的url放置到集合中

[外鏈圖片轉存失敗(img-wZqPj6he-1563093902036)(assets/1557644149947.png)]

  • 2)在分頁的方法中, 執行分頁的時候, 也需要根據不同的地址進行分頁

[外鏈圖片轉存失敗(img-yuHIfNSS-1563093902036)(assets/1557644179735.png)]

1.9 將整體的爬蟲:

package com.itheima.spider.news163Spider;import com.google.gson.Gson; import com.itheima.spider.dao.NewsDao; import com.itheima.spider.pojo.News; import com.itheima.spider.utils.HttpClientUtils; import com.itheima.spider.utils.IdWorker; import com.itheima.spider.utils.JedisUtils; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.select.Elements; import redis.clients.jedis.Jedis;import java.util.ArrayList; import java.util.List; import java.util.Map;public class News163Spider {private static IdWorker idWorker = new IdWorker(0,1);private static NewsDao newsDao = new NewsDao();public static void main(String[] args) throws Exception {//2. 發送請求, 獲取數據// 此處獲取的json的數據, 并不是一個非標準的json//String jsonStr = HttpClientUtils.doGet(indexUrl);//jsonStr = splitJson(jsonStr);// System.out.println(jsonStr);//3. 解析數據(json) :/*** 1) json格式一共有幾種: 二種 一般見復合格式認為是前二種的擴展格式* 一種: [value1,value2,value3 ....] ---數組格式* 二種: {key1:value1,key2:value2}* 三種: {key1:[value1,value2]}* 四種: [{},{}]** 2) 如何區分一個json的格式是一個對象呢, 還是一個數組呢?* 查看最外層的符號即可, 如果是[] 那就是數組, 如果{}那就是對象* [{key,[{key,value}]}] : 轉回對應的類型* List<Map<String,List<Map<String,String>>>>** 3) json格式本質上就是一個字符串: 在js 和 java中表示的類型有所不同的:* js java* [] 數組 數組/List/set* {} 對象 javaBean對象/Map** js中如何定義一個對象: var persion = {username:'張三'}; persion.username*///parseJson(jsonStr);//1. 確定首頁url://String indexUrl = "https://ent.163.com/special/000380VU/newsdata_index.js?callback=data_callback";List<String> urlList = new ArrayList<String>();urlList.add("https://ent.163.com/special/000380VU/newsdata_index.js?callback=data_callback");urlList.add("https://ent.163.com/special/000380VU/newsdata_star.js?callback=data_callback");urlList.add("https://ent.163.com/special/000380VU/newsdata_movie.js?callback=data_callback");urlList.add("https://ent.163.com/special/000380VU/newsdata_tv.js?callback=data_callback");urlList.add("https://ent.163.com/special/000380VU/newsdata_show.js?callback=data_callback");urlList.add("https://ent.163.com/special/000380VU/newsdata_music.js?callback=data_callback");//5. 分頁獲取數據while(!urlList.isEmpty()) {String indexUrl = urlList.remove(0);System.out.println("獲取了下一個欄目的數據#######################################");page(indexUrl);}}// 執行分頁的方法public static void page(String indexUrl) throws Exception{String page = "02";while(true) {//1. 發送請求獲取數據// 此處獲取的json的數據, 并不是一個非標準的jsonString jsonStr = HttpClientUtils.doGet(indexUrl);if(jsonStr==null){System.out.println("數據獲取完成");break;}jsonStr = splitJson(jsonStr);//2. 解析數據, 3 保存數據parseJson(jsonStr);//4. 獲取下一頁的urlif(indexUrl.contains("newsdata_index")){indexUrl = "https://ent.163.com/special/000380VU/newsdata_index_" + page + ".js?callback=data_callback";}if(indexUrl.contains("newsdata_star")){indexUrl = "https://ent.163.com/special/000380VU/newsdata_star_" + page + ".js?callback=data_callback";}if(indexUrl.contains("newsdata_movie")){indexUrl = "https://ent.163.com/special/000380VU/newsdata_movie_" + page + ".js?callback=data_callback";}if(indexUrl.contains("newsdata_tv")){indexUrl = "https://ent.163.com/special/000380VU/newsdata_tv_" + page + ".js?callback=data_callback";}if(indexUrl.contains("newsdata_show")){indexUrl = "https://ent.163.com/special/000380VU/newsdata_show_" + page + ".js?callback=data_callback";}if(indexUrl.contains("newsdata_music")){indexUrl = "https://ent.163.com/special/000380VU/newsdata_music_" + page + ".js?callback=data_callback";}//5. page ++int pageNum = Integer.parseInt(page);pageNum++;if(pageNum <10){page = "0"+pageNum;}else{page = pageNum+"";}}}// 解析json的方法private static void parseJson(String jsonStr) throws Exception{//3.1 將json字符串轉換成 指定的對象Gson gson = new Gson();List<Map<String, Object>> newsList = gson.fromJson(jsonStr, List.class);// 3.2 遍歷整個新聞的結合, 獲取每一個新聞的對象for (Map<String, Object> newsObj : newsList) {// 新聞 : 標題, 時間,來源 , 內容 , 新聞編輯 , 新聞的url//3.2.1 獲取新聞的url , 需要根據url, 獲取詳情頁中新聞數據String docUrl = (String) newsObj.get("docurl");// 過濾掉一些不是新聞數據的urlif(docUrl.contains("photoview")){continue;}if(docUrl.contains("v.163.com")){continue;}if(docUrl.contains("c.m.163.com")){continue;}if(docUrl.contains("dy.163.com")){continue;}// ###################去重處理代碼######################Jedis jedis = JedisUtils.getJedis();Boolean flag = jedis.sismember("bigData:spider:163spider:docurl", docUrl);jedis.close();//一定一定一定不要忘記關閉, 否則用著用著沒了, 導致程序卡死不動if(flag){// 代表存在, 表示已經爬取過了continue;}// ###################去重處理代碼######################//System.out.println(docUrl);//3.3 獲取新聞詳情頁的數據News news = parseNewsItem(docUrl);// 4. 保存數據 ---- 一會 會有問題的//System.out.println(news);newsDao.saveNews(news);// ###################去重處理代碼######################// 將保存到數據庫中的docurl添加到redis的set集合中jedis = JedisUtils.getJedis();jedis.sadd("bigData:spider:163spider:docurl",news.getDocurl());jedis.close();// ###################去重處理代碼######################}}// 根據url 解析新聞詳情頁:private static News parseNewsItem(String docUrl) throws Exception {System.out.println(docUrl);// 3.3.1 發送請求, 獲取新聞詳情頁數據String html = HttpClientUtils.doGet(docUrl);//3.3.2 解析新聞詳情頁:Document document = Jsoup.parse(html);//3.3.2.1 : 解析新聞的標題:News news = new News();Elements h1El = document.select("#epContentLeft h1");String title = h1El.text();news.setTitle(title);//3.3.2.2 : 解析新聞的時間:Elements timeAndSourceEl = document.select(".post_time_source");String timeAndSource = timeAndSourceEl.text();String[] split = timeAndSource.split(" 來源: ");// 請各位一定一定一定要復制, 否則會切割失敗news.setTime(split[0]);//3.3.2.3 : 解析新聞的來源:news.setSource(split[1]);//3.3.2.4 : 解析新聞的正文:Elements ps = document.select("#endText p");String content = ps.text();news.setContent(content);//3.3.2.5 : 解析新聞的編輯:Elements spanEl = document.select(".ep-editor");// 責任編輯:陳少杰_b6952String editor = spanEl.text();// 一定要接收返回值, 否則白寫了editor = editor.substring(editor.indexOf(":")+1,editor.lastIndexOf("_"));news.setEditor(editor);//3.3.2.6 : 解析新聞的url:news.setDocurl(docUrl);//3.3.2.7: idlong id = idWorker.nextId();news.setId(id+"");return news;}// 將非標準的json轉換為標準的json字符串private static String splitJson(String jsonStr) {int firstIndex = jsonStr.indexOf("(");int lastIndex = jsonStr.lastIndexOf(")");return jsonStr.substring(firstIndex + 1, lastIndex);} }

2. 爬取騰訊新聞娛樂數據

2.1 確定首頁url

熱點url : https://pacaio.match.qq.com/irs/rcd?cid=137&token=d0f13d594edfc180f5bf6b845456f3ea&ext=ent&num=60非熱點的首頁url : https://pacaio.match.qq.com/irs/rcd?cid=146&token=49cbb2154853ef1a74ff4e53723372ce&ext=ent&page=0非熱點的分頁url :https://pacaio.match.qq.com/irs/rcd?cid=146&token=49cbb2154853ef1a74ff4e53723372ce&ext=ent&page=0

2.2 發送請求, 獲取數據

// 騰訊娛樂新聞的爬蟲 public class TencentNewsSpider {public static void main(String[] args) throws Exception{//1. 確定首頁urlString topNewsUrl = "https://pacaio.match.qq.com/irs/rcd?cid=137&token=d0f13d594edfc180f5bf6b845456f3ea&ext=ent&num=60";String noTopNewsUrl = "https://pacaio.match.qq.com/irs/rcd?cid=146&token=49cbb2154853ef1a74ff4e53723372ce&ext=ent&page=0";//2. 發送請求, 獲取數據String topNewsJsonStr = HttpClientUtils.doGet(topNewsUrl);String noTopNewsJsonStr = HttpClientUtils.doGet(noTopNewsUrl);System.out.println(topNewsJsonStr);System.out.println(noTopNewsJsonStr);//3. 解析數據 :parseJson(topNewsJsonStr);parseJson(noTopNewsJsonStr);}// 解析新聞數據private static void parseJson(String newsJsonStr) {} }

2.3 解析新聞數據(json)

// 解析新聞數據private static List<News> parseJson(String newsJsonStr) {//3.1 將字符串json數據轉換為指定的類型: mapGson gson = new Gson();Map<String,Object> map = gson.fromJson(newsJsonStr, Map.class);//3.2 獲取data中數據 : 列表頁中數據List<Map<String,Object>> newsList = (List<Map<String, Object>>) map.get("data");//3.3 遍歷這個列表, 獲取每一個新聞的數據List<News> tencentNewList = new ArrayList<News>();for (Map<String, Object> newsMap : newsList) {//3.3.1 封裝news對象News news = new News();news.setTitle((String)newsMap.get("title"));news.setTime((String)newsMap.get("update_time"));news.setSource((String)newsMap.get("source"));news.setContent((String)newsMap.get("intro"));news.setEditor((String)newsMap.get("source"));news.setDocurl((String)newsMap.get("vurl"));news.setId(idWorker.nextId() +"");tencentNewList.add(news);}return tencentNewList;}

2.4 保存數據

  • 1)創建一個saveNews的方法:
// 保存數據的操作public static void saveNews(List<News> newsList) {for (News news : newsList) {newsDao.saveNews(news);}}
  • 2)在main方法中, 添加保存數據的操作

[外鏈圖片轉存失敗(img-QqZpQhCN-1563093902039)(assets/1557647802086.png)]

2.5 分頁獲取數據

// 執行分頁的方法public static void page(String topNewsUrl,String noTopNewsUrl) throws Exception{//1. 熱點新聞數據的獲取: 只有一頁數據//1.1 發送請求, 獲取數據String topNewsJsonStr = HttpClientUtils.doGet(topNewsUrl);//1.2 解析數據List<News> topNewsList = parseJson(topNewsJsonStr);//1.3 保存數據saveNews(topNewsList);//2. 處理非熱點數據int page = 1;while(true){//2.1 發送請求, 獲取數據String noTopNewsJsonStr = HttpClientUtils.doGet(noTopNewsUrl);//2.2 解析數據List<News> noTopNewsList = parseJson(noTopNewsJsonStr);if(noTopNewsList == null){break;}//2.3 保存數據saveNews(noTopNewsList);//2.4 獲取下一頁urlnoTopNewsUrl = "https://pacaio.match.qq.com/irs/rcd?cid=146&token=49cbb2154853ef1a74ff4e53723372ce&ext=ent&page="+page;//2.5 自增 +1page++;System.out.println(page);}}
  • 過濾一些視頻的鏈接: 在parseJson的方法中過濾的

[外鏈圖片轉存失敗(img-2w8NM4Ey-1563093902040)(assets/1557648803513.png)]

2.6 去重處理

  • 1)在獲取docurl后, 需要判斷, 這個url是否已經爬取過: parseJson方法中
    • 不需要在執行封裝的代碼了

[外鏈圖片轉存失敗(img-VMMqN2G9-1563093902040)(assets/1557649544185.png)]

  • 2)在保存數據之前, 再次進行判斷, 在保存之后, 將爬取過的url存儲到redis中

[外鏈圖片轉存失敗(img-D2GGal1g-1563093902040)(assets/1557649615117.png)]

2.7 整體騰訊爬蟲:

package com.itheima.spider.tencent;import com.google.gson.Gson; import com.itheima.spider.dao.NewsDao; import com.itheima.spider.pojo.News; import com.itheima.spider.utils.HttpClientUtils; import com.itheima.spider.utils.IdWorker; import com.itheima.spider.utils.JedisUtils; import redis.clients.jedis.Jedis;import java.util.ArrayList; import java.util.List; import java.util.Map;// 騰訊娛樂新聞的爬蟲 public class TencentNewsSpider {private static IdWorker idWorker = new IdWorker(0,2);private static NewsDao newsDao = new NewsDao();public static void main(String[] args) throws Exception{//1. 確定首頁urlString topNewsUrl = "https://pacaio.match.qq.com/irs/rcd?cid=137&token=d0f13d594edfc180f5bf6b845456f3ea&ext=ent&num=60";String noTopNewsUrl = "https://pacaio.match.qq.com/irs/rcd?cid=146&token=49cbb2154853ef1a74ff4e53723372ce&ext=ent&page=0";//2. 執行分頁:page(topNewsUrl,noTopNewsUrl);}// 執行分頁的方法public static void page(String topNewsUrl,String noTopNewsUrl) throws Exception{//1. 熱點新聞數據的獲取: 只有一頁數據//1.1 發送請求, 獲取數據String topNewsJsonStr = HttpClientUtils.doGet(topNewsUrl);//1.2 解析數據List<News> topNewsList = parseJson(topNewsJsonStr);//1.3 保存數據saveNews(topNewsList);//2. 處理非熱點數據int page = 1;while(true){//2.1 發送請求, 獲取數據String noTopNewsJsonStr = HttpClientUtils.doGet(noTopNewsUrl);//2.2 解析數據List<News> noTopNewsList = parseJson(noTopNewsJsonStr);if(noTopNewsList == null){break;}//2.3 保存數據saveNews(noTopNewsList);//2.4 獲取下一頁urlnoTopNewsUrl = "https://pacaio.match.qq.com/irs/rcd?cid=146&token=49cbb2154853ef1a74ff4e53723372ce&ext=ent&page="+page;//2.5 自增 +1page++;System.out.println(page);}}// 保存數據的操作 : 騰訊返回數據的時候, 就會有重復的數據public static void saveNews(List<News> newsList) {Jedis jedis = JedisUtils.getJedis();for (News news : newsList) {// ###################去重處理########################Boolean flag = jedis.sismember("bigData:spider:tencentSpider:docurl", news.getDocurl());if(flag){// 如果為true, 表示已經存在, 已經爬取過了continue;}// ###################去重處理########################newsDao.saveNews(news);// 保存數據之后, 將url保存到redis中//###################去重處理########################jedis.sadd("bigData:spider:tencentSpider:docurl",news.getDocurl());//###################去重處理########################}jedis.close();}// 解析新聞數據private static List<News> parseJson(String newsJsonStr) {//3.1 將字符串json數據轉換為指定的類型: mapGson gson = new Gson();Map<String,Object> map = gson.fromJson(newsJsonStr, Map.class);//獲取一下, 本次獲取了多少條數據Double datanum = (Double) map.get("datanum");if(datanum.intValue() == 0){return null;}//3.2 獲取data中數據 : 列表頁中數據List<Map<String,Object>> newsList = (List<Map<String, Object>>) map.get("data");//3.3 遍歷這個列表, 獲取每一個新聞的數據List<News> tencentNewList = new ArrayList<News>();for (Map<String, Object> newsMap : newsList) {String docurl = (String) newsMap.get("vurl");if(docurl.contains("video")){continue;}//######################去重處理############################33Jedis jedis = JedisUtils.getJedis();Boolean flag = jedis.sismember("bigData:spider:tencentSpider:docurl", docurl);jedis.close();if(flag){// 如果為true, 表示已經存在, 已經爬取過了continue;}//######################去重處理############################33//3.3.1 封裝news對象News news = new News();news.setTitle((String)newsMap.get("title"));news.setTime((String)newsMap.get("update_time"));news.setSource((String)newsMap.get("source"));news.setContent((String)newsMap.get("intro"));news.setEditor((String)newsMap.get("source"));news.setDocurl(docurl);news.setId(idWorker.nextId() +"");tencentNewList.add(news);System.out.println(docurl);}return tencentNewList;} }

3. 梳理整個爬蟲的流程

3.1 163娛樂爬蟲的流程

[外鏈圖片轉存失敗(img-w1tjv4By-1563093902041)(assets/1557652264866.png)]

3.2 騰訊娛樂爬蟲的流程

[外鏈圖片轉存失敗(img-je6CPrCj-1563093902041)(assets/1557652742929.png)]

jedis.close();if(flag){// 如果為true, 表示已經存在, 已經爬取過了continue;}//######################去重處理############################33//3.3.1 封裝news對象News news = new News();news.setTitle((String)newsMap.get("title"));news.setTime((String)newsMap.get("update_time"));news.setSource((String)newsMap.get("source"));news.setContent((String)newsMap.get("intro"));news.setEditor((String)newsMap.get("source"));news.setDocurl(docurl);news.setId(idWorker.nextId() +"");tencentNewList.add(news);System.out.println(docurl);}return tencentNewList;} }

總結

以上是生活随笔為你收集整理的Java爬虫实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。