首頁>技術>

好久沒更新了,今天辦完房子裝修手續,有點空咱們更新一下。

今天更新的內容是以前工作中採集資料的時候遇到的,目前我遇到的透過EventSource方式給前端提供資料的方式比較少,只見過這一種但是這種方式感覺還是有很多優勢。

我們開始之前先看一下這幾個問題。

資料爬取遇到EventStream是個什麼東西?

在一次採集資料的過程中遇到這樣一幕,一般我們的請求都是http,請求結束以後就釋放連線,耗時也很低,大部分我們很容易發現呼叫的介面就直接獲取資料了,但是我在本次採集中沒有找到相關的資料介面,這就有些納悶了,我就想她是如何提供資料的呢?接著我想他肯定是用了websocket或dwr技術推送給前端資料,我就檢視相關頁面原始碼最後也沒找到,開啟除錯以後發現有一個特別耗時的連結,引起了我的注意。我就跟進去了,如下圖:

EventSource方式獲取資料

正常http請求

看到這裡我發現這裡的返回是怎麼不想其他的請求,我找了個http連結對比了一下發現返回內容在EventStream 中,恩這次採集果然和以前的都不同,以前要麼是資料介面,要麼解析頁面,要麼接通websocket,這次來了個EventStream ,在這之前我確實沒見過,於是乎我網上開始百度了一下原來是html5裡的EventSource。w3cshool介紹如下:

HTML5 伺服器傳送事件(Server-Sent Events)

HTML5 伺服器傳送事件(server-sent event)允許網頁獲得來自伺服器的更新。

Server-Sent 事件 - 單向訊息傳遞

Server-Sent 事件指的是網頁自動獲取來自伺服器的更新。

以前也可能做到這一點,前提是網頁不得不詢問是否有可用的更新。透過伺服器傳送事件,更新能夠自動到達。

例子:Facebook/Twitter 更新、股價更新、新的博文、賽事結果等。

透過描述我們可以知道他可以接受伺服器向客戶端推送消流,即完成資料的推送,那麼資料推送我們可以用輪詢、websocket、wdr、Comet, Ajax推送, 反向Ajax, HTTP流等等方式實現,SSE是不同的技術,Server-Sent的特性是單向接收,自動接收,與其他接收方式都不同。

EventSource與websocket有何區別?

他們都能實現服務端向客戶端推送資料,SSE用於web應用程式重新整理資料,不需要使用者做任何動作。WebSockets是實現服務端更加複雜的技術,但它是真的全雙工socket, 服務端能推送資料到客戶端,客戶端也能推送資料回服務端。SSE工作於存在HTTP/HTTPS協議,支援代理伺服器與認證技術。SSE是文字協議你能輕易地除錯它。如果你需要傳送大部二進位制資料從服務端到客戶端,WebSocket是更好的選擇。如果要雙向互動也選用websocket較好。w3cshool中描述,獲取股價等資訊,顯然EventSource是更好的選擇。

WebSocket基於TCP協議,EventSource基於http協議。EventSource是單向通訊,而websocket是雙向通訊。EventSource只能傳送文字,而websocket支援傳送二進位制資料。在實現上EventSource比websocket更簡單。EventSource有自動重連線(不借助第三方)以及傳送隨機事件的能力。websocket的資源佔用過大EventSource更輕量。websocket可以跨域,EventSource基於http跨域需要服務端設定請求頭Java後臺如何獲取爬取資料併入庫?

前面說了半天廢話,總之EventSource的資料我們需要爬取,而且他能實現資料的推送知道這兩點就可以了。關於前端怎麼呼叫我們直接跳過,如果有和作者一樣不知道怎麼寫得直接上w3cshool,上面有你想要的相關資訊,我們接下來重點就看這個資料我們如何採集

我們要知道如何採集這個資料,就應該知道這個資料後臺傳送的原理是什麼。首先他肯定是一個數據連線的請求,

