由於九月事件把爬蟲推到風口浪尖
而我寫這些只是分享技術
不涉及隱私等個人資料的獲取
並且是在不會對對方服務器造成壓力的情況下進行的爬取
特此聲明
36Kr 也叫36氪,是一個我非常喜歡的網站,網羅天下資訊,而且頁面整潔資訊一目瞭然,極大的開拓眼界,許多不管是金融方面科技方面我感覺是最新最全面,當然最終是準備爬取一下上面的資訊,當然是不會對對方服務器造成壓力的情況下進行的爬取.
一.所需材料,涉及技術
-
java
-
jsoup 爬取方法
-
sql 數據庫
-
一個可愛的腦子
-
當然還需要對H5結構的熟悉瞭解,以及json層次結構
分析數據源的方法我寫過詳細的博客,這裏就不詳細說明數據的獲取方式了.
詳情參考:([java爬蟲]常用網頁接口查找方法)這篇博客
這裏就直接粘貼數據接口
https://36kr.com/api/newsflash?b_id=AAAA&per_page=BBBB
主要是b_id&per_page的參數
但要記住per_page的值不能超過30
因爲訪問的數量越多,後臺就需要讀取大量數據進行組裝,消耗大量資源,切記不能對對方服務器造成壓力的情況下進行爬取
因爲訪問的數量越多,後臺就需要讀取大量數據進行組裝,消耗大量資源,切記不能對對方服務器造成壓力的情況下進行爬取
因爲訪問的數量越多,後臺就需要讀取大量數據進行組裝,消耗大量資源,切記不能對對方服務器造成壓力的情況下進行爬取
例子
如b_id=10005&per_page=5
新聞從id爲10005開始,返回5條數據
10005,10004,10003,10002,10001
五條數據
代碼部分會寫如何獲取最新的新聞數據方法
下面是真實數據
{"code":0,
"timestamp":1571904380,
"timestamp_rt":1571904380,
"data":{"items":[
{
"id":187910,
"project_id":1,
"column_id":72,
"post_id":null,
"is_top":0,
"pin":0,
"title":"金柚網2019人力資源產業生態論壇在杭舉辦",
"catch_title":"",
"description":"36氪獲悉,2019中國(浙江)人力資源服務博覽會開幕,來自全國的120家人力資源機構參展。在金柚網“重塑·創新·激活人效·智享未來” 2019人力資源產業生態論壇上,金柚網助理總裁兼產品發展部總監陳鴻飛表示,數字化將在數據沉澱、效率提升、智能決策與交付提升方面顯著提升人力資源服務質量與水平,金柚網將以“AI+人力資源”爲發展動能,持續打造數字化人力資源全流程服務平臺。",
"cover":"",
"news_url_type":"",
"news_url":"",
"user_id":16754887,
"published_at":"2019-10-24 15:10:44",
"created_at":"2019-10-24 15:10:44",
"updated_at":"2019-10-24 15:10:44",
"counters":{"view_count":13,
"pv":12,
"pv_mobile":0,
"pv_app":1,
"comment":0},
"extraction_tags_arr":[],
"extraction_tags":"[]",
"column":{
"id":72,
"name":"其他",
"bg_color":"#000000",
"type":"normal"
},"db_counters":[{"id":287449590,
"entity_type":"newsflash",
"entity_id":187910,
"count_type":"favorite",
"key":"kr_newssite_counter:newsflash_187910_favorite",
"value":1,
"created_at":"2019-10-24 15:28:00",
"updated_at":"2019-10-24 15:28:00",
"entity_id_old":null
},{
"id":287441265,
"entity_type":"newsflash",
"entity_id":187910,
"count_type":"pv",
"key":"kr_newssite_counter:newsflash_187910_pv",
"value":12,
"created_at":"2019-10-24 15:14:51",
"updated_at":"2019-10-24 15:49:07",
"entity_id_old":null
},{
"id":287449996,
"entity_type":"newsflash",
"entity_id":187910,
"count_type":"pv_app",
"key":"kr_newssite_counter:newsflash_187910_pv_app",
"value":1,
"created_at":"2019-10-24 15:28:34",
"updated_at":"2019-10-24 15:28:34",
"entity_id_old":null}],
"user":{
"id":16754887,
"name":"李欣",
"avatar_url":""
},"news_url_title":"",
"station_info":null
},{
"id":187909,
"project_id":1,
"column_id":72,
"post_id":null,
"is_top":0,
"pin":0,
"title":"金柚網2019人力資源產業生態論壇在杭舉辦",
"catch_title":"",
"description":"36氪獲悉,2019中國(浙江)人力資源服務博覽會開幕,來自全國的120家人力資源機構參展。在金柚網“重塑·創新·激活人效·智享未來” 2019人力資源產業生態論壇上,金柚網助理總裁兼產品發展部總監陳鴻飛表示,數字化將在數據沉澱、效率提升、智能決策與交付提升方面顯著提升人力資源服務質量與水平,金柚網將以“AI+人力資源”爲發展動能,持續打造數字化人力資源全流程服務平臺。",
"cover":"",
"news_url_type":"news_url",
"news_url":"http://baijiahao.baidu.com/s?id=1648179606039764976&wfr=spider&for=pc",
"user_id":16754887,
"published_at":"2019-10-24 14:56:29",
"created_at":"2019-10-24 14:56:29",
"updated_at":"2019-10-24 14:56:29",
"counters":{
"view_count":39,
"pv":39,
"pv_mobile":0,
"pv_app":0,
"comment":0},
"extraction_tags_arr":[],
"extraction_tags":"[]",
"column":{
"id":72,
"name":"其他",
"bg_color":"#000000",
"type":"normal"},
"db_counters":[
{"id":287430436,
"entity_type":"newsflash",
"entity_id":187909,
"count_type":"pv",
"key":"kr_newssite_counter:newsflash_187909_pv",
"value":39,
"created_at":"2019-10-24 14:58:21",
"updated_at":"2019-10-24 15:58:10",
"entity_id_old":null
},{
"user":{
"id":16754887,
"name":"李欣",
"avatar_url":""},
"news_url_title":"原文鏈接",
"station_info":null
},{
]
}
}
接口返回json格式數據
數據比較多,涉及到的參數也比較詳細
這裏就需要對json格式比較熟悉可以快速的進行數據篩選
對這種數據進行篩選的方法有很多,也有很多便利的方法
我這裏就使用java 自帶的String中的方法
由於是使用json格式所以新聞存儲在List<Map<String,String>>格式裏面
使用的"},{"進行分隔
對獲取到的數據用.split()方法,分割出來
下面是代碼
首先是如何獲取到最新的新聞
https://36kr.com/api/newsflash?b_id=AAAA&per_page=BBBB
接口需要兩個值,一個是從那條新聞開始獲取,一個是獲取幾條數據
所以獲取最新的新聞就需要獲取最新的新聞的ID
/**
* 當前最新的新聞ID
* @return 返回 int 類型 的id
*/
public int newID() {
int front = 0;
int later = 0;
String textno1 = "";
String newsURL = "https://36kr.com/newsflashes";
try {
// 爬取方法(每個人獲取數據的方法不同,所以就不具體寫爬取方法了)
String information = Getinformation(newsURL);
front = information.indexOf("newsflashList");
textno1 = information.substring(front);
front = textno1.indexOf("id");
later = textno1.indexOf("project_id");
textno1 = textno1.substring(front + 4, later - 2);
front = Integer.parseInt(textno1);
} catch (Exception e) {
e.printStackTrace();
} finally {
return front;
}
}
之後就可以根據自己需要填寫需要返回的新聞條數
如果是定時任務獲取數據可以先獲取最新id,在獲取數據庫內最新的新聞id,做差值
得到距離上次爬取新生成的新聞數
來準確的獲取新生成的數據,節省時間,節省資源
再貼一份有關數據庫做差獲取新聞方法
/**
* 處理並返回新網址
* @param NEWID 頁面最新ID
* @param SQLID 數據庫最新ID
* @return
*/
public String newurl(int SQLID, int NEWID) {
String http = "https://36kr.com/api/newsflash?b_id=AAAA&per_page=BBBB";
String BBBB = "";
if (SQLID == 0) {
BBBB = "30";
} else {
BBBB = String.valueOf(NEWID - SQLID);
}
http = http.replace("AAAA", String.valueOf(NEWID));
http = http.replace("BBBB", BBBB);
return http;
}
當有了接口鏈接就可以進行獲取數據了
數據分割方法
/**
* 數據分割方法
* @param information 源碼
* @return 分割後的集合
*/
public List roughsaix(String information) {
List<String> list = new ArrayList<String>();
try {
String[] Array = information.split("\\}\\,\\{");// 拆分爲String數組
for (int i = 0; i < Array.length; i++) {
list.add(Array[i]);// 轉化爲集合
}
} catch (Exception e) {
e.printStackTrace();
} finally {
return list;
}
}
數據篩選方法
/**
* 數據篩選方法
將剛剛分割後的數據傳入
* @param Clist
* @return 返回整理好的數據List<Map<String, Object>>集合
*/
public List<Map<String, Object>> ScreenText(List<String> Clist) {
List<Map<String, Object>> listmap = new ArrayList<Map<String, Object>>();
int front;
int later;
// 所提取的值
String time;// created_at
String ID;// id
String title;// title
String summary;// summary
String newsurl;
// 記錄當前爬取詳情
try {
for (String information : Clist) {
Map<String, Object> map = new HashMap<String, Object>();
front = information.indexOf("title\":\"");
later = information.indexOf("catch_title");
if (front != -1 && later != -1) { // 判斷是否爲要爬取的目標
// title
title = information.substring(front + 8, later - 3);
front = information.indexOf("id\":");
later = information.indexOf("project_id");
// ID
ID = information.substring(front + 4, later - 2);
front = information.indexOf("description");
later = information.indexOf("cover");
// summary
summary = information.substring(front + 14, later - 3);
// url
front = information.indexOf("\"news_url\":\"http");
later = information.indexOf("user_id");
if (front != -1) {
newsurl = information.substring(front + 12, later - 3);
} else {
newsurl = null;
}
front = information.indexOf("created_at");
later = information.indexOf("updated_at");
// time
time = information.substring(front + 13, later - 3);
map.put("id", ID);// 數據id
map.put("url", url);// 外部鏈接
map.put("title", title);// 存儲標題
map.put("text", summary);// 新聞主體
map.put("time", time);// 新聞時間
//保存 也可以直接入庫
listmap.add(map);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
return listmap;
}
}
最後將數據入庫,結束
可以在服務器裏設置定時任務,每半個小時獲取一次新聞,保存入庫
也可以在入庫之後發送給自己的手機,