從前端的連結程式碼我們可以看到她定義了一個後端的服務地址,也就是我們的請求地址,緊接著就會接收到後臺源源不斷推送過來的資料。明白了這點我們就直接透過程式碼傳送模擬請求是不是就可以獲取資料了?根據這個思路我們獲取資料就可以了。

前端呼叫程式碼如下圖

我們看到上圖提示的程式碼是用php寫的,我們用java寫一個推送的,大概就是這樣

response.setContentType("text/event-stream"); //這裡最重要,定義資料格式response.setCharacterEncoding("UTF-8"); try { PrintWriter writer = response.getWriter(); writer.write("data: 測試資料,測試資料,測試資料 \n\n");//這裡需要\n\n,必須要,不然前臺接收不到值,鍵必須為datawriter.flush(); Thread.sleep(3000); } catch (Exception e) { e.printStackTrace(); }

那麼以上java程式碼就相當於我們模擬的一個推送資料服務,也就是說這個資料其實就是個資料輸出流,只要進入服務就相當於一個長連線,服務端不關閉那麼就可以一直推送資料,根據這個思路我們寫一個接收程式:

思路:

1.建立請求

2.模擬前端請求,模擬請求驗證引數

3.透過while迴圈讀取資料

4.讀取資料處理

5.資料入庫,程式碼大概如下

URL realUrl = new URL(url);realUrl.openConnection().setConnectTimeout(30*60*60*1000);realUrl.openConnection().setReadTimeout(30*60*60*1000);// 開啟和URL之間的連線URLConnection conn = realUrl.openConnection();// 設定通用的請求屬性conn.setRequestProperty("accept", "*/*");conn.setRequestProperty("connection", "Keep-Alive");conn.setRequestProperty("user-agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36");conn.setRequestProperty("Host", "www.abc.cn");conn.setRequestProperty("Pragma", "no-cache");conn.setRequestProperty("Cache-Control", "no-cache");conn.setRequestProperty("Referer", "http://xxx/index.html");conn.setRequestProperty("Accept-Encoding", " gzip, deflate, sdch");conn.setRequestProperty("Cookie", "+cHCtySezP+hV83LD+/nIFk4h+DnX3JUe0B7f");

// 傳送POST請求必須設定如下兩行conn.setDoOutput(true);conn.setDoInput(true);// 獲取URLConnection物件對應的輸出流out = new PrintWriter(conn.getOutputStream());// 傳送請求引數out.print(param);// flush輸出流的緩衝out.flush();// 定義BufferedReader輸入流來讀取URL的響應in = new BufferedReader(new InputStreamReader(conn.getInputStream()));String line;

String clum ="latitude,longitude,intens,slope,error,location,minisecond,province,"+ "district,country,usedids,cg_ic,height,datetime,hour,minute,second";//獲取欄位

StringBuffer sb=new StringBuffer();sb.append("insert into thunder ("+clum+")");sb.append(" values("+BaseDao.buildQuestionMarkParam(clum.split(",").length)+")");while ((line = in.readLine()) != null) {String str=line.replace("data: ", "").toLowerCase();str=new String(str.getBytes(),"UTF-8");ThunderModel json = JSON.parseObject(str, ThunderModel.class);//解析資料BaseDao.batch(sb.toString(), JSON.parseArray(JSON.toJSONString(json.getM().get(0).getA())), clum);//資料入庫System.out.println("採集成功");}} catch (Exception e) {System.out.println("傳送 POST 請求出現異常!"+e);e.printStackTrace();System.out.println("正在嘗試重啟,如果啟動失敗,請手動啟動");startThreadData();//出錯後重啟服務}//使用finally塊來關閉輸出流、輸入流finally{try{if(out!=null){out.close();}if(in!=null){in.close();}}catch(IOException ex){ex.printStackTrace();}}

入庫呼叫程式碼採用QueryRunner封裝

5
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 全網最簡我的世界Minecraft搭建Python程式設計環